diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/CREDITS linux/CREDITS
--- linux.orig/CREDITS	2002-08-03 00:39:42.000000000 +0000
+++ linux/CREDITS	2002-08-12 22:14:06.000000000 +0000
@@ -704,6 +704,11 @@
 S: Warrendale, Pennsylvania 15086
 S: USA
 
+N: Martin Devera
+E: devik@cdi.cz
+W: http://luxik.cdi.cz/~devik/qos/
+D: HTB qdisc and random networking hacks
+
 N: Alex deVries
 E: adevries@thepuffingroup.com
 D: Various SGI parts, bits of HAL2 and Newport, PA-RISC Linux.
@@ -1329,6 +1334,12 @@
 S: Provo, Utah 84606-5607
 S: USA
 
+N: Marcel Holtmann
+E: marcel@holtmann.org
+W: http://www.holtmann.org
+D: Author of the Linux Bluetooth Subsystem PC Card drivers
+S: Germany
+
 N: Rob W. W. Hooft
 E: hooft@EMBL-Heidelberg.DE
 D: Shared libs for graphics-tools and for the f2c compiler
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/Configure.help linux/Documentation/Configure.help
--- linux.orig/Documentation/Configure.help	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/Configure.help	2002-08-12 22:14:26.000000000 +0000
@@ -2,10 +2,7 @@
 #	Eric S. Raymond <mailto:esr@thyrsus.com>
 #	Steven Cole <mailto:elenstev@mesatop.com>
 #
-# Version 3.00: current with 2.4.19
-#
-# This version of the Linux kernel configuration help texts
-# corresponds to kernel versions 2.4.x and 2.5.x.
+# Version 3.01: current with 2.4.19+
 #
 # Translations of this file available on the WWW:
 #
@@ -376,6 +373,12 @@
   Select this if you have a 32-bit processor and more than 4
   gigabytes of physical RAM.
 
+HIGHMEM I/O support
+CONFIG_HIGHIO
+  If you want to be able to do I/O to high memory pages, say Y.
+  Otherwise low memory pages are used as bounce buffers causing a
+  degrade in performance.
+
 Normal floppy disk support
 CONFIG_BLK_DEV_FD
   If you want to use the floppy disk drive(s) of your PC under Linux,
@@ -534,6 +537,17 @@
 
   If unsure, say N.
 
+Per partition statistics in /proc/partitions
+CONFIG_BLK_STATS
+  If you say yes here, your kernel will keep statistical information
+  for every partition. The information includes things as numbers of
+  read and write accesses, thenumber of merged requests etc.
+
+  This is required for the full functionality of sar(8) and interesting
+  if you want to do performance tuning, by tweaking the elevator, e.g.
+
+  If unsure, say N.
+
 ATA/IDE/MFM/RLL support
 CONFIG_IDE
   If you say Y here, your kernel will be able to manage low cost mass
@@ -1067,10 +1081,10 @@
   This effect can be also invoked by calling "idex=ata66"
   If unsure, say N.
 
-CMD64X chipset support
+CMD64X and CMD680 chipset support
 CONFIG_BLK_DEV_CMD64X
   Say Y here if you have an IDE controller which uses any of these
-  chipsets: CMD643, CMD646, or CMD648.
+  chipsets: CMD643, CMD646, CMD648, CMD649 or CMD680.
 
 CY82C693 chipset support
 CONFIG_BLK_DEV_CY82C693
@@ -2493,6 +2507,17 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+skb->pkt_type packet match support
+CONFIG_IP_NF_MATCH_PKTTYPE
+  This patch allows you to match packet in accrodance
+  to its "class", eg. BROADCAST, MULTICAST, ...
+  
+  Typical usage:
+  iptables -A INPUT -m pkttype --pkt-type broadcast -j LOG
+  
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
 MAC address match support
 CONFIG_IP_NF_MATCH_MAC
   MAC matching allows you to match packets based on the source
@@ -2543,6 +2568,28 @@
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt.  If unsure, say `N'.
 
+DSCP match support
+CONFIG_IP_NF_TARGET_DSCP
+  This option adds a `DSCP' match, which allows you to match against
+  the IPv4 header DSCP field (DSCP codepoint).
+
+  The DSCP codepoint can have any value between 0x0 and 0x4f.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+ 
+
+ECN match support
+CONFIG_IP_NF_MATCH_ECN
+  This option adds a `ECN' match, which allows you to match against
+  the IPv4 and TCP header ECN fields.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+ 
+
 TOS match support
 CONFIG_IP_NF_MATCH_TOS
   TOS matching allows you to match packets based on the Type Of
@@ -2551,6 +2598,18 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+conntrack match support
+CONFIG_IP_NF_MATCH_CONNTRACK
+  This is a general conntrack match module, a superset of the state match.
+
+  It allows matching on additional conntrack information, which is
+  useful in complex configurations, such as NAT gateways with multiple
+  internet links or tunnels.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+
 Connection state match support
 CONFIG_IP_NF_MATCH_STATE
   Connection state matching allows you to match packets based on their
@@ -2668,6 +2727,36 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+DSCP target support
+CONFIG_IP_NF_TARGET_DSCP
+  This option adds a `DSCP' target, which allows you to create rules in
+  the iptables mangle table. The selected packet has the DSCP field set
+  to the hex value provided on the command line; unlike the TOS target
+  which will only set the legal values within ip.h.
+
+  The DSCP field can be set to any value between 0x0 and 0x4f. It does
+  take into account that bits 6 and 7 are used by ECN.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+ 
+
+ECN target support
+CONFIG_IP_NF_TARGET_ECN
+  This option adds a `ECN' target, which can be used in the iptables mangle
+  table.  
+
+  You can use this target to remove the ECN bits from the IPv4 header of
+  an IP packet.  This is particularly useful, if you need to work around
+  existing ECN blackholes on the internet, but don't want to disable
+  ECN support in general.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
+ 
+
 TOS target support
 CONFIG_IP_NF_TARGET_TOS
   This option adds a `TOS' target, which allows you to create rules in
@@ -2714,6 +2803,14 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+Helper match support
+CONFIG_IP_NF_MATCH_HELPER
+  Helper matching allows you to match packets in dynamic connections
+  tracked by a conntrack-helper, ie. ip_conntrack_ftp
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `Y'.
+
 TCPMSS match support
 CONFIG_IP_NF_MATCH_TCPMSS
   This option adds a `tcpmss' match, which allows you to examine the
@@ -2766,6 +2863,15 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+EUI64 address check (EXPERIMENTAL)
+CONFIG_IP6_NF_MATCH_EUI64
+  This module performs checking on the IPv6 source address
+  Compares the last 64 bits with the EUI64 (delivered
+  from the MAC address) address
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
 MAC address match support
 CONFIG_IP6_NF_MATCH_MAC
   mac matching allows you to match packets based on the source
@@ -2774,6 +2880,14 @@
   If you want to compile it as a module, say M here and read
   <file:Documentation/modules.txt>.  If unsure, say `N'.
 
+length match support
+CONFIG_IP6_NF_MATCH_LENGTH
+  This option allows you to match the length of a packet against a
+  specific value or range of values.
+
+  If you want to compile it as a module, say M here and read
+  Documentation/modules.txt.  If unsure, say `N'.
+
 Netfilter MARK match support
 CONFIG_IP6_NF_MATCH_MARK
   Netfilter mark matching allows you to match packets based on the
@@ -9558,6 +9672,20 @@
   whenever you want).  If you want to compile it as a module, say M
   here and read <file:Documentation/modules.txt>.
 
+CONFIG_NET_SCH_HTB
+  Say Y here if you want to use the Hierarchical Token Buckets (HTB)
+  packet scheduling algorithm for some of your network devices. See
+  URL http://luxik.cdi.cz/~devik/qos/htb/ for complete manual and
+  in-depth articles.
+
+  HTB is very similar to the CBQ regarding its goals however is has 
+  different properties and different algorithm.
+
+  This code is also available as a module called sch_htb.o ( = code
+  which can be inserted in and removed from the running kernel
+  whenever you want).  If you want to compile it as a module, say M
+  here and read <file:Documentation/modules.txt>.
+
 CSZ packet scheduler
 CONFIG_NET_SCH_CSZ
   Say Y here if you want to use the Clark-Shenker-Zhang (CSZ) packet
@@ -10474,12 +10602,14 @@
   in case your mainboard has memory consistency issues.  If unsure,
   say N.
 
-Support for automatic channel equalization
+Support for uncommon RTL-8139 rev. K (automatic channel equalization)
 CONFIG_8139TOO_TUNE_TWISTER
-  This implements a function which might come in handy in case you are
-  using low quality on long cabling. It tries to match the transceiver
-  to the cable characteristics. This is experimental since hardly
-  documented by the manufacturer.  If unsure, say N.
+  This implements a function which might come in handy in case you
+  are using low quality on long cabling. It is required for RealTek
+  RTL-8139 revision K boards, and totally unused otherwise.  It tries
+  to match the transceiver to the cable characteristics. This is
+  experimental since hardly documented by the manufacturer.
+  If unsure, say Y.
 
 Support for older RTL-8129/8130 boards
 CONFIG_8139TOO_8129
@@ -10488,6 +10618,14 @@
   instead of an internal one.  Disabling this option will save some
   memory by making the code size smaller.  If unsure, say Y.
 
+Use older RX-reset method
+CONFIG_8139_OLD_RX_RESET
+  The 8139too driver was recently updated to contain a more rapid
+  reset sequence, in the face of severe receive errors.  This "new"
+  RX-reset method should be adequate for all boards.  But if you
+  experience problems, you can enable this option to restore the
+  old RX-reset behavior.  If unsure, say N.
+
 SiS 900/7016 PCI Fast Ethernet Adapter support
 CONFIG_SIS900
   This is a driver for the Fast Ethernet PCI network cards based on
@@ -13108,9 +13246,9 @@
   The module will be called wacom.o.  If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-Aiptek 8000U tablet support
+Aiptek 6000U/8000U tablet support
 CONFIG_USB_AIPTEK
-  Say Y here if you want to use the USB version of the Aiptek 8000U
+  Say Y here if you want to use the USB version of the Aiptek 6000U/8000U
   tablet.  Make sure to say Y to "Event interface support"
   (CONFIG_INPUT_EVDEV) as well.
 
@@ -13242,7 +13380,6 @@
   inserted in and removed from the running kernel whenever you want).
   The module will be called audio.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
-			
 
 USB Modem (CDC ACM) support
 CONFIG_USB_ACM
@@ -13951,15 +14088,24 @@
   The module will be called rio500.o. If you want to compile it as
   a module, say M here and read <file:Documentation/modules.txt>.
 
-USB Auerswald ISDN device support
-CONFIG_USB_AUERSWALD
-  Say Y here if you want to connect an Auerswald USB ISDN Device
-  to your computer's USB port.
+CONFIG_USB_TIGL
+  If you own a Texas Instruments graphing calculator and use a 
+  TI-GRAPH LINK USB cable (aka SilverLink), then you might be 
+  interested in this driver.
+
+  If you enable this driver, you will be able to communicate with
+  your calculator through a set of device nodes under /dev.
 
   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 auerswald.o. If you want to compile it as
-  a module, say M here and read <file:Documentation/modules.txt>.
+  The module will be called tiglusb.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
+  If you don't know what the SilverLink cable is or what a Texas
+  Instruments graphing calculator is, then you probably don't need this
+  driver.
+
+  If unsure, say N.
 
 Tieman Voyager USB Braille display support
 CONFIG_USB_BRLVOYAGER
@@ -14314,12 +14460,13 @@
 
 Publish some reiserfs-specific info under /proc/fs/reiserfs
 CONFIG_REISERFS_PROC_INFO
-  Create under /proc/fs/reiserfs hierarchy of files, displaying
-  various ReiserFS statistics and internal data on the expense of
-  making your kernel or module slightly larger (+8 KB).  This also
-  increases amount of kernel memory required for each mount.  Almost
-  everyone but ReiserFS developers and people fine-tuning reiserfs or
-  tracing problems should say N.
+  Create under /proc/fs/reiserfs a hierarchy of files, displaying
+  various ReiserFS statistics and internal data at the expense of making
+  your kernel or module slightly larger (+8 KB). This also increases the
+  amount of kernel memory required for each mount by 440 bytes.
+  It isn't useful to average persons, and you probably can't measure the
+  performance cost of it.  If you are fine-tuning reiserfs, say Y,
+  otherwise say N.
 
 Second extended fs support
 CONFIG_EXT2_FS
@@ -15345,9 +15492,11 @@
 
 IBM disk label and partition support
 CONFIG_IBM_PARTITION
-  Say Y here if you would like to be able to read the hard disk
-  partition table format used by IBM DASD disks operating under CMS.
-  Otherwise, say N.
+  You have to say Y here if you would like to be able to read volume 
+  labels of IBM DASD disks. These can be ECKD DASD disks with 
+  compatible disk layout (cdl) and standard Linux disk layout (ldl), 
+  FBA DASD disks and CMS reserved minidisks.
+  Otherwise, say N and you will not be able to access these disks.
 
 ADFS file system support
 CONFIG_ADFS_FS
@@ -17929,20 +18078,6 @@
   computer, say `Y' here to support its built-in watchdog timer
   feature.  See the help for CONFIG_WATCHDOG for discussion.
 
-W83877F Watchdog Timer
-CONFIG_W83877F_WDT
-  This is the driver for the hardware watchdog on the W83877F chipset
-  as used in EMACS PC-104 motherboards (and likely others).  This
-  watchdog simply watches your kernel to make sure it doesn't freeze,
-  and if it does, it reboots your computer after a certain amount of
-  time.
-
-  This driver is also available as a module ( = code which can be
-  inserted in and removed from the running kernel whenever you want).
-  The module is called mixcomwd.o.  If you want to compile it as a
-  module, say M here and read <file:Documentation/modules.txt>.  Most
-  people will say N.
-
 ALi M7101 Watchdog Timer
 CONFIG_ALIM7101_WDT
   This is the driver for the hardware watchdog on the ALi M7101 PMU
@@ -19581,16 +19716,6 @@
   hardware debugging with a logic analyzer and need to see all traffic
   on the bus.
 
-AU1000 serial console
-CONFIG_AU1000_SERIAL_CONSOLE
-  If you have an Alchemy AU1000 processor (MIPS based) and you want
-  to use a console on a serial port, say Y.  Otherwise, say N.
-
-AU1000 serial support
-CONFIG_AU1000_UART
-  If you have an Alchemy AU1000 processor (MIPS based) and you want
-  to use serial ports, say Y.  Otherwise, say N.
-
 AU1000 ethernet controller on SGI MIPS system
 CONFIG_MIPS_AU1000_ENET
   If you have an Alchemy Semi AU1000 ethernet controller
@@ -20283,7 +20408,7 @@
 
 Kernel support for 32-bit ELF binaries
 CONFIG_BINFMT_ELF32
-  This allows you to run 32-bit Linux/ELF binaries on your Ultra.
+  This allows you to run 32-bit Linux/ELF binaries on your machine.
   Everybody wants this; say Y.
 
 Kernel support for 32-bit (ie. SunOS) a.out binaries
@@ -20369,7 +20494,7 @@
 DBRI Lowlevel Driver
 CONFIG_SPARCAUDIO_DBRI
   This driver supports the DBRI audio interface found on the SS10,
-  SS20, Sparcbook 3, and Voyager systems.
+  SS20, LX, Sparcbook 3, and Voyager systems.
 
 Dummy Lowlevel Driver
 CONFIG_SPARCAUDIO_DUMMY
@@ -20436,6 +20561,19 @@
   Say Y here to compile SCO support into the kernel or say M to
   compile it as module (sco.o).
 
+BNEP protocol support
+CONFIG_BLUEZ_BNEP
+  BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
+  emulation layer on top of Bluetooth. BNEP is required for Bluetooth
+  PAN (Personal Area Network).
+
+  To use BNEP, you will need user-space utilities provided in the 
+  BlueZ-PAN package.
+  For more information, see <http://bluez.sourceforge.net>.
+
+  Say Y here to compile BNEP support into the kernel or say M to
+  compile it as module (bnep.o).
+
 HCI UART driver
 CONFIG_BLUEZ_HCIUART
   Bluetooth HCI UART driver.
@@ -20464,18 +20602,9 @@
   Say Y here to compile support for Bluetooth USB devices into the
   kernel or say M to compile it as module (hci_usb.o).
 
-HCI USB firmware download support
-CONFIG_BLUEZ_USB_FW_LOAD
-  Firmware download support for Bluetooth USB devices.
-  This support is required for devices like Broadcom BCM2033.
-
-  HCI USB driver uses external firmware downloader program provided 
-  in BlueFW package.
-  For more information, see <http://bluez.sf.net/>.
-
 HCI USB zero packet support
 CONFIG_BLUEZ_USB_ZERO_PACKET
-  Support for USB zero packets. 
+  Support for USB zero packets.
   This option is provided only as a work around for buggy Bluetooth USB 
   devices. Do _not_ enable it unless you know for sure that your device 
   requires zero packets.
@@ -20494,11 +20623,37 @@
   Bluetooth HCI DTL1 (PC Card) driver.
   This driver provides support for Bluetooth PCMCIA devices with
   Nokia DTL1 interface:
-     Nokia Bluetooth PC Card, Socketcom Bluetooth CF module
+     Nokia Bluetooth Card
+     Socket Bluetooth CF Card
 
   Say Y here to compile support for HCI DTL1 devices into the
   kernel or say M to compile it as module (dtl1_cs.o).
 
+HCI BT3C (PC Card) device driver
+CONFIG_BLUEZ_HCIBT3C
+  Bluetooth HCI BT3C (PC Card) driver.
+  This driver provides support for Bluetooth PCMCIA devices with
+  3Com BT3C interface:
+     3Com Bluetooth Card (3CRWB6096)
+     HP Bluetooth Card
+
+  The HCI BT3C driver uses external firmware loader program provided in
+  the BlueFW package. For more information, see <http://bluez.sf.net>.
+
+  Say Y here to compile support for HCI BT3C devices into the
+  kernel or say M to compile it as module (bt3c_cs.o).
+
+HCI BlueCard (PC Card) device driver
+CONFIG_BLUEZ_HCIBLUECARD
+  Bluetooth HCI BlueCard (PC Card) driver.
+  This driver provides support for Bluetooth PCMCIA devices with
+  Anycom BlueCard interface:
+     Anycom Bluetooth PC Card
+     Anycom Bluetooth CF Card
+
+  Say Y here to compile support for HCI BlueCard devices into the
+  kernel or say M to compile it as module (bluecard_cs.o).
+
 # The following options are for Linux when running on the Hitachi
 # SuperH family of RISC microprocessors.
 
@@ -20931,12 +21086,6 @@
   Hades. This increases the SCSI transfer rates at least ten times
   compared to PIO transfers.
 
-Sun3 NCR5380 OBIO SCSI
-CONFIG_SUN3_SCSI
-  This option will enable support for the OBIO (onboard io) NCR5380
-  SCSI controller found in the Sun 3/50 and 3/60.  Note that this
-  driver does not provide support for VME SCSI boards.
-
 Sun3x ESP SCSI
 CONFIG_SUN3X_ESP
   This option will enable support for the ESP SCSI controller found
@@ -20990,11 +21139,6 @@
   General Linux information on the Sun 3 series (now discontinued)
   is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
 
-Sun3x ESP SCSI driver
-CONFIG_SUN3X_ESP
-  The ESP was an on-board SCSI controller used on Sun 3/80
-  machines.  Say Y here to compile in support for it.
-
 PCMCIA NE2000 and compatibles support
 CONFIG_APNE
   If you have a PCMCIA NE2000 compatible adapter, say Y.  Otherwise,
@@ -21005,19 +21149,6 @@
   want). The module is called apne.o. If you want to compile it as a
   module, say M here and read <file:Documentation/modules.txt>.
 
-Sun3/Sun3x on-board LANCE support
-CONFIG_SUN3LANCE
-  This driver enables support for the on-board LANCE ethernet adapter
-  found on the Sun 3/50, 3/60, and 3/80 workstations.  If you have 
-  one of these workstations, and would like Ethernet, say Y. 
-  Otherwise, say N.
-
-Sun3 on-board Intel 82586 support
-CONFIG_SUN3_82586
-  This driver enables support for the on-board Intel 82586 based Ethernet
-  adapter found on Sun 3/1xx and 3/2xx motherboards.  Note that this driver
-  does not support 82586-based adapters on additional VME boards.
-
 Atari Lance support
 CONFIG_ATARILANCE
   Say Y to include support for several Atari Ethernet adapters based
@@ -22398,7 +22529,7 @@
   IPL device on another question, that pops up, when you select
   CONFIG_IPL.
 
-IPL from a /390 tape unit
+IPL from a S/390 tape unit
 CONFIG_IPL_TAPE
   Select this option if you want to IPL the image from a Tape.
 
@@ -22407,18 +22538,22 @@
   Select this option if you are running under VM/ESA and want 
   to IPL the image from the emulated card reader.
 
-Support for DASD hard disks
-CONFIG_DASD
-  Enable this option if you want to access DASDs directly utilizing
-  S/390s channel subsystem commands. This is necessary for running
-  natively on a single image or an LPAR.
+CONFIG_PFAULT
+  Select this option, if you want to use PFAULT pseudo page fault
+  handling under VM. If running native or in LPAR, this option
+  has no effect. If your VM does not support PFAULT, PAGEEX
+  pseudo page fault handling will be used.
+  Note that VM 4.2 supports PFAULT but has a bug in its
+  implementation that causes some problems.
+  Everybody who wants to run Linux under VM != VM4.2 should select
+  this option.
 
-Enable DASD fast write
-CONFIG_DASD_FAST_IO
-  Enable fast I/O for DASDs. That means that the next I/O command
-  is already issued at interrupt time, if an I/O request is pending.
-  This option gives significant speedup of I/O, because we don't
-  schedule the bottom-halves as often as Intel.
+CONFIG_SHARED_KERNEL
+  Select this option, if you want to share the text segment of the
+  Linux kernel between different VM guests. This reduces memory
+  usage with lots of guests but greatly increases kernel size.
+  You should only select this option if you know what you are
+  doing and want to exploit this feature.
 
 Support for IBM-style disk-labels (S/390)
 CONFIG_S390_PARTITION
@@ -22427,18 +22562,40 @@
   attached to another IBM mainframe operation system (OS/390, 
   VM/ESA, VSE/ESA).
 
+Support for DASD hard disks
+CONFIG_DASD
+  Enable this option if you want to access DASDs directly utilizing
+  S/390s channel subsystem commands. This is necessary for running
+  natively on a single image or an LPAR.
+
 Support for ECKD hard disks
 CONFIG_DASD_ECKD
-  ECKD devices are the most commonly used devices. You should enable
-  this option unless you are very sure you have no ECKD device.
+  ECKD (Extended Count Key Data) devices are the most commonly used 
+  devices on S/390s. You should enable this option unless you are 
+  very sure you have no ECKD device.
 
-CKD devices
-CONFIG_DASD_CKD
-  CKD devices are currently unsupported.
+ECKD demand loading
+CONFIG_DASD_AUTO_ECKD
+  This option enables demand loading of the ECKD module. 
 
 Support for FBA hard disks
 CONFIG_DASD_FBA
-  FBA devices are currently unsupported.
+  Select this option if you want to use FBA (Fixed Block) devices.
+  If you are not sure what it is, say "Y".
+
+FBA demand loading
+CONFIG_DASD_AUTO_FBA
+  This option enables demand loading of the FBA module. 
+
+Support for DIAG access to CMS reserved Disks
+CONFIG_DASD_DIAG
+  Select this option if you want to use CMS reserved Disks under VM
+  with the Diagnose250 command.  If you are not running under VM or
+  unsure what it is, say "N".
+
+DIAG demand loading
+CONFIG_DASD_AUTO_DIAG
+  This option enables demand loading of the DIAG module. 
 
 Merge some code into the kernel to make the image IPLable
 CONFIG_IPLABLE
@@ -22476,6 +22633,16 @@
   Include support for using an IBM HWC line-mode terminal as the Linux
   system console.
 
+Control Program Identification
+CONFIG_HWC_CPI
+  Allows for Control Program Identification via the HWC interface,
+  i.e. provides a mean to pass an OS instance name (system name)
+  to the machine.
+
+  This option should only be selected as a module since the
+  system name has to be passed as module parameter. The module
+  will be called hwc_cpi.o.
+
 S/390 tape device support
 CONFIG_S390_TAPE
   Select this option if you want to access channel-attached tape
@@ -22484,8 +22651,9 @@
   least one of the tape interface options and one of the tape
   hardware options in order to access a tape device.
   This option is also available as a module. The module will be
-  called tape390.o and include all selected interfaces and
-  hardware drivers.
+  called tape390.o and include all selected interfaces.
+  The hardware drivers will be seperate modules.
+  If unsure, say "Y".
 
 Support for tape character devices
 CONFIG_S390_TAPE_CHAR
@@ -22506,14 +22674,23 @@
 
 Support for 3490 tape hardware
 CONFIG_S390_TAPE_3490
-  Select this option if you want to access IBM 3480 magnetic
+  Select this option if you want to access IBM 3490 magnetic
   tape subsystems and 100% compatibles.
+  This option is also available as a module. The module will be
+  called tape3490.o. If CONFIG_S390_TAPE is selected as a module,
+  this hardware driver cannot be built-in but is only available
+  as a module.
   It is safe to say "Y" here.
 
 Support for 3480 tape hardware
 CONFIG_S390_TAPE_3480
-  Select this option if you want to access IBM 3490 magnetic
+  Select this option if you want to access IBM 3480 magnetic
   tape subsystems and 100% compatibles.
+  This option is also available as a module. The module will be
+  called tape3480.o. If CONFIG_S390_TAPE is selected as a module,
+  this hardware driver cannot be built-in but is only available
+  as a module.
+  It is safe to say "Y" here.
 
 CTC device support
 CONFIG_CTC
@@ -22524,12 +22701,6 @@
   available.  This option is also available as a module which will be
   called ctc.o.  If you do not know what it is, it's safe to say "Y".
 
-Support for DIAG access to CMS reserved Disks
-CONFIG_DASD_DIAG
-  Select this option if you want to use CMS reserved Disks under VM
-  with the Diagnose250 command.  If you are not running under VM or
-  unsure what it is, say "N".
-
 XPRAM disk support
 CONFIG_BLK_DEV_XPRAM
   Select this option if you want to use your expanded storage on S/390
@@ -22552,6 +22723,20 @@
   vehicle networking under VM or VIF.  This option is also available
   as a module which will be called iucv.o. If unsure, say "Y".
 
+Process warning machine checks
+CONFIG_MACHCHK_WARNING
+  Select this option if you want the machine check handler on IBM S/390 or 
+  zSeries to process warning machine checks (e.g. on power failures). 
+  If unsure, say "Y".
+
+Use chscs for Common I/O
+CONFIG_CHSC
+  Select this option if you want the s390 common I/O layer to use information
+  obtained by channel subsystem calls. This will enable Linux to process link
+  failures and resource accessibility events. Moreover, if you have procfs
+  enabled, you'll be able to toggle chpids logically offline and online. Even
+  if you don't understand what this means, you should say "Y".
+
 Kernel support for 31 bit ELF binaries
 CONFIG_S390_SUPPORT
   Select this option if you want to enable your system kernel to
@@ -23014,6 +23199,11 @@
   It is recommended to be used on a NetWinder, but it is not a
   necessity.
 
+Check for stack overflows
+CONFIG_DEBUG_STACKOVERFLOW
+  This option make do_IRQ() check for enough stack space beeing left.
+  This is safe to enable.
+
 Debug high memory support
 CONFIG_DEBUG_HIGHMEM
   This options enables addition error checking for high memory systems.
@@ -23542,6 +23732,18 @@
   used by IrTTY.  To activate support for Parallax dongles you will
   have to start irattach like this "irattach -d litelink".
 
+Microchip MCP2120 dongle
+CONFIG_MCP2120_DONGLE
+  Say Y here if you want to build support for the Microchip MCP2120
+  dongle.  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  The MCP2120 dongle attaches to
+  the normal 9-pin serial port connector, and can currently only be
+  used by IrTTY.  To activate support for MCP2120 dongles you will
+  have to insert "irattach -d mcp2120" in the /etc/irda/drivers script.
+
+  You must build this dongle yourself.  For more information see:
+  <http://www.eyetap.org/~tangf/irda_sir_linux.html>
+
 Old Belkin dongle
 CONFIG_OLD_BELKIN_DONGLE
   Say Y here if you want to build support for the Adaptec Airport 1000
@@ -23549,6 +23751,30 @@
   and read <file:Documentation/modules.txt>.  The module will be
   called old_belkin.o.  Some information is contained in the comments
   at the top of <file:drivers/net/irda/old_belkin.c>.
+ 
+ACTiSYS IR-200L dongle (Experimental)
+CONFIG_ACT200L_DONGLE
+  Say Y here if you want to build support for the ACTiSYS IR-200L
+  dongle. If you want to compile it as a module, say M here and read
+  Documentation/modules.txt. The ACTiSYS IR-200L dongle attaches to
+  the normal 9-pin serial port connector, and can currently only be
+  used by IrTTY. To activate support for ACTiSYS IR-200L dongles
+  you will have to start irattach like this: "irattach -d act200l".
+
+Mobile Action MA600 dongle (Experimental)
+CONFIG_MA600_DONGLE
+  Say Y here if you want to build support for the Mobile Action MA600
+  dongle.  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>.  The MA600 dongle attaches to
+  the normal 9-pin serial port connector, and can currently only be
+  tested on IrCOMM.  To activate support for MA600 dongles you will
+  have to insert "irattach -d ma600" in the /etc/irda/drivers script.
+  Note: irutils 0.9.15 requires no modification. irutils 0.9.9 needs
+  modification. For more information, download the following tar gzip
+  file.
+
+  There is a pre-compiled module on
+  <http://engsvr.ust.hk/~eetwl95/download/ma600-2.4.x.tar.gz>
 
 VME (Motorola and BVM) support
 CONFIG_VME
@@ -24526,15 +24752,6 @@
   the IA32 instruction set.  Say Y here to build in kernel support for
   this.  If in doubt, say Y.
 
-/proc/efi/vars support
-CONFIG_EFI_VARS
-  If you say Y here, you are able to get EFI (Extensible Firmware
-  Interface) variable information in /proc/efi/vars.  You may read,
-  write, create, and destroy EFI variables through this interface.
-
-  To use this option, you have to check that the "/proc file system
-  support" (CONFIG_PROC_FS) is enabled, too.
-
 Physical memory granularity (16 MB)
 CONFIG_IA64_GRANULE_16MB
   IA64 identity-mapped regions use a large page size.  We'll call such
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl
--- linux.orig/Documentation/DocBook/kernel-hacking.tmpl	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/DocBook/kernel-hacking.tmpl	2002-08-12 22:14:21.000000000 +0000
@@ -1091,18 +1091,17 @@
    <title>Initializing structure members</title>
 
    <para>
-    The preferred method of initializing structures is to use the
-    gcc Labeled Elements extension, eg:
+    The preferred method of initializing structures is to use
+    designated initialisers, as defined by ISO C99, eg:
    </para>
    <programlisting>
 static struct block_device_operations opt_fops = {
-        open:                   opt_open,
-        release:                opt_release,
-        ioctl:                  opt_ioctl,
-        check_media_change:     opt_media_change,
+        .open               = opt_open,
+        .release            = opt_release,
+        .ioctl              = opt_ioctl,
+        .check_media_change = opt_media_change,
 };
    </programlisting>
-
    <para>
     This makes it easy to grep for, and makes it clear which
     structure fields are set.  You should do this because it looks
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/SubmittingPatches linux/Documentation/SubmittingPatches
--- linux.orig/Documentation/SubmittingPatches	2000-12-04 01:48:18.000000000 +0000
+++ linux/Documentation/SubmittingPatches	2002-08-12 22:14:00.000000000 +0000
@@ -161,7 +161,7 @@
 When sending patches to Linus, always follow step #6.
 
 Large changes are not appropriate for mailing lists, and some
-maintainers.  If your patch, uncompressed, exceeds 40Kb in size,
+maintainers.  If your patch, uncompressed, exceeds 40 kB in size,
 it is preferred that you store your patch on an Internet-accessible
 server, and provide instead a URL (link) pointing to your patch.
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX
--- linux.orig/Documentation/filesystems/00-INDEX	2001-06-20 18:10:27.000000000 +0000
+++ linux/Documentation/filesystems/00-INDEX	2002-08-12 22:14:20.000000000 +0000
@@ -6,6 +6,8 @@
 	- info and mount options for the Acorn Advanced Disc Filing System.
 affs.txt
 	- info and mount options for the Amiga Fast File System.
+befs.txt
+	- info for the BeOS file system (BFS)
 bfs.txt
 	- info for the SCO UnixWare Boot Filesystem (BFS).
 coda.txt
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/filesystems/befs.txt linux/Documentation/filesystems/befs.txt
--- linux.orig/Documentation/filesystems/befs.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/filesystems/befs.txt	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,111 @@
+BeOS filesystem for Linux
+
+Document last updated: Dec 6, 2001
+
+WARNING
+=======
+Make sure you understand that this is alpha software.  This means that the
+implementation is neither complete nor well-tested. 
+
+I DISCLAIM ALL RESPONSIBILTY FOR ANY POSSIBLE BAD EFFECTS OF THIS CODE!
+
+LICENSE
+=====
+This software is covered by the GNU General Public License. 
+See the file COPYING for the complete text of the license.
+Or the GNU website: <http://www.gnu.org/licenses/licenses.html>
+
+AUTHOR
+=====
+Current maintainer: Will Dyson <will_dyson@pobox.com>
+Has been working on the code since Aug 13, 2001. See the changelog for details.
+
+Original Author: Makoto Kato <m_kato@ga2.so-net.ne.jp>
+His orriginal code can still be found at: <http://hp.vector.co.jp/authors/VA008030/bfs/>
+Does anyone know of a more current email address for Makoto? He doesn't respond
+to the address given above...
+
+WHAT IS THIS DRIVER?
+==================
+This module implements the native filesystem of BeOS <http://www.be.com/>
+for the linux 2.4.1 and later kernels. Currently it is a read-only implementation.
+
+Which is it, BFS or BEFS?
+================
+Be, Inc said, "BeOS Filesystem is officially called BFS, not BeFS". 
+But Unixware Boot Filesystem is called bfs, too. And they are already in the
+kernel.
+Because of this nameing conflict, on Linux the BeOS filesystem is called befs.
+
+HOW TO INSTALL
+==============
+step 1.  Install the BeFS  patch into the source code tree of linux.
+
+Apply the patchfile to your kernel source tree.
+Assuming that your kernel source is in /foo/bar/linux and the patchfile is called
+patch-befs-xxx, you would do the following:
+
+	cd /foo/bar/linux
+	patch -p1 < /path/to/patch-befs-xxx
+
+if the patching step fails (i.e. there are rejected hunks), you can try to
+figure it out yourself (it shouldn't be hard), or mail the maintainer 
+(Will Dyson <will_dyson@pobox.com>) for help.
+
+step 2.  Configuretion & make kernel
+
+The linux kernel has many compile-time options. Most of them are beyond the
+scope of this document. I suggest the Kernel-HOWTO document as a good general
+reference on this topic. <http://www.linux.com/howto/Kernel-HOWTO.html>
+
+However, to use the BeFS module, you must enable it at configure time.
+
+	cd /foo/bar/linux
+	make menuconfig (or xconfig)
+
+The BeFS module is not a standard part of the linux kernel, so you must first
+enable support for experimental code under the "Code maturity level" menu.
+
+Then, under the "Filesystems" menu will be an option called "BeFS filesystem (experimental)",
+or something like that. Enable that option (it is fine to make it a module).
+
+Save your kernel configuration and then build your kernel.
+
+step 3.  Install
+
+See the kernel howto <http://www.linux.com/howto/Kernel-HOWTO.html> for
+instructions on this critical step.
+
+USING BFS
+=========
+To use the BeOS filesystem, use filesystem type 'befs'.
+
+ex)
+    mount -t befs /dev/fd0 /beos
+
+MOUNT OPTIONS
+=============
+uid=nnn        All files in the partition will be owned by user id nnn.
+gid=nnn	       All files in the partition will be in group nnn.
+iocharset=xxx  Use xxx as the name of the NLS translation table.
+debug          The driver will output debugging information to the syslog.
+
+HOW TO GET LASTEST VERSION
+==========================
+
+The latest version is currently available at:
+<http://befs-driver.sourceforge.net/>
+
+ANY KNOWN BUGS?
+===========
+As of Jan 20, 2002:
+	
+	None
+
+SPECIAL THANKS
+==============
+Dominic Giampalo ... Writing "Practical file system design with Be filesystem"
+Hiroyuki Yamada  ... Testing LinuxPPC.
+
+
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/ide.txt linux/Documentation/ide.txt
--- linux.orig/Documentation/ide.txt	2001-09-07 16:28:38.000000000 +0000
+++ linux/Documentation/ide.txt	2002-08-12 22:14:05.000000000 +0000
@@ -306,6 +306,9 @@
  "idex=serialize"	: do not overlap operations on idex and ide(x^1)
  "idex=reset"		: reset interface after probe
  "idex=dma"		: automatically configure/use DMA if possible.
+ "idex=nohighio"	: don't use i/o to high memory addresses on this
+			 	interface. i/o to memory locations higher
+				than ~860MiB will be bounced.
 
  The following are valid ONLY on ide0,
  and the defaults for the base,ctl ports must not be altered.
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/00-INDEX linux/Documentation/networking/00-INDEX
--- linux.orig/Documentation/networking/00-INDEX	2001-02-09 00:32:44.000000000 +0000
+++ linux/Documentation/networking/00-INDEX	2002-08-12 22:14:09.000000000 +0000
@@ -44,6 +44,10 @@
 	- the Digi International RightSwitch SE-X Ethernet driver
 dmfe.txt
 	- info on the Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver.
+e100.txt
+	- info on Intel's EtherExpress PRO/100 line of 10/100 boards
+e1000.txt
+	- info on Intel's E1000 line of gigabit ethernet boards
 eql.txt
 	- serial IP load balancing
 ethertap.txt
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/8139too.txt linux/Documentation/networking/8139too.txt
--- linux.orig/Documentation/networking/8139too.txt	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/networking/8139too.txt	2002-08-12 22:14:01.000000000 +0000
@@ -185,9 +185,22 @@
 Change History
 --------------
 
-Version 0.9.23 - January 16, 2002
+Version 0.9.26 - August 9, 2002
 
-* New, compile-time conditional for testing better RX reset
+* Fix MII ioctl phy id corruption.
+* Fix big-endian multicast bug.
+* Support register dumps via ethtool.
+* Fix several uses of 'len' after potential skb free, in dev->hard_start_xmit
+* Replace several "magic numbers" with their proper representation
+  constants in linux/mii.h.
+* Support ethtool media interface via generic kernel MII API
+* Export NIC-specific statistics via ethtool.
+* Proper support for RTL8139 rev K. (can be disabled via
+  compile-time conditional)
+* Add PCI ids for new 8139 boards.
+* Use ethernet crc via generic linux/crc32.h kernel API.
+* Better RX reset.  Old rx-reset method still available via
+  a compile-time conditional.
 * Only account specific RX errors if rx_status is !OK
 
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/NAPI_HOWTO.txt linux/Documentation/networking/NAPI_HOWTO.txt
--- linux.orig/Documentation/networking/NAPI_HOWTO.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/networking/NAPI_HOWTO.txt	2002-08-12 22:13:59.000000000 +0000
@@ -0,0 +1,749 @@
+HISTORY:
+February 16/2002 -- revision 0.2.1:
+COR typo corrected
+February 10/2002 -- revision 0.2:
+some spell checking ;->
+January 12/2002 -- revision 0.1
+This is still work in progress so may change.
+To keep up to date please watch this space.
+
+Introduction to NAPI
+====================
+
+NAPI is a proven (www.cyberus.ca/~hadi/usenix-paper.tgz) technique
+to improve network performance on Linux. For more details please
+read that paper.
+NAPI provides a "inherent mitigation" which is bound by system capacity
+as can be seen from the following data collected by Robert on Gigabit 
+ethernet (e1000):
+
+ Psize    Ipps       Tput     Rxint     Txint    Done     Ndone
+ ---------------------------------------------------------------
+   60    890000     409362        17     27622        7     6823
+  128    758150     464364        21      9301       10     7738
+  256    445632     774646        42     15507       21    12906
+  512    232666     994445    241292     19147   241192     1062
+ 1024    119061    1000003    872519     19258   872511        0
+ 1440     85193    1000003    946576     19505   946569        0
+ 
+
+Legend:
+"Ipps" stands for input packets per second. 
+"Tput" == packets out of total 1M that made it out.
+"txint" == transmit completion interrupts seen
+"Done" == The number of times that the poll() managed to pull all
+packets out of the rx ring. Note from this that the lower the
+load the more we could clean up the rxring
+"Ndone" == is the converse of "Done". Note again, that the higher
+the load the more times we couldnt clean up the rxring.
+
+Observe that:
+when the NIC receives 890Kpackets/sec only 17 rx interrupts are generated. 
+The system cant handle the processing at 1 interrupt/packet at that load level. 
+At lower rates on the other hand, rx interrupts go up and therefore the
+interrupt/packet ratio goes up (as observable from that table). So there is
+possibility that under low enough input, you get one poll call for each
+input packet caused by a single interrupt each time. And if the system 
+cant handle interrupt per packet ratio of 1, then it will just have to 
+chug along ....
+
+
+0) Prerequisites:
+==================
+A driver MAY continue using the old 2.4 technique for interfacing
+to the network stack and not benefit from the NAPI changes.
+NAPI additions to the kernel do not break backward compatibility.
+NAPI, however, requires the following features to be available:
+
+A) DMA ring or enough RAM to store packets in software devices.
+
+B) Ability to turn off interrupts or maybe events that send packets up 
+the stack.
+
+NAPI processes packet events in what is known as dev->poll() method.
+Typically, only packet receive events are processed in dev->poll(). 
+The rest of the events MAY be processed by the regular interrupt handler 
+to reduce processing latency (justified also because there are not that 
+many of them).
+Note, however, NAPI does not enforce that dev->poll() only processes 
+receive events. 
+Tests with the tulip driver indicated slightly increased latency if
+all of the interrupt handler is moved to dev->poll(). Also MII handling
+gets a little trickier.
+The example used in this document is to move the receive processing only
+to dev->poll(); this is shown with the patch for the tulip driver.
+For an example of code that moves all the interrupt driver to 
+dev->poll() look at the ported e1000 code.
+
+There are caveats that might force you to go with moving everything to 
+dev->poll(). Different NICs work differently depending on their status/event 
+acknowledgement setup. 
+There are two types of event register ACK mechanisms.
+	I)  what is known as Clear-on-read (COR).
+	when you read the status/event register, it clears everything!
+	The natsemi and sunbmac NICs are known to do this.
+	In this case your only choice is to move all to dev->poll()
+
+	II) Clear-on-write (COW)
+	 i) you clear the status by writting a 1 in the bit-location you want.
+		These are the majority of the NICs and work the best with NAPI.
+		Put only receive events in dev->poll(); leave the rest in
+		the old interrupt handler.
+	 ii) whatever you write in the status register clears every thing ;->
+		Cant seem to find any supported by Linux which do this. If
+		someone knows such a chip email us please.
+		Move all to dev->poll()
+
+C) Ability to detect new work correctly.
+NAPI works by shutting down event interrupts when theres work and
+turning them on when theres none. 
+New packets might show up in the small window while interrupts were being 
+re-enabled (refer to appendix 2).  A packet might sneak in during the period 
+we are enabling interrupts. We only get to know about such a packet when the 
+next new packet arrives and generates an interrupt. 
+Essentially, there is a small window of opportunity for a race condition
+which for clarity we'll refer to as the "rotting packet".
+
+This is a very important topic and appendix 2 is dedicated for more 
+discussion.
+
+Locking rules and environmental guarantees
+==========================================
+
+-Guarantee: Only one CPU at any time can call dev->poll(); this is because
+only one CPU can pick the initial interrupt and hence the initial
+netif_rx_schedule(dev);
+- The core layer invokes devices to send packets in a round robin format.
+This implies receive is totaly lockless because of the guarantee only that 
+one CPU is executing it.
+-  contention can only be the result of some other CPU accessing the rx
+ring. This happens only in close() and suspend() (when these methods
+try to clean the rx ring); 
+****guarantee: driver authors need not worry about this; synchronization 
+is taken care for them by the top net layer.
+-local interrupts are enabled (if you dont move all to dev->poll()). For 
+example link/MII and txcomplete continue functioning just same old way. 
+This improves the latency of processing these events. It is also assumed that 
+the receive interrupt is the largest cause of noise. Note this might not 
+always be true. 
+[according to Manfred Spraul, the winbond insists on sending one 
+txmitcomplete interrupt for each packet (although this can be mitigated)].
+For these broken drivers, move all to dev->poll().
+
+For the rest of this text, we'll assume that dev->poll() only
+processes receive events.
+
+new methods introduce by NAPI
+=============================
+
+a) netif_rx_schedule(dev)
+Called by an IRQ handler to schedule a poll for device
+
+b) netif_rx_schedule_prep(dev)
+puts the device in a state which allows for it to be added to the
+CPU polling list if it is up and running. You can look at this as
+the first half of  netif_rx_schedule(dev) above; the second half
+being c) below.
+
+c) __netif_rx_schedule(dev)
+Add device to the poll list for this CPU; assuming that _prep above
+has already been called and returned 1.
+
+d) netif_rx_reschedule(dev, undo)
+Called to reschedule polling for device specifically for some
+deficient hardware. Read Appendix 2 for more details.
+
+e) netif_rx_complete(dev)
+
+Remove interface from the CPU poll list: it must be in the poll list
+on current cpu. This primitive is called by dev->poll(), when
+it completes its work. The device cannot be out of poll list at this
+call, if it is then clearly it is a BUG(). You'll know ;->
+
+All these above nethods are used below. So keep reading for clarity.
+
+Device driver changes to be made when porting NAPI
+==================================================
+
+Below we describe what kind of changes are required for NAPI to work.
+
+1) introduction of dev->poll() method 
+=====================================
+
+This is the method that is invoked by the network core when it requests
+for new packets from the driver. A driver is allowed to send upto
+dev->quota packets by the current CPU before yielding to the network
+subsystem (so other devices can also get opportunity to send to the stack).
+
+dev->poll() prototype looks as follows:
+int my_poll(struct net_device *dev, int *budget)
+
+budget is the remaining number of packets the network subsystem on the
+current CPU can send up the stack before yielding to other system tasks.
+*Each driver is responsible for decrementing budget by the total number of
+packets sent.
+	Total number of packets cannot exceed dev->quota.
+
+dev->poll() method is invoked by the top layer, the driver just sends if it 
+can to the stack the packet quantity requested.
+
+more on dev->poll() below after the interrupt changes are explained.
+
+2) registering dev->poll() method
+===================================
+
+dev->poll should be set in the dev->probe() method. 
+e.g:
+dev->open = my_open;
+.
+.
+/* two new additions */
+/* first register my poll method */
+dev->poll = my_poll;
+/* next register my weight/quanta; can be overriden in /proc */
+dev->weight = 16;
+.
+.
+dev->stop = my_close;
+
+
+
+3) scheduling dev->poll()
+=============================
+This involves modifying the interrupt handler and the code
+path which takes the packet off the NIC and sends them to the 
+stack.
+
+it's important at this point to introduce the classical D Becker 
+interrupt processor:
+
+------------------
+static void
+netdevice_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	struct net_device *dev = (struct net_device *)dev_instance;
+	struct my_private *tp = (struct my_private *)dev->priv;
+
+	int work_count = my_work_count;
+        status = read_interrupt_status_reg();
+        if (status == 0)
+                return;         /* Shared IRQ: not us */
+        if (status == 0xffff)
+                return;         /* Hot unplug */
+        if (status & error)
+		do_some_error_handling()
+        
+	do {
+		acknowledge_ints_ASAP();
+
+		if (status & link_interrupt) {
+			spin_lock(&tp->link_lock);
+			do_some_link_stat_stuff();
+			spin_unlock(&tp->link_lock);
+		}
+		
+		if (status & rx_interrupt) {
+			receive_packets(dev);
+		}
+
+		if (status & rx_nobufs) {
+			make_rx_buffs_avail();
+		}
+			
+		if (status & tx_related) {
+			spin_lock(&tp->lock);
+			tx_ring_free(dev);
+			if (tx_died)
+				restart_tx();
+			spin_unlock(&tp->lock);
+		}
+
+		status = read_interrupt_status_reg();
+
+	} while (!(status & error) || more_work_to_be_done);
+
+}
+
+----------------------------------------------------------------------
+
+We now change this to what is shown below to NAPI-enable it:
+
+----------------------------------------------------------------------
+static void
+netdevice_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *)dev_instance;
+	struct my_private *tp = (struct my_private *)dev->priv;
+
+        status = read_interrupt_status_reg();
+        if (status == 0)
+                return;         /* Shared IRQ: not us */
+        if (status == 0xffff)
+                return;         /* Hot unplug */
+        if (status & error)
+		do_some_error_handling();
+        
+	do {
+/************************ start note *********************************/		
+		acknowledge_ints_ASAP();  // dont ack rx and rxnobuff here
+/************************ end note *********************************/		
+
+		if (status & link_interrupt) {
+			spin_lock(&tp->link_lock);
+			do_some_link_stat_stuff();
+			spin_unlock(&tp->link_lock);
+		}
+/************************ start note *********************************/		
+		if (status & rx_interrupt || (status & rx_nobuffs)) {
+			if (netif_rx_schedule_prep(dev)) {
+
+				/* disable interrupts caused 
+			         *	by arriving packets */
+				disable_rx_and_rxnobuff_ints();
+				/* tell system we have work to be done. */
+				__netif_rx_schedule(dev);
+			} else {
+				printk("driver bug! interrupt while in poll\n");
+				/* FIX by disabling interrupts  */
+				disable_rx_and_rxnobuff_ints();
+			}
+		}
+/************************ end note note *********************************/		
+			
+		if (status & tx_related) {
+			spin_lock(&tp->lock);
+			tx_ring_free(dev);
+
+			if (tx_died)
+				restart_tx();
+			spin_unlock(&tp->lock);
+		}
+
+		status = read_interrupt_status_reg();
+
+/************************ start note *********************************/		
+	} while (!(status & error) || more_work_to_be_done(status));
+/************************ end note note *********************************/		
+
+}
+
+---------------------------------------------------------------------
+
+
+We note several things from above:
+
+I) Any interrupt source which is caused by arriving packets is now
+turned off when it occurs. Depending on the hardware, there could be
+several reasons that arriving packets would cause interrupts; these are the
+interrupt sources we wish to avoid. The two common ones are a) a packet 
+arriving (rxint) b) a packet arriving and finding no DMA buffers available
+(rxnobuff) .
+This means also acknowledge_ints_ASAP() will not clear the status
+register for those two items above; clearing is done in the place where 
+proper work is done within NAPI; at the poll() and refill_rx_ring() 
+discussed further below.
+netif_rx_schedule_prep() returns 1 if device is in running state and
+gets successfully added to the core poll list. If we get a zero value
+we can _almost_ assume are already added to the list (instead of not running. 
+Logic based on the fact that you shouldnt get interrupt if not running)
+We rectify this by disabling rx and rxnobuf interrupts.
+
+II) that receive_packets(dev) and make_rx_buffs_avail() may have dissapeared.
+These functionalities are still around actually......
+
+infact, receive_packets(dev) is very close to my_poll() and 
+make_rx_buffs_avail() is invoked from my_poll()
+
+4) converting receive_packets() to dev->poll()
+===============================================
+
+We need to convert the classical D Becker receive_packets(dev) to my_poll()
+
+First the typical receive_packets() below:
+-------------------------------------------------------------------
+
+/* this is called by interrupt handler */
+static void receive_packets (struct net_device *dev)
+{
+
+	struct my_private *tp = (struct my_private *)dev->priv;
+	rx_ring = tp->rx_ring;
+	cur_rx = tp->cur_rx;
+	int entry = cur_rx % RX_RING_SIZE;
+	int received = 0;
+	int rx_work_limit = tp->dirty_rx + RX_RING_SIZE - tp->cur_rx;
+
+	while (rx_ring_not_empty) {
+		u32 rx_status;
+		unsigned int rx_size;
+		unsigned int pkt_size;
+		struct sk_buff *skb;
+                /* read size+status of next frame from DMA ring buffer */
+		/* the number 16 and 4 are just examples */
+                rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+                rx_size = rx_status >> 16;
+                pkt_size = rx_size - 4;
+
+		/* process errors */
+                if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
+                    (!(rx_status & RxStatusOK))) {
+                        netdrv_rx_err (rx_status, dev, tp, ioaddr);
+                        return;
+                }
+
+                if (--rx_work_limit < 0)
+                        break;
+
+		/* grab a skb */
+                skb = dev_alloc_skb (pkt_size + 2);
+                if (skb) {
+			.
+			.
+			netif_rx (skb);
+			.
+			.
+                } else {  /* OOM */
+			/*seems very driver specific ... some just pass
+			whatever is on the ring already. */
+                }
+
+		/* move to the next skb on the ring */
+		entry = (++tp->cur_rx) % RX_RING_SIZE;
+		received++ ;
+
+        }
+
+	/* store current ring pointer state */
+        tp->cur_rx = cur_rx;
+
+        /* Refill the Rx ring buffers if they are needed */
+	refill_rx_ring();
+	.
+	.
+
+}
+-------------------------------------------------------------------
+We change it to a new one below; note the additional parameter in
+the call.
+
+-------------------------------------------------------------------
+
+/* this is called by the network core */
+static void my_poll (struct net_device *dev, int *budget)
+{
+
+	struct my_private *tp = (struct my_private *)dev->priv;
+	rx_ring = tp->rx_ring;
+	cur_rx = tp->cur_rx;
+	int entry = cur_rx % RX_BUF_LEN;
+	/* maximum packets to send to the stack */
+/************************ note note *********************************/		
+	int rx_work_limit = dev->quota;
+
+/************************ end note note *********************************/		
+    do {  // outer beggining loop starts here
+
+	clear_rx_status_register_bit();
+
+	while (rx_ring_not_empty) {
+		u32 rx_status;
+		unsigned int rx_size;
+		unsigned int pkt_size;
+		struct sk_buff *skb;
+                /* read size+status of next frame from DMA ring buffer */
+		/* the number 16 and 4 are just examples */
+                rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+                rx_size = rx_status >> 16;
+                pkt_size = rx_size - 4;
+
+		/* process errors */
+                if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
+                    (!(rx_status & RxStatusOK))) {
+                        netdrv_rx_err (rx_status, dev, tp, ioaddr);
+                        return;
+                }
+
+/************************ note note *********************************/		
+                if (--rx_work_limit < 0) { /* we got packets, but no quota */
+			/* store current ring pointer state */
+			tp->cur_rx = cur_rx;
+
+			/* Refill the Rx ring buffers if they are needed */
+			refill_rx_ring(dev);
+                        goto not_done;
+		}
+/**********************  end note **********************************/
+
+		/* grab a skb */
+                skb = dev_alloc_skb (pkt_size + 2);
+                if (skb) {
+			.
+			.
+/************************ note note *********************************/		
+			netif_receive_skb (skb);
+/**********************  end note **********************************/
+			.
+			.
+                } else {  /* OOM */
+			/*seems very driver specific ... common is just pass
+			whatever is on the ring already. */
+                }
+
+		/* move to the next skb on the ring */
+		entry = (++tp->cur_rx) % RX_RING_SIZE;
+		received++ ;
+
+        }
+
+	/* store current ring pointer state */
+        tp->cur_rx = cur_rx;
+
+        /* Refill the Rx ring buffers if they are needed */
+	refill_rx_ring(dev);
+	
+	/* no packets on ring; but new ones can arrive since we last 
+	   checked  */
+	status = read_interrupt_status_reg();
+	if (rx status is not set) {
+                        /* If something arrives in this narrow window,
+			an interrupt will be generated */
+                        goto done;
+	}
+	/* done! at least thats what it looks like ;->
+	if new packets came in after our last check on status bits
+	they'll be caught by the while check and we go back and clear them 
+	since we havent exceeded our quota */
+    } while (rx_status_is_set); 
+
+done:
+
+/************************ note note *********************************/		
+        dev->quota -= received;
+        *budget -= received;
+
+        /* If RX ring is not full we are out of memory. */
+        if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+                goto oom;
+
+	/* we are happy/done, no more packets on ring; put us back
+	to where we can start processing interrupts again */
+        netif_rx_complete(dev);
+	enable_rx_and_rxnobuf_ints();
+
+       /* The last op happens after poll completion. Which means the following:
+        * 1. it can race with disabling irqs in irq handler (which are done to 
+	* schedule polls)
+        * 2. it can race with dis/enabling irqs in other poll threads
+        * 3. if an irq raised after the begining of the outer  beginning 
+        * loop(marked in the code above), it will be immediately
+        * triggered here.
+        *
+        * Summarizing: the logic may results in some redundant irqs both
+        * due to races in masking and due to too late acking of already
+        * processed irqs. The good news: no events are ever lost.
+        */
+
+        return 0;   /* done */
+
+not_done:
+        if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
+            tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+                refill_rx_ring(dev);
+
+        if (!received) {
+                printk("received==0\n");
+                received = 1;
+        }
+        dev->quota -= received;
+        *budget -= received;
+        return 1;  /* not_done */
+
+oom:
+        /* Start timer, stop polling, but do not enable rx interrupts. */
+	start_poll_timer(dev);
+        return 0;  /* we'll take it from here so tell core "done"*/
+
+/************************ End note note *********************************/		
+}
+-------------------------------------------------------------------
+
+From above we note that:
+0) rx_work_limit = dev->quota 
+1) refill_rx_ring() is in charge of clearing the bit for rxnobuff when
+it does the work.
+2) We have a done and not_done state.
+3) instead of netif_rx() we call netif_receive_skb() to pass the skb.
+4) we have a new way of handling oom condition
+5) A new outer for (;;) loop has been added. This serves the purpose of
+ensuring that if a new packet has come in, after we are all set and done,
+and we have not exceeded our quota that we continue sending packets up.
+ 
+
+-----------------------------------------------------------
+Poll timer code will need to do the following:
+
+a) 
+
+        if (tp->cur_rx - tp->dirty_rx > RX_RING_SIZE/2 ||
+            tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL) 
+                refill_rx_ring(dev);
+
+        /* If RX ring is not full we are still out of memory.
+	   Restart the timer again. Else we re-add ourselves 
+           to the master poll list.
+         */
+
+        if (tp->rx_buffers[tp->dirty_rx % RX_RING_SIZE].skb == NULL)
+                restart_timer();
+
+	else netif_rx_schedule(dev);  /* we are back on the poll list */
+	
+5) dev->close() and dev->suspend() issues
+==========================================
+The driver writter neednt worry about this. The top net layer takes
+care of it.
+
+6) Adding new Stats to /proc 
+=============================
+In order to debug some of the new features, we introduce new stats
+that need to be collected.
+TODO: Fill this later.
+
+APPENDIX 1: discussion on using ethernet HW FC
+==============================================
+Most chips with FC only send a pause packet when they run out of Rx buffers.
+Since packets are pulled off the DMA ring by a softirq in NAPI,
+if the system is slow in grabbing them and we have a high input
+rate (faster than the system's capacity to remove packets), then theoretically
+there will only be one rx interrupt for all packets during a given packetstorm.
+Under low load, we might have a single interrupt per packet.
+FC should be programmed to apply in the case when the system cant pull out
+packets fast enough i.e send a pause only when you run out of rx buffers.
+Note FC in itself is a good solution but we have found it to not be
+much of a commodity feature (both in NICs and switches) and hence falls
+under the same category as using NIC based mitigation. Also experiments
+indicate that its much harder to resolve the resource allocation
+issue (aka lazy receiving that NAPI offers) and hence quantify its usefullness
+proved harder. In any case, FC works even better with NAPI but is not
+necessary.
+
+
+APPENDIX 2: the "rotting packet" race-window avoidance scheme 
+=============================================================
+
+There are two types of associations seen here
+
+1) status/int which honors level triggered IRQ
+
+If a status bit for receive or rxnobuff is set and the corresponding 
+interrupt-enable bit is not on, then no interrupts will be generated. However, 
+as soon as the "interrupt-enable" bit is unmasked, an immediate interrupt is 
+generated.  [assuming the status bit was not turned off].
+Generally the concept of level triggered IRQs in association with a status and
+interrupt-enable CSR register set is used to avoid the race.
+
+If we take the example of the tulip:
+"pending work" is indicated by the status bit(CSR5 in tulip).
+the corresponding interrupt bit (CSR7 in tulip) might be turned off (but
+the CSR5 will continue to be turned on with new packet arrivals even if
+we clear it the first time)
+Very important is the fact that if we turn on the interrupt bit on when
+status is set that an immediate irq is triggered.
+ 
+If we cleared the rx ring and proclaimed there was "no more work
+to be done" and then went on to do a few other things;  then when we enable
+interrupts, there is a possibility that a new packet might sneak in during
+this phase. It helps to look at the pseudo code for the tulip poll
+routine:
+
+--------------------------
+        do {
+                ACK;
+                while (ring_is_not_empty()) {
+                        work-work-work
+                        if quota is exceeded: exit, no touching irq status/mask
+                }
+                /* No packets, but new can arrive while we are doing this*/
+                CSR5 := read
+                if (CSR5 is not set) {
+                        /* If something arrives in this narrow window here,
+                        *  where the comments are ;-> irq will be generated */
+                        unmask irqs;
+                        exit poll;
+                }
+        } while (rx_status_is_set);
+------------------------
+
+CSR5 bit of interest is only the rx status. 
+If you look at the last if statement: 
+you just finished grabbing all the packets from the rx ring .. you check if
+status bit says theres more packets just in ... it says none; you then
+enable rx interrupts again; if a new packet just came in during this check,
+we are counting that CSR5 will be set in that small window of opportunity
+and that by re-enabling interrupts, we would actually triger an interrupt
+to register the new packet for processing.
+
+[The above description nay be very verbose, if you have better wording 
+that will make this more understandable, please suggest it.]
+
+2) non-capable hardware
+
+These do not generally respect level triggered IRQs. Normally,
+irqs may be lost while being masked and the only way to leave poll is to do
+a double check for new input after netif_rx_complete() is invoked
+and re-enable polling (after seeing this new input).
+
+Sample code:
+
+---------
+	.
+	.
+restart_poll:
+	while (ring_is_not_empty()) {
+		work-work-work
+		if quota is exceeded: exit, not touching irq status/mask
+	}
+	.
+	.
+	.
+	enable_rx_interrupts()
+	netif_rx_complete(dev);
+	if (ring_has_new_packet() && netif_rx_reschedule(dev, received)) {
+		disable_rx_and_rxnobufs()
+		goto restart_poll
+	} while (rx_status_is_set);
+---------
+		
+Basically netif_rx_complete() removes us from the poll list, but because a
+new packet which will never be caught due to the possibility of a race
+might come in, we attempt to re-add ourselves to the poll list. 
+
+
+
+--------------------------------------------------------------------
+
+relevant sites:
+==================
+ftp://robur.slu.se/pub/Linux/net-development/NAPI/
+
+
+--------------------------------------------------------------------
+TODO: Write net-skeleton.c driver.
+-------------------------------------------------------------
+
+Authors:
+========
+Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+Jamal Hadi Salim <hadi@cyberus.ca>
+Robert Olsson <Robert.Olsson@data.slu.se>
+
+Acknowledgements:
+================
+People who made this document better:
+
+Lennert Buytenhek <buytenh@gnu.org>
+Andrew Morton  <akpm@zip.com.au>
+Manfred Spraul <manfred@colorfullife.com>
+Donald Becker <becker@scyld.com>
+Jeff Garzik 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/dl2k.txt linux/Documentation/networking/dl2k.txt
--- linux.orig/Documentation/networking/dl2k.txt	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/networking/dl2k.txt	2002-08-12 22:14:05.000000000 +0000
@@ -1,7 +1,7 @@
 
     D-Link DL2000-based Gigabit Ethernet Adapter Installation
     for Linux
-    Jan 29, 2002
+    May 23, 2002
 
 Contents
 ========
@@ -202,7 +202,7 @@
 				  1000mbps_fd and 1000mbps_hd types are only
 				  available for fiber adapter.
 
-vlan=[0|1]			- Specifies the VLAN ID. If vlan=0, the
+vlan=n				- Specifies the VLAN ID. If vlan=0, the
 				  Virtual Local Area Network (VLAN) function is
 				  disable.
 
@@ -211,24 +211,34 @@
 				  function is disabled.
 				  Jumbo frame usually improve the performance
 				  int gigabit.
+				  This feature need jumbo frame compatible 
+				  remote.
 				  
-rx_coalesce=n			- Rx frame count each interrupt.
-rx_timeout=n			- Rx DMA wait time for an interrupt. Proper 
-				  values of rx_coalesce and rx_timeout bring 
-				  a conspicuous performance in the fast machine.
-				  Ex. rx_coalesce=5 and rx_timeout=750 
-
-tx_coalesce=n			- Tx transmit count each TxComp interrupt.
-				  Setting value larger than 1 will improve 
-				  performance, but this is possible to lower 
-				  stability in slow UP machines. By default, 
-				  tx_coalesce=1. (dl2k)
+rx_coalesce=m			- Number of rx frame handled each interrupt.
+rx_timeout=n			- Rx DMA wait time for an interrupt. 
+				  If set rx_coalesce > 0, hardware only assert 
+				  an interrupt for m frames. Hardware won't 
+				  assert rx interrupt until m frames received or
+				  reach timeout of n * 640 nano seconds. 
+				  Set proper rx_coalesce and rx_timeout can 
+				  reduce congestion collapse and overload which
+				  has been a bottlenect for high speed network.
 				  
-tx_flow=[1|0]			- Specifies the Tx flow control. If tx_flow=1, 
-				  the Tx flow control enable.
+				  For example, rx_coalesce=10 rx_timeout=800.
+				  that is, hardware assert only 1 interrupt 
+				  for 10 frames received or timeout of 512 us. 
+
+tx_coalesce=n			- Number of tx frame handled each interrupt.
+				  Set n > 1 can reduce the interrupts 
+				  congestion usually lower performance of
+				  high speed network card. Default is 16.
 				  
-rx_flow=[1|0]			- Specifies the Rx flow control. If rx_flow=1, 
-				  the Rx flow control enable.
+tx_flow=[1|0]			- Specifies the Tx flow control. If tx_flow=0, 
+				  the Tx flow control disable else driver
+				  autodetect.
+rx_flow=[1|0]			- Specifies the Rx flow control. If rx_flow=0, 
+				  the Rx flow control enable else driver
+				  autodetect.
 
 
 Configuration Script Sample
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/e100.txt linux/Documentation/networking/e100.txt
--- linux.orig/Documentation/networking/e100.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/networking/e100.txt	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,272 @@
+Linux* Base Driver for the Intel(R) PRO/100 Family of Adapters
+==============================================================
+
+April 9, 2002
+
+
+Contents
+========
+
+- In This Release
+- Supported Adapters
+- Command Line Parameters
+- CPU Cycle Saver
+- Additional Configurations
+- Support
+
+
+In This Release
+===============
+
+This file describes the Linux* Base Driver for the Intel(R) PRO/100 Family of
+Adapters, version 2.0.x.  This driver includes support for Itanium(TM)-based 
+systems.
+
+New for this release:
+
+   - Additional ethtool functionality, including link status test and EEPROM 
+     read/write. A third-party application can use the ethtool interface to 
+     get and set driver parameters.
+
+   - Support for Zero copy on 82550-based adapters. This feature provides 
+     faster data throughput and significant CPU usage improvement in systems 
+     that use the relevant system call (sendfile(2)).
+
+   - Support for large MTU-enabling interface (1504 bytes) with kernel's 
+     VLAN module
+
+   - Support for polling on RX
+
+   - Support for Wake On LAN* on 82550 and 82559-based adapters
+
+
+Supported Adapters
+==================
+
+The following Intel network adapters are compatible with the drivers 
+in this release:
+
+Controller  Adapter Name                            Board IDs
+----------  ------------                            ---------
+
+82558       PRO/100+ PCI Adapter                    668081-xxx, 689661-xxx
+
+82558       PRO/100+ Management Adapter             691334-xxx, 701738-xxx,
+                                                    721383-xxx
+
+82558       PRO/100+ Dual Port Server Adapter       714303-xxx, 711269-xxx, 
+                                                    A28276-xxx
+
+82558       PRO/100+ PCI Server Adapter             710550-xxx
+
+82550       PRO/100 S Server Adapter                752438-xxx (82550)
+82559                                               A56831-xxx, A10563-xxx,
+                                                    A12171-xxx, A12321-xxx, 
+                                                    A12320-xxx, A12170-xxx
+                                                    748568-xxx (82559)
+                                                    748565-xxx (82559)
+
+
+82550       PRO/100 S Desktop Adapter               751767-xxx (82550)
+82559                                               748592-xxx, A12167-xxx, 
+                                                    A12318-xxx, A12317-xxx, 
+                                                    A12165-xxx
+                                                    748569-xxx (82559)
+
+
+
+82559       PRO/100+ Server Adapter                 729757-xxx
+
+82559       PRO/100 S Management Adapter            748566-xxx, 748564-xxx
+
+82550       PRO/100 S Dual Port Server Adapter      A56831-xxx
+
+82551       PRO/100 M Desktop Adapter               A80897-xxx
+
+            PRO/100 S Advanced Management Adapter   747842-xxx, 745171-xxx
+
+CNR         PRO/100 VE Desktop Adapter              A10386-xxx, A10725-xxx, 
+                                                    A23801-xxx, A19716-xxx
+
+
+            PRO/100 VM Desktop Adapter              A14323-xxx, A19725-xxx, 
+                                                    A23801-xxx, A22220-xxx, 
+                                                    A23796-xxx
+   
+
+To verify that your adapter is supported, find the board ID number on the 
+adapter. Look for a label that has a barcode and a number in the format 
+123456-001 (six digits hyphen three digits). Match this to the list of 
+numbers above.
+
+For more information on how to identify your adapter, go to the Adapter & 
+Driver ID Guide at:
+
+  http://support.intel.com/support/network/adapter/pro100/21397.htm
+
+For the latest Intel PRO/100 network driver for Linux, see:
+
+  http://appsr.intel.com/scripts-df/support_intel.asp
+
+
+Command Line Parameters
+=======================
+
+The following parameters are used by entering them on the command line with 
+the modprobe or insmod command. For example, with two Intel PRO/100 PCI 
+adapters, entering:
+	
+     modprobe e100 TxDescriptors=32,128
+
+loads the e100 driver with 32 TX resources for the first adapter and 128 TX 
+resources for the second adapter. This configuration favors the second 
+adapter. The driver supports up to 16 network adapters concurrently.
+
+NOTE: Giving any command line option the value "-1" causes the driver to use 
+      the appropriate default value for that option, as if no value was 
+      specified.
+
+
+BundleMax
+Valid Range: 0x1-0xFFFF
+Default Value: 6
+   This parameter holds the maximum number of packets in a bundle. Suggested 
+   values range from 2 to 10. See "CPU Cycle Saver."
+
+BundleSmallFr
+Valid Range: 0-1 (0=off, 1=on)
+Default Value: 0
+   The value 1 (on) causes small packets (less than 128 bytes) to be bundled. 
+   See "CPU Cycle Saver."
+
+e100_speed_duplex
+Valid Range: 0-4 (1=10half;2=10full;3=100half;4=100full)
+Default Value: 0
+   The default value of 0 is set to auto-negotiate if the link partner is set
+   to auto-negotiate. If the link partner is forced, e100_speed_duplex 
+   defaults to half-duplex. 
+   Example usage: insmod e100.o e100_speed_duplex=4,4 (for two adapters)
+
+flow_control
+Valid Range: 0-1 (0=off, 1=on)
+Default Value: 0
+   This parameter controls the automatic generation(Tx) and response(Rx) to 
+   Ethernet PAUSE frames. flow_control should NOT be set to 1 when the e100 
+   adapter is connected to an interface that does not support Ethernet PAUSE 
+   frames and when the e100_speed_duplex parameter is NOT set to zero. 
+
+IntDelay
+Valid Range: 0-0xFFFF (0=off)
+Default Value: 1536
+   This parameter holds the number of time units (in adapter terminology)
+   until the adapter generates an interrupt. The recommended value for 
+   IntDelay is 0x600 (upon initialization). Suggested values range from 
+   0x200h to 0x800. See "CPU Cycle Saver."
+
+IFS
+Valid Range: 0-1 (0=off, 1=on)
+Default Value: 1
+  Inter Frame Spacing (IFS) aims to reduce the number of Ethernet frame
+  collisions by altering the time between frame transmissions. When IFS is 
+  enabled the driver tries to find an optimal IFS value. However, some 
+  switches function better when IFS is disabled.
+
+PollingMaxWork
+Valid Range: 1-1024 (max number of RxDescriptors)
+Default Value: Specified number of RxDescriptors
+  This value specifies the maximum number of receive packets that are 
+  processed on a single polling call. This parameter is invalid if 
+  RxCongestionControl is set to 0.
+
+RxCongestionControl
+Valid Range: 0-1 (0=off, 1=on)
+Default Value: 1
+  1 enables polling mode. When the link is congested, the driver can decide 
+  to handle received packets by polling them, instead of waiting until 
+  interrupts occur.
+
+RxDescriptors
+Valid Range: 8-1024
+Default Value: 64
+   This parameter defines the number of receive descriptors allocated by 
+   the driver. Increasing this value allows the driver to buffer more 
+   incoming packets before the driver is required to service an interrupt. 
+   The maximum value for Itanium-based systems is 64.
+
+TxDescriptors
+Valid Range: 19-1024
+Default Value: 64
+   This value is the number of transmit descriptors allocated by the driver. 
+   Increasing this value allows the protocol stack to queue more transmits at
+   the driver level. The maximum value for Itanium-based systems is 64.
+
+ucode (not available for 82557-based adapters)
+Valid Range: 0-1 (0=off, 1=on)
+Default Value: 0 for 82558-based adapters
+               1 for 82559(and higher)-based adapters
+   On uploads the micro code to the adapter, which enables CPU Cycle Saver. 
+   See the section "CPU Cycle Saver" below.
+   Example usage: insmod e100.o ucode=0  (does not reduce CPU usage)
+
+XsumRX
+Valid Range: 0-1 (0=off, 1=on)
+Default Value: 1
+   On allows Rx checksum offloading for TCP/UDP packets. Requires that the 
+   hardware support this feature.
+
+
+CPU Cycle Saver
+================
+
+CPU Cycle Saver reduces CPU utilization by reducing the number of interrupts 
+that the adapter generates.
+
+When CPU Cycle Saver is turned off, the adapter generates one interrupt for 
+every frame that is received. This means that the operating system stops what
+it is doing and switches to the network driver in order to process the 
+receive.
+
+When CPU Cycle Saver is on, the adapter does not generate an interrupt for 
+every frame it receives. Instead, it waits until it receives several frames 
+before generating an interrupt. This reduces the amount of time spent 
+switching to and from the driver. 
+
+CPU Cycle Saver consists of these arguments: IntDelay, BundleMax and 
+BundleSmallFr. When IntDelay is increased, the adapter waits longer for 
+frames to arrive before generating the interrupt. By increasing BundleMax, 
+the network adapter waits for the number of frames specified to arrive before 
+generating the interrupt. When BundleSmallFr is disabled, the adapter does 
+not bundle packets that are smaller than 128 bytes. Such small packets are 
+often, but not always, control packets that are better served immediately.
+
+For most users, it is recommended that CPU Cycle Saver be used with the 
+default values specified in the Command Line Parameters section. However, in 
+some cases, performance problems may occur with CPU Cycle Saver. If such 
+problems are observed, we recommend turning off this feature by setting 
+ucode=0.
+
+
+Support
+=======
+
+For general information and support, go to the Intel support website at:
+
+    http://support.intel.com
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related to 
+the issue to linux.nics@intel.com.
+
+
+License
+=======
+
+This software program is released under the terms of a license agreement 
+between you ('Licensee') and Intel. Do not use or load this software or any 
+associated materials (collectively, the 'Software') until you have carefully 
+read the full terms and conditions of the LICENSE located in this software 
+package. By loading or using the Software, you agree to the terms of this 
+Agreement. If you do not agree with the terms of this Agreement, do not 
+install or use the Software.
+
+* Other names and brands may be claimed as the property of others.
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/e1000.txt linux/Documentation/networking/e1000.txt
--- linux.orig/Documentation/networking/e1000.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/networking/e1000.txt	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,272 @@
+Linux* Base Driver for the Intel(R) PRO/1000 Family of Adapters
+===============================================================
+
+June 11, 2002
+
+
+Contents
+========
+
+- In This Release
+- Supported Adapters
+- Command Line Parameters
+- Speed and Duplex Configuration
+- Additional Configurations
+- Known Issues
+- Support
+
+
+In This Release
+===============
+
+This file describes the Linux* Base Driver for the Intel(R) PRO/1000 Family
+of Adapters, version 4.2.x.  This driver includes support for 
+Itanium(TM)-based systems.
+
+This release version includes the following:
+
+   - Support for the ethtool 1.5 interface. A third-party application can use
+     the ethtool interface to get and set driver parameters.
+
+   - Zero copy. This feature provides faster data throughput. Enabled by
+     default in supporting kernels. It is not supported on the Intel(R)
+     PRO/1000 Gigabit Server Adapter.
+
+New features include:
+
+   - Support for the 82545 and 82546-based adapters listed below
+
+   - Wake on LAN* support via ethtool for 82540, 82544, 82545, and 82546-
+     based adapters
+
+   - Adaptive IFS for increased performance at half duplex
+
+
+
+Supported Adapters
+==================
+
+The following Intel network adapters are compatible with the drivers in this
+release:
+
+   Controller  Adapter Name                         Board IDs
+   ----------  ------------                         ---------
+
+   82542       PRO/1000 Gigabit Server Adapter      700262-xxx, 717037-xxx
+
+   82543       PRO/1000 F Server Adapter            738640-xxx, A38888-xxx
+
+   82543       PRO/1000 T Server Adapter            A19845-xxx, A33948-xxx
+
+   82544       PRO/1000 XT Server Adapter           A51580-xxx
+
+   82544       PRO/1000 XF Server Adapter           A50484-xxx
+
+   82544       PRO/1000 T Desktop Adapter           A62947-xxx
+
+   82540       PRO/1000 MT Desktop Adapter          A78408-xxx
+
+   82545       PRO/1000 MT Server Adapter           A92165-xxx
+
+   82546       PRO/1000 MT Dual Port Server Adapter A92111-xxx
+
+   82545       PRO/1000 MF Server Adapter           A91622-xxx
+
+   82545       PRO/1000 MF Server Adapter(LX)       A91624-xxx
+
+   82546       PRO/1000 MF Dual Port Server Adapter A91620-xxx
+
+
+To verify your Intel adapter is supported, find the board ID number on the
+adapter. Look for a label that has a barcode and a number in the format of
+123456-001 (six digits hyphen three digits). Match this to the list of
+numbers above.
+
+For more information on how to identify your adapter, go to the Adapter &
+Driver ID Guide at:
+
+    http://support.intel.com/support/network/adapter/pro100/21397.htm
+
+For the latest Intel network drivers for Linux, go to:
+
+    http://appsr.intel.com/scripts-df/support_intel.asp
+
+
+Command Line Parameters
+=======================
+
+If the driver is built as a module, the following optional parameters are 
+used by entering them on the command line with the modprobe or insmod command. 
+For example, with two PRO/1000 PCI adapters, entering:
+
+    insmod e1000 TxDescriptors=80,128
+
+loads the e1000 driver with 80 TX resources for the first adapter and 128 TX
+resources for the second adapter.
+
+For more information about the AutoNeg, Duplex, and Speed parameters, see the
+"Speed and Duplex Configuration" section in this document.
+
+
+AutoNeg (adapters using copper connections only)
+Valid Range: 0x01-0x0F, 0x20-0x2F
+Default Value: 0x2F
+    This parameter is a bit mask that specifies which speed and duplex
+    settings the board advertises. When this parameter is used, the Speed and
+    Duplex parameters must not be specified.
+
+Duplex (adapters using copper connections only)
+Valid Range: 0-2 (0=auto-negotiate, 1=half, 2=full)
+Default Value: 0
+    Defines the direction in which data is allowed to flow. Can by either one
+    or two-directional. If both Duplex and the link partner are set to auto-
+    negotiate, the board auto-detects the correct duplex. If the link partner
+    is forced (either full or half), Duplex defaults to half-duplex.
+
+FlowControl
+Valid Range: 0-3 (0=none, 1=Rx only, 2=Tx only, 3=Rx&Tx)
+Default: Read flow control settings from the EEPROM
+    This parameter controls the automatic generation(Tx) and response(Rx) to
+    Ethernet PAUSE frames.
+
+RxDescriptors
+Valid Range: 80-256 for 82542 and 82543-based adapters
+             80-4096 for 82540, 82544, 82545, and 82546-based adapters
+Default Value: 80
+    This value is the number of receive descriptors allocated by the driver.
+    Increasing this value allows the driver to buffer more incoming packets.
+    Each descriptor is 16 bytes.  A receive buffer is also allocated for each
+    descriptor and can be either 2048, 4096, 8192, or 16384 bytes, depending
+    on the MTU setting. The maximum MTU size is 16110.
+
+RxIntDelay
+Valid Range: 0-65535 (0=off)
+Default Value: 0 (82542, 82543, and 82544-based adapters)
+               128 (82540, 82545, and 82546-based adapters)
+    This value delays the generation of receive interrupts in units of 1.024
+    microseconds.  Receive interrupt reduction can improve CPU efficiency if
+    properly tuned for specific network traffic. Increasing this value adds
+    extra latency to frame reception and can end up decreasing the throughput
+    of TCP traffic. If the system is reporting dropped receives, this value
+    may be set too high, causing the driver to run out of available receive
+    descriptors.
+
+    CAUTION: When setting RxIntDelay to a value other than 0, adapters based
+             on the Intel 82543 and 82544 LAN controllers may hang (stop
+             transmitting) under certain network conditions. If this occurs a
+             message is logged in the system event log. In addition, the
+             controller is automatically reset, restoring the network
+             connection. To eliminate the potential for the hang ensure that
+             RxIntDelay is set to 0.
+
+Speed (adapters using copper connections only)
+Valid Settings: 0, 10, 100, 1000
+Default Value: 0 (auto-negotiate at all supported speeds)
+    Speed forces the line speed to the specified value in megabits per second
+    (Mbps). If this parameter is not specified or is set to 0 and the link
+    partner is set to auto-negotiate, the board will auto-detect the correct
+    speed. Duplex must also be set when Speed is set to either 10 or 100.
+
+TxDescriptors
+Valid Range: 80-256 for 82542 and 82543-based adapters
+             80-4096 for 82540, 82544, 82545, and 82546-based adapters
+Default Value: 256
+    This value is the number of transmit descriptors allocated by the driver.
+    Increasing this value allows the driver to queue more transmits. Each
+    descriptor is 16 bytes.
+
+XsumRX (not available on the PRO/1000 Gigabit Server Adapter)
+Valid Range: 0-1
+Default Value: 1
+    A value of '1' indicates that the driver should enable IP checksum
+    offload for received packets (both UDP and TCP) to the adapter hardware.
+
+
+Speed and Duplex Configuration
+==============================
+
+Three keywords are used to control the speed and duplex configuration. These
+keywords are Speed, Duplex, and AutoNeg.
+
+If the board uses a fiber interface, these keywords are ignored, and the
+fiber interface board only links at 1000 Mbps full-duplex.
+
+For copper-based boards, the keywords interact as follows:
+
+  The default operation is auto-negotiate. The board advertises all supported
+  speed and duplex combinations, and it links at the highest common speed and
+  duplex mode IF the link partner is set to auto-negotiate.
+
+  If Speed = 1000, limited auto-negotiation is enabled and only 1000 Mbps is
+  advertised (The 1000BaseT spec requires auto-negotiation.)
+
+  If Speed = 10 or 100, then both Speed and Duplex must be set. Auto-
+  negotiation is disabled, and the AutoNeg parameter is ignored. Partner MUST
+  also be forced.
+
+The AutoNeg parameter is used when more control is required over the auto-
+negotiation process.  When this parameter is used, Speed and Duplex must not
+be specified.  This parameter is a bitmap that specifies which speed and
+duplex settings are advertised to the link partner.
+
+Bit            7      6      5       4       3      2      1       0
+Speed (Mbps)   N/A    N/A    1000    N/A     100    100    10      10
+Duplex                       Full            Full   Half   Full    Half
+
+Note that setting AutoNeg does not guarantee that the board will link at the
+highest specified speed or duplex mode, but the board will link at the
+highest possible speed/duplex of the link partner IF the link partner is also
+set to auto-negotiate. If the link partner is forced speed/duplex, the
+adapter MUST be forced to the same speed/duplex.
+
+
+Additional Configurations
+=========================
+
+  Jumbo Frames
+  ------------
+
+  The driver supports Jumbo Frames for all adapters except 82542-based
+  adapters.  Jumbo Frames support is enabled by changing the MTU to a value
+  larger than the default of 1500.  Use the ifconfig command to increase the
+  MTU size. For example:
+
+        ifconfig ethx mtu 9000 up
+
+
+Known Issues
+============
+
+  Jumbo Frames System Requirement
+  -------------------------------
+
+  Memory allocation failures have been observed on Linux systems with 64 MB
+  of RAM or less that are running Jumbo Frames. If you are using Jumbo
+  Frames, your system may require more than the advertised minimum
+  requirement of 64 MB of system memory.
+
+
+Support
+=======
+
+For general information and support, go to the Intel support website at:
+
+    http://support.intel.com
+
+If an issue is identified with the released source code on the supported
+kernel with a supported adapter, email the specific information related to
+the issue to linux.nics@intel.com.
+
+
+License
+=======
+
+This software program is released under the terms of a license agreement
+between you ('Licensee') and Intel. Do not use or load this software or any
+associated materials (collectively, the 'Software') until you have carefully
+read the full terms and conditions of the LICENSE located in this software
+package. By loading or using the Software, you agree to the terms of this
+Agreement. If you do not agree with the terms of this Agreement, do not
+install or use the Software.
+
+* Other names and brands may be claimed as the property of others.
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/networking/pktgen.txt linux/Documentation/networking/pktgen.txt
--- linux.orig/Documentation/networking/pktgen.txt	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/networking/pktgen.txt	2002-08-12 22:14:14.000000000 +0000
@@ -4,6 +4,9 @@
    in the place where insmod may find it.
 2. Cut script "ipg" (see below).
 3. Edit script to set preferred device and destination IP address.
+3a.  Create more scripts for different interfaces.  Up to thirty-two
+     pktgen processes can be configured and run at once by using the
+     32 /proc/net/pg* files.
 4. Run in shell: ". ipg"
 5. After this two commands are defined:
    A. "pg" to start generator and to get results.
@@ -12,12 +15,33 @@
       pgset "multiskb 0"      use single SKB for all transmits
       pgset "pkt_size 9014"   sets packet size to 9014
       pgset "frags 5"         packet will consist of 5 fragments
-      pgset "count 200000"    sets number of packets to send
+      pgset "count 200000"    sets number of packets to send, set to zero
+                              for continious sends untill explicitly
+                              stopped.
       pgset "ipg 5000"        sets artificial gap inserted between packets
                               to 5000 nanoseconds
       pgset "dst 10.0.0.1"    sets IP destination address
                               (BEWARE! This generator is very aggressive!)
+      pgset "dst_min 10.0.0.1"            Same as dst
+      pgset "dst_max 10.0.0.254"          Set the maximum destination IP.
+      pgset "src_min 10.0.0.1"            Set the minimum (or only) source IP.
+      pgset "src_max 10.0.0.254"          Set the maximum source IP.
       pgset "dstmac 00:00:00:00:00:00"    sets MAC destination address
+      pgset "srcmac 00:00:00:00:00:00"    sets MAC source address
+      pgset "src_mac_count 1" Sets the number of MACs we'll range through.  The
+                              'minimum' MAC is what you set with srcmac.
+      pgset "dst_mac_count 1" Sets the number of MACs we'll range through.  The
+                              'minimum' MAC is what you set with dstmac.
+      pgset "flag [name]"     Set a flag to determine behaviour.  Current flags
+                              are: IPSRC_RND #IP Source is random (between min/max),
+                                   IPDST_RND, UDPSRC_RND,
+                                   UDPDST_RND, MACSRC_RND, MACDST_RND 
+      pgset "udp_src_min 9"   set UDP source port min, If < udp_src_max, then
+                              cycle through the port range.
+      pgset "udp_src_max 9"   set UDP source port max.
+      pgset "udp_dst_min 9"   set UDP destination port min, If < udp_dst_max, then
+                              cycle through the port range.
+      pgset "udp_dst_max 9"   set UDP destination port max.
       pgset stop    	      aborts injection
       
   Also, ^C aborts generator.
@@ -26,22 +50,24 @@
 
 #! /bin/sh
 
-modprobe pktgen.o
+modprobe pktgen
+
+PGDEV=/proc/net/pg/pg0
 
 function pgset() {
     local result
 
-    echo $1 > /proc/net/pg
+    echo $1 > $PGDEV
 
-    result=`cat /proc/net/pg | fgrep "Result: OK:"`
+    result=`cat $PGDEV | fgrep "Result: OK:"`
     if [ "$result" = "" ]; then
-         cat /proc/net/pg | fgrep Result:
+         cat $PGDEV | fgrep Result:
     fi
 }
 
 function pg() {
-    echo inject > /proc/net/pg
-    cat /proc/net/pg
+    echo inject > $PGDEV
+    cat $PGDEV
 }
 
 pgset "odev eth0"
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/parisc/00-INDEX linux/Documentation/parisc/00-INDEX
--- linux.orig/Documentation/parisc/00-INDEX	2000-12-05 20:29:38.000000000 +0000
+++ linux/Documentation/parisc/00-INDEX	2002-08-12 22:14:24.000000000 +0000
@@ -1,10 +1,10 @@
 00-INDEX
 	- this file.
 IODC.txt
-	- Documentation IODC
+	- Documentation for IODC
 debugging
 	- some debugging hints for real-mode code
-mm
-	- Documentation on parisc mm status
+unwritten
+	- list of unwritten / incomplete functions
 registers
 	- current/planned usage of registers
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/parisc/registers linux/Documentation/parisc/registers
--- linux.orig/Documentation/parisc/registers	2001-09-14 21:04:06.000000000 +0000
+++ linux/Documentation/parisc/registers	2002-08-12 22:14:00.000000000 +0000
@@ -25,8 +25,8 @@
 CR27 (TR 3)			Thread descriptor pointer
 CR28 (TR 4)			not used
 CR29 (TR 5)			not used
-CR30 (TR 6)			current / 0
-CR31 (TR 7)			Temporary register, used in various places
+CR30 (TR 6)			current
+CR31 (TR 7)			interrupt stack base
 
 	Space Registers (kernel mode)
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/usb/silverlink.txt linux/Documentation/usb/silverlink.txt
--- linux.orig/Documentation/usb/silverlink.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/usb/silverlink.txt	2002-08-12 22:14:05.000000000 +0000
@@ -0,0 +1,76 @@
+-------------------------------------------------------------------------
+Readme for Linux device driver for the Texas Instruments SilverLink cable
+-------------------------------------------------------------------------
+
+Author: Romain Liévin & Julien Blache
+Homepage: http://lpg.ticalc.org/prj_usb
+
+INTRODUCTION:
+
+This is a driver for the TI-GRAPH LINK USB (aka SilverLink) cable, a cable 
+designed by TI for connecting their TI8x/9x calculators to a computer 
+(PC or Mac usually).
+
+If you need more information, please visit the 'SilverLink drivers' homepage 
+at the above URL.
+
+WHAT YOU NEED:
+
+A TI calculator of course and a program capable to communicate with your 
+calculator.
+TiLP will work for sure (since I am his developer !). yal92 may be able to use
+it by changing tidev for tiglusb (may require some hacking...).
+
+HOW TO USE IT:
+
+You must have first compiled USB support, support for your specific USB host
+controller (UHCI or OHCI).
+
+Next, (as root) from your appropriate modules directory (lib/modules/2.5.XX):
+
+       insmod usb/usbcore.o
+       insmod usb/usb-uhci.o  <OR>  insmod usb/ohci-hcd.o
+       insmod tiglusb.o
+
+If it is not already there (it usually is), create the device:
+
+       mknod /dev/tiglusb0 c 115 16
+
+You will have to set permissions on this device to allow you to read/write
+from it:
+
+       chmod 666 /dev/tiglusb0
+       
+Now you are ready to run a linking program such as TiLP. Be sure to configure 
+it properly (RTFM).
+       
+MODULE PARAMETERS:
+
+  You can set these with:  insmod tiglusb NAME=VALUE
+  There is currently no way to set these on a per-cable basis.
+
+  NAME: timeout
+  TYPE: integer
+  DEFAULT: 15
+  DESC: Timeout value in tenth of seconds. If no data is available once this 
+       time has expired then the driver will return with a timeout error.
+
+QUIRKS:
+
+The following problem seems to be specific to the link cable since it appears 
+on all platforms (Linux, Windows, Mac OS-X). 
+
+In some very particular cases, the driver returns with success but
+without any data. The application should retry a read operation at least once.
+
+HOW TO CONTACT US:
+
+You can email me at roms@lpg.ticalc.org. Please prefix the subject line
+with "TIGLUSB: " so that I am certain to notice your message.
+You can also mail JB at jb@jblache.org: he has written the first release of 
+this driver but he better knows the Mac OS-X driver.
+
+CREDITS:
+
+The code is based on dabusb.c, printer.c and scanner.c !
+The driver has been developed independantly of Texas Instruments.
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST
--- linux.orig/Documentation/video4linux/bttv/CARDLIST	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/video4linux/bttv/CARDLIST	2002-08-12 22:14:05.000000000 +0000
@@ -3,41 +3,41 @@
   card=1 - MIRO PCTV
   card=2 - Hauppauge (bt848)
   card=3 - STB
-  card=4 - Intel
+  card=4 - Intel Create and Share PCI/ Smart Video Recorder III
   card=5 - Diamond DTV2000
   card=6 - AVerMedia TVPhone
   card=7 - MATRIX-Vision MV-Delta
-  card=8 - FlyVideo II (Bt848) LR26
-  card=9 - IXMicro TurboTV
+  card=8 - Lifeview FlyVideo II (Bt848) LR26
+  card=9 - IMS/IXmicro TurboTV
   card=10 - Hauppauge (bt878)
   card=11 - MIRO PCTV pro
-  card=12 - ADS Technologies Channel Surfer TV
+  card=12 - ADS Technologies Channel Surfer TV (bt848)
   card=13 - AVerMedia TVCapture 98
   card=14 - Aimslab Video Highway Xtreme (VHX)
   card=15 - Zoltrix TV-Max
-  card=16 - Pixelview PlayTV (bt878)
+  card=16 - Prolink Pixelview PlayTV (bt878)
   card=17 - Leadtek WinView 601
   card=18 - AVEC Intercapture
-  card=19 - LifeView FlyKit w/o Tuner
+  card=19 - Lifeview FlyVideo II EZ /FlyKit LR38 Bt848 (capture only)
   card=20 - CEI Raffles Card
-  card=21 - Lucky Star Image World ConferenceTV
-  card=22 - Phoebe Tv Master + FM (CPH050)
+  card=21 - Lifeview FlyVideo 98/ Lucky Star Image World ConferenceTV LR50
+  card=22 - Askey CPH050/ Phoebe Tv Master + FM
   card=23 - Modular Technology MM205 PCTV, bt878
-  card=24 - [many vendors] CPH05X/06X (bt878)
-  card=25 - Terratec/Vobis TV-Boostar
-  card=26 - Newer Hauppauge WinCam (bt878)
-  card=27 - MAXI TV Video PCI2
+  card=24 - Askey CPH05X/06X (bt878) [many vendors]
+  card=25 - Terratec Terra TV+ Version 1.0 (Bt848)/Vobis TV-Boostar
+  card=26 - Hauppauge WinCam newer (bt878)
+  card=27 - Lifeview FlyVideo 98/ MAXI TV Video PCI2 LR50
   card=28 - Terratec TerraTV+
   card=29 - Imagenation PXC200
-  card=30 - FlyVideo 98
-  card=31 - iProTV
-  card=32 - Intel Create and Share PCI
+  card=30 - Lifeview FlyVideo 98 LR50
+  card=31 - Formac iProTV
+  card=32 - Intel Create and Share PCI/ Smart Video Recorder III
   card=33 - Terratec TerraTValue
   card=34 - Leadtek WinFast 2000
-  card=35 - Flyvideo 98 (LR50Q) / Chronos Video Shuttle II
-  card=36 - Flyvideo 98FM (LR50Q) / Typhoon TView TV/FM Tuner
-  card=37 - PixelView PlayTV pro
-  card=38 - TView99 CPH06X
+  card=35 - Lifeview FlyVideo 98 LR50 / Chronos Video Shuttle II
+  card=36 - Lifeview FlyVideo 98FM LR50 / Typhoon TView TV/FM Tuner
+  card=37 - Prolink PixelView PlayTV pro
+  card=38 - Askey CPH06X TView99
   card=39 - Pinnacle PCTV Studio/Rave
   card=40 - STB2
   card=41 - AVerMedia TVPhone 98
@@ -47,45 +47,47 @@
   card=45 - MATRIX-Vision MV-Delta 2
   card=46 - Zoltrix Genie TV/FM
   card=47 - Terratec TV/Radio+
-  card=48 - Dynalink Magic TView 
-  card=49 - GV-BCTV3
+  card=48 - Askey CPH03x/ Dynalink Magic TView
+  card=49 - IODATA GV-BCTV3/PCI
   card=50 - Prolink PV-BT878P+4E / PixelView PlayTV PAK / Lenco MXTV-9578 CP
   card=51 - Eagle Wireless Capricorn2 (bt878A)
   card=52 - Pinnacle PCTV Studio Pro
   card=53 - Typhoon TView RDS + FM Stereo / KNC1 TV Station RDS
-  card=54 - Lifetec LT 9415 TV (LR90 Rev.F)
-  card=55 - BESTBUY Easy TV (CPH031)
-  card=56 - FlyVideo '98/FM
+  card=54 - Lifeview FlyVideo 2000 /FlyVideo A2/ Lifetec LT 9415 TV [LR90]
+  card=55 - Askey CPH031/ BESTBUY Easy TV
+  card=56 - Lifeview FlyVideo 98FM LR50
   card=57 - GrandTec 'Grand Video Capture' (Bt848)
-  card=58 - Phoebe TV Master Only (No FM) CPH060
-  card=59 - TV Capturer (CPH03X)
+  card=58 - Askey CPH060/ Phoebe TV Master Only (No FM)
+  card=59 - Askey CPH03x TV Capturer
   card=60 - Modular Technology MM100PCTV
   card=61 - AG Electronics GMV1
-  card=62 - BESTBUY Easy TV (bt878)
+  card=62 - Askey CPH061/ BESTBUY Easy TV (bt878)
   card=63 - ATI TV-Wonder
   card=64 - ATI TV-Wonder VE
-  card=65 - FlyVideo 2000S
+  card=65 - Lifeview FlyVideo 2000S LR90
   card=66 - Terratec TValueRadio
-  card=67 - GV-BCTV4/PCI
+  card=67 - IODATA GV-BCTV4/PCI
   card=68 - 3Dfx VoodooTV FM (Euro), VoodooTV 200 (USA)
   card=69 - Active Imaging AIMMS
-  card=70 - PV-BT878P+
-  card=71 - Flyvideo 98EZ (capture only)
-  card=72 - Prolink PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)
+  card=70 - Prolink Pixelview PV-BT878P+ (Rev.4C)
+  card=71 - Lifeview FlyVideo 98EZ (capture only) LR51
+  card=72 - Prolink Pixelview PV-BT878P+9B (PlayTV Pro rev.9B FM+NICAM)
   card=73 - Sensoray 311
   card=74 - RemoteVision MX (RV605)
   card=75 - Powercolor MTV878/ MTV878R/ MTV878F
   card=76 - Canopus WinDVR PCI (COMPAQ Presario 3524JP, 5112JP)
   card=77 - GrandTec Multi Capture Card (Bt878)
-  card=78 - AOPEN VA1000
+  card=78 - Jetway TV/Capture JW-TV878-FBK, Kworld KW-TV878RF
+  card=79 - DSP Design TCVIDEO
+  card=80 - Hauppauge WinTV PVR
 
 tuner.o
   type=0 - Temic PAL (4002 FH5)
-  type=1 - Philips PAL_I
-  type=2 - Philips NTSC
-  type=3 - Philips SECAM
+  type=1 - Philips PAL_I (FI1246 and compatibles)
+  type=2 - Philips NTSC (FI1236 and compatibles)
+  type=3 - Philips (SECAM+PAL_BG) (FI1216MF, FM1216MF, FR1216MF)
   type=4 - NoTuner
-  type=5 - Philips PAL
+  type=5 - Philips PAL_BG (FI1216 and compatibles)
   type=6 - Temic NTSC (4032 FY5)
   type=7 - Temic PAL_I (4062 FY5)
   type=8 - Temic NTSC (4036 FY5)
@@ -103,7 +105,7 @@
   type=20 - Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)
   type=21 - Temic NTSC (4039 FR5)
   type=22 - Temic PAL/SECAM multi (4046 FM5)
-  type=23 - Philips PAL_DK
+  type=23 - Philips PAL_DK (FI1256 and compatibles)
   type=24 - Philips PAL/SECAM multi (FQ1216ME)
   type=25 - LG PAL_I+FM (TAPC-I001D)
   type=26 - LG PAL_I (TAPC-I701D)
@@ -118,3 +120,5 @@
   type=35 - Temic PAL_DK/SECAM_L (4012 FY5)
   type=36 - Temic NTSC (4136 FY5)
   type=37 - LG PAL (newer TAPC series)
+  type=38 - Philips PAL/SECAM multi (FM1216ME MK3)
+  type=39 - LG NTSC (newer TAPC series)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/bttv/Cards linux/Documentation/video4linux/bttv/Cards
--- linux.orig/Documentation/video4linux/bttv/Cards	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/video4linux/bttv/Cards	2002-08-12 22:14:07.000000000 +0000
@@ -1,3 +1,8 @@
+
+Gunther Mayer's bttv card gallery (graphical version of this text file :-)
+is available at: http://mayerg.gmxhome.de/bttv/bttv-gallery.html
+
+
 Suppported cards:
 
 
@@ -91,10 +96,9 @@
 - sound decoder: TDA9800, MSP34xx (stereo cards) 
 
 
-CPH-Series (CPH050, ...)
-------------------------
-Developed by TelSignal(?), OEMed by many vendors (Askey, Typhoon, 
-  Anubis, Dynalink)
+Askey CPH-Series
+----------------
+Developed by TelSignal(?), OEMed by many vendors (Typhoon, Anubis, Dynalink)
 
   Card series:
     CPH01x: BT848 capture only
@@ -149,9 +153,13 @@
       LR50 Rev.Q = Flyvideo 98 (w/eeprom and PCI subsystem ID)
            Rev.W = Flyvideo 98 (no eeprom)
       LR51 Rev.E = Flyvideo 98 EZ (capture only)
-      LR90       = Flyvideo 2000 series
+      LR90       = Flyvideo 2000 (Bt878)
+		   Flyvideo 2000S (Bt878) w/Stereo TV (Package incl. LR91 daughterboard)
       LR91       = Stereo daughter card for LR90
       LR97       = Flyvideo DVBS
+      LR99 Rev.E = Low profile card for OEM integration (only internal audio!) bt878
+      LR136	 = Flyvideo 2100/3100 (Low profile, SAA7130/SAA7134)
+      LR137      = Flyvideo DV2000/DV3000 (SAA7130/SAA7134 + IEEE1394)
       LR138 Rev.C= Flyvideo 2000 (SAA7130)
 	        or Flyvideo 3000 (SAA7134) w/Stereo TV
 		   These exist in variations w/FM and w/Remote sometimes denoted
@@ -162,15 +170,14 @@
       Their Bt8x8 cards are listed as discontinued.
       Flyvideo 2000S was probably sold as Flyvideo 3000 in some contries(Europe?).
       The new Flyvideo 2000/3000 are SAA7130/SAA7134 based. 
-      Flyvideo 2100/3100 are half-sized cards (for system integrators etc.)
 
   "Flyvideo II" had been the name for the 848 cards, nowadays (in Germany)
   this name is re-used for LR50 Rev.W.
   The Lifeview website mentioned Flyvideo III at some time, but such a card
-  has never been seen. 
+  has not yet been seen (perhaps it was the german name for LR90 [stereo]).
   These cards are sold by many OEMs too.
 
-  FlyVideo A2 = LR90 Rev.F (w/Remote, w/o FM, stereo TV by tda9821)
+  FlyVideo A2 = LR90 Rev.F (w/Remote, w/o FM, stereo TV by tda9821) {Germany}
 
 
 Typhoon TV card series:
@@ -190,7 +197,12 @@
   50686 "TV Tuner"                       = KNC1 TV Station
   50687 "TV Tuner stereo"                = KNC1 TV Station pro
   50688 "TV Tuner RDS" (black package)   = KNC1 TV Station RDS
+  50689  TV SAT DVB-S CARD CI PCI (SAA7146AH)
   50692 "TV/FM Tuner" (small PCB)
+  50694  TV TUNER CARD RDS (PHILIPS CHIPSET SAA7134HL)
+  50696  TV TUNER STEREO (PHILIPS CHIPSET SAA7134HL, MK3ME Tuner)
+  50804  PC-SAT TV/Audio Karte = Techni-PC-Sat (ZORAN 36120PQC, Tuner:Alps)
+  50866  TVIEW SAT RECEIVER+ADR
   50868 "TV/FM Tuner Pal I" (variant of 50682)
   50999 "TV/FM Tuner Secam" (variant of 50682)
 
@@ -207,16 +219,31 @@
 
 Prolink
 -------
-   Pixelview Play TV Pro:
-     PV-BT878P+rev.9B (Play TV Pro w/FM w/NICAM)
-     PV-BT878P+rev.8X 
-     PV-BT878P+rev.4C (Play TV Pro) 
-     PV-BT878P+rev.4E (Play TV Pak) 
-     PV-BT878P+rev.2F 
-     PV-BT878TV 
-
-   PixelView Play TV 
-     PV-BT848P+
+   TV cards:
+   PixelView Play TV pro - (Model: PV-BT878P+ REV 8E)
+   PixelView Play TV pro - (Model: PV-BT878P+ REV 9D)
+   PixelView Play TV pro - (Model: PV-BT878P+ REV 4C / 8D / 10A )
+   PixelView Play TV - (Model: PV-BT848P+)
+   878TV - (Model: PV-BT878TV)
+
+   Multimedia TV packages (card + software pack):
+   PixelView Play TV Theater - (Model: PV-M4200) =  PixelView Play TV pro + Software
+   PixelView Play TV PAK -     (Model: PV-BT878P+ REV 4E)
+   PixelView Play TV/VCR -     (Model: PV-M3200 REV 4C / 8D / 10A ) 
+   PixelView Studio PAK -      (Model:    M2200 REV 4C / 8D / 10A )
+   PixelView PowerStudio PAK - (Model: PV-M3600 REV 4E)
+   PixelView DigitalVCR PAK -  (Model: PV-M2400 REV 4C / 8D / 10A )
+
+   Further Cards:
+   PV-BT878P+rev.9B (Play TV Pro, opt. w/FM w/NICAM)
+   PV-BT878P+rev.2F
+   PV-BT878P Rev.1D (bt878, capture only)
+   
+   Video Conferencing:
+   PixelView Meeting PAK - (Model: PV-BT878P)
+   PixelView Meeting PAK Lite - (Model: PV-BT878P)
+   PixelView Meeting PAK plus - (Model: PV-BT878P+rev 4C/8D/10A)
+   PixelView Capture - (Model: PV-BT848P)
 
 Dynalink
 --------
@@ -235,7 +262,7 @@
 Tekram
 ------
    VideoCap C205 (Bt848)
-   VideoCap C210 (Zoran ZR36120 +Philips)
+   VideoCap C210 (zr36120 +Philips)
    CaptureTV M200 (ISA)
    CaptureTV M205 (Bt848)
 
@@ -257,8 +284,10 @@
    TV-Station FM (+Radio)
    TV-Station RDS (+RDS)
 
-PV951 cards:
-------------
+   newer Cards have saa7134, but model name stayed the same?
+
+Provideo PV951 
+--------------
   These are sold as:
    Boeder TV-FM Video Capture Card
    Titanmedia Supervision TV-2400
@@ -270,12 +299,14 @@
 Highscreen
 ----------
    TV Karte = LR50 Rev.S
-   TV-Boostar = Terratec Terra TV+ Version 1.0 (Bt848, TDA9821) "ceb105.pcb"
+   TV-Boostar = Terratec Terra TV+ Version 1.0 (Bt848, tda9821) "ceb105.pcb"
 
 Zoltrix
 -------
+   Face to Face Capture (Bt848 capture only) (PCB "VP-2848")
    Face To Face TV MAX (Bt848) (PCB "VP-8482 Rev1.3")
    Genie TV (Bt878) (PCB "VP-8790 Rev 2.1")
+   Genie Wonder Pro
 
 AVerMedia
 ---------
@@ -302,21 +333,24 @@
 
 Aimslab
 -------
+   Video Highway or "Video Highway TR200" (ISA)
    Video Highway Xtreme (aka "VHX") (Bt848, FM w/ TEA5757)
 
-IXMicro
+IXMicro (former: IMS=Integrated Micro Solutions)
 -------
    IXTV BT848
    IXTV BT878
    TurboTV (Bt848)
 
 Lifetec/Medion/Tevion/Aldi
--------
-   LT9415/MD9415 = LR90 Rev. F
+--------------------------
+   LT9306/MD9306 = CPH061
+   LT9415/MD9415 = LR90 Rev.F or Rev.G
           MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H)
+          MD9717 = KNC One (Rev D4, saa7134)
 
 Modular Technologies (www.modulartech.com) UK
---------------------
+---------------------------------------------
    MM100 PCTV (Bt848)
    MM205 PCTV (Bt878)
    MM210 PCTV (Bt878) (Galaxy TV)
@@ -326,19 +360,28 @@
    Terra TV+ Version 1.0 (Bt848), "ceb105.PCB" printed on the PCB, TDA9821
    Terra TV+ Version 1.1 (Bt878), "LR74 Rev.E" printed on the PCB, TDA9821
    Terra TValueRadio,             "LR102 Rev.C" printed on the PCB
-   Terra TV/Radio+ Version 1.0,   "80-CP2830100-0" TTTV3 printed on the PCB, i
+   Terra TV/Radio+ Version 1.0,   "80-CP2830100-0" TTTV3 printed on the PCB,
 				     "CPH010-E83" on the back, SAA6588T, TDA9873H
    Terra TValue Version BT878,    "80-CP2830110-0 TTTV4" printed on the PCB, 
 				     "CPH011-D83" on back
    Terra TValue Version 1.0       "ceb105.PCB" (really identical to Terra TV+ Version 1.0)
+   Terra Active Radio Upgrade (tea5757h, saa6588t)
 
    LR74 is a newer PCB revision of ceb105 (both incl. connector for Active Radio Upgrade)
 
+   Cinergy 400 (saa7134), "E877 11(S)", "PM820092D" printed on PCB
 
 Technisat
 ---------
-   Mediafocus I (ZR36120/ZR36125)
-   Mediafocus II (SAA7146)
+   Discos ADR PC-Karte ISA (no TV!)
+   Discos ADR PC-Karte PCI (probably no TV?)
+   Techni-PC-Sat (Sat. analog)
+         Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A)
+   Mediafocus I (zr36120/zr36125, drp3510, Sat. analog + ADR Radio)
+   Mediafocus II (saa7146, Sat. analog)
+         SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A)
+   SkyStar 1 DVB  (AV7110)
+   SkyStar 2 DVB  (B2C2) (=Sky2PC)
 
 Siemens
 -------
@@ -359,34 +402,262 @@
    Mirovideo PCTV (Bt848)
    Mirovideo PCTV SE (Bt848)
    Mirovideo PCTV Pro (Bt848 + Daughterboard)
-   Studio PCTV Rave (Bt878 w/o infrared)
-   Studio PCTV
-   Studio PCTV Pro (Bt878 stereo w/ FM)
+   Studio PCTV Rave (Bt878 package w/o infrared)
+   Studio PCTV      (Bt878)
+   Studio PCTV Pro  (Bt878 stereo w/ FM)
 
+   M(J)PEG capture and playback:
    DC1+ (ISA)
-   DC10  (zr36057 + zr36060 + saa7110 + adv7176)
-   DC10+ (zr36067 + zr36060 + saa7110 + adv7176)
-   DC20
-   DC30
-   DC30+ (zr36067 + zr36050 + zr36016 + vpx3220 + adv7176)
+   DC10  (zr36057,     zr36060,      saa7110, adv7176)
+   DC10+ (zr36067,     zr36060,      saa7110, adv7176)
+   DC20  (ql16x24b,zr36050, zr36016, saa7110, saa7187 ...)
+   DC30  (zr36057, zr36050, zr36016, vpx3220, adv7176, ad1843, tea6415, miro FST97A1)
+   DC30+ (zr36067, zr36050, zr36016, vpx3220, adv7176)
+   DC50  (zr36067, zr36050, zr36016, saa7112, adv7176 (2 pcs.?), ad1843, miro FST97A1, Lattice ???)
 
 Lenco
 -----
    MXR-9565 (=Technisat Mediafocus?)
-   MXR-9571 (Bt848)
+   MXR-9571 (Bt848) (=CPH031?)
    MXR-9575
-   MXR-9477 (Bt878)
-   MXTV-9578CP (= Prolink PV-BT878P+4E)
+   MXR-9577 (Bt878) (=Prolink 878TV Rev.3x)
+   MXTV-9578CP (Bt878) (= Prolink PV-BT878P+4E)
 
 Iomega
 ------
-   Buz (Zoran zr36067 + zr36060 + SAA7111 + SAA7185)
+   Buz (zr36067, zr36060, saa7111, saa7185)
 
 LML
 ---
-   LML33 (zr36067 + zr36060 + bt819+ bt856)
+   LML33 (zr36067, zr36060, bt819, bt856)
 
 Grandtec
 --------
    Grand Video Capture (Bt848)
    Multi Capture Card  (Bt878)
+
+Koutech
+-------
+   KW-606 (Bt848)
+   KW-607 (Bt848 capture only)
+   KW-606RSF
+   KW-607A (capture only)
+   KW-608 (Zoran capture only)
+ 
+IODATA (jp)
+------
+   GV-BCTV/PCI
+   GV-BCTV2/PCI
+   GV-BCTV3/PCI
+   GV-BCTV4/PCI
+   GV-VCP/PCI (capture only)
+   GV-VCP2/PCI (capture only)
+
+Canopus (jp)
+-------
+   WinDVR	= Kworld "KW-TVL878RF"
+
+www.sigmacom.co.kr 
+------------------
+   Sigma Cyber TV II 
+
+www.sasem.co.kr
+---------------
+   Litte OnAir TV
+
+hama 
+----
+   TV/Radio-Tuner Card, PCI (Model 44677) = CPH051
+
+Sigma Designs
+-------------
+   Hollywood plus (em8300, em9010, adv7175), (PCB "M340-10") MPEG DVD decoder
+
+Formac
+------
+   iProTV (Card for iMac Mezzanine slot, Bt848+SCSI)
+   ProTV (Bt848)
+   ProTV II = ProTV Stereo (Bt878)
+
+ATI
+---
+   TV-Wonder
+   TV-Wonder VE
+
+Diamond Multimedia
+------------------
+   DTV2000 (Bt848, tda9875)
+
+Aopen
+-----
+   VA1000 Plus (w/ Stereo)
+   VA1000 Lite
+   VA1000 (=LR90)
+
+Intel
+-----
+   Smart Video Recorder (ISA full-length)
+   Smart Video Recorder pro (ISA half-length)
+   Smart Video Recorder III (Bt848)
+
+STB
+---
+   TV PCI (Temic4032FY5, tda9850??)
+   other variants?
+
+Videologic
+----------
+   Captivator Pro/TV (ISA?)
+   Captivator PCI/VC (Bt848 bundled with camera) (capture only)
+
+Technotrend
+------------
+   TT-SAT PCI (PCB "Sat-PCI Rev.:1.3.1"; zr36125, vpx3225d, stc0056a, Tuner:BSKE6-155A
+   TT-DVB-Sat
+   TT-DVB-C PCI
+
+Teles
+-----
+   DVB-s (Rev. 2.2, BSRV2-301A, data only?)
+
+Remote Vision
+-------------
+   MX RV605 (Bt848 capture only)
+
+Boeder
+------
+   PC ChatCam (Model 68252) (Bt848 capture only)
+   Tv/Fm Capture Card  (Model 68404) = PV951
+
+Media-Surfer  (esc-kathrein.de)
+-------------------------------
+   Sat-Surfer (ISA)
+   Sat-Surfer PCI = Techni-PC-Sat
+   Cable-Surfer 1
+   Cable-Surfer 2
+   Cable-Surfer PCI (zr36120)
+   Audio-Surfer (ISA Radio card)
+
+Jetway (www.jetway.com.tw)
+--------------------------
+   JW-TV 878M 
+   JW-TV 878  = KWorld KW-TV878RF
+
+Galaxis
+-------
+   Galaxis DVB Card S CI
+   Galaxis DVB Card C CI
+   Galaxis DVB Card S
+   Galaxis DVB Card C
+
+Hauppauge
+---------
+   many many WinTV models ...
+   WinTV DVBs
+   WinTV NOVA
+   WinTV NOVA-CI
+   WinTV-Nexus-s
+
+Matrix-Vision
+-------------
+   MATRIX-Vision MV-Delta
+   MATRIX-Vision MV-Delta 2
+   MVsigma-SLC (Bt848)
+
+Conceptronic (.net)
+------------
+   TVCON FM,  TV card w/ FM = CPH05x
+
+BestData
+--------
+   HCC100 = VCC100rev1 + camera
+   VCC100 rev1 (bt848)
+   VCC100 rev2 (bt878)
+
+Gallant  (www.gallantcom.com) www.minton.com.tw
+-----------------------------------------------
+   Intervision IV-510 (capture only bt8x8)
+   Intervision IV-550 (bt8x8)
+   Intervision IV-100 (zoran)
+   Intervision IV-1000 (bt8x8)
+   
+Asonic (www.asonic.com.cn) (website down)
+-----------------------------------------
+   SkyEye tv 878
+
+Hoontech
+--------
+   878TV/FM
+
+Teppro (www.itcteppro.com.tw)
+-----------------------------
+   ITC PCITV (Card Ver 1.0) "Teppro TV1/TVFM1 Card"
+   ITC PCITV (Card Ver 2.0)
+   ITC PCITV (Card Ver 3.0) = "PV-BT878P+ (REV.9D)"
+   ITC PCITV (Card Ver 4.0)
+   TEPPRO IV-550 (For BT848 Main Chip)
+   ITC DSTTV (bt878, satellite)
+   ITC VideoMaker (saa7146, StreamMachine sm2110, tvtuner) "PV-SM2210P+ (REV:1C)"
+
+Kworld (www.kworld.com.tw)
+--------------------------
+   KWORLD KW-TV878RF-Pro TV Capture with FM Radio
+   KWORLD KW-TV878R-Pro TV
+   KWORLD KW-TVL878RF  (low profile)
+   KWORLD KW-TV878R TV Capture (No FM Radio)
+   KWORLD KW-TV878RF TV
+
+JTT/ Justy Corp.http://www.justy.co.jp/ (www.jtt.com.jp website down)
+---------------------------------------------------------------------
+   JTT-02 (JTT TV) "TV watchmate pro" (bt848) 
+
+ADS www.adstech.com
+-------------------
+   Channel Surfer TV ( CHX-950 ) 
+   Channel Surfer TV+FM ( CHX-960FM )
+
+AVEC www.prochips.com
+---------------------
+   AVEC Intercapture (bt848, tea6320)
+
+NoBrand
+-------
+   TV Excel = Australian Name for "PV-BT878P+ 8E" or so
+
+Mach www.machspeed.com
+----
+   Mach TV 878
+
+Eline www.eline-net.com/
+-----
+   Eline Vision TVMaster / TVMaster FM (ELV-TVM/ ELV-TVM-FM) = LR26  (bt878)
+   Eline Vision TVMaster-2000 (ELV-TVM-2000, ELV-TVM-2000-FM)= LR138 (saa713x)
+
+Spirit http://www.spiritmodems.com.au/
+------
+   Spirit TV Tuner/Video Capture Card (bt848)
+
+Boser www.boser.com.tw
+-----
+   HS-878 Mini PCI Capture Add-on Card
+   HS-879 Mini PCI 3D Audio and Capture Add-on Card (w/ ES1938 Solo-1)
+
+Satelco
+-------
+   TV-FM =KNC1 saa7134
+
+Sensoray www.sensoray.com
+--------
+   Sensoray 311 (PC/104 bus)
+   Sensoray 611 (PCI)
+
+CEI (Chartered Electronics Industries Pte Ltd [CEI] [FCC ID HBY])
+---
+  TV Tuner  -  HBY-33A-RAFFLES  Brooktree Bt848KPF + Philips
+  TV Tuner MG9910  -  HBY33A-TVO  CEI + Philips SAA7110 + OKI M548262 + ST STV8438CV
+  Primetime TV (ISA)
+   acquired by Singapore Technologies
+   now operating as Chartered Semiconductor Manufacturing
+   Manufacturer of video cards is listed as:
+   Cogent Electronics Industries [CEI]
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/bttv/Insmod-options linux/Documentation/video4linux/bttv/Insmod-options
--- linux.orig/Documentation/video4linux/bttv/Insmod-options	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/video4linux/bttv/Insmod-options	2002-08-12 22:14:05.000000000 +0000
@@ -29,7 +29,7 @@
 		irq_debug=0/1	irq handler debug messages.
 				default is 0 (off).
 		gbuffers=2-32	number of capture buffers for mmap'ed capture.
-				default is 2.
+				default is 4.
 		gbufsize=	size of capture buffers. default and
 				maximum value is 0x208000 (~2MB)
 		no_overlay=0	Enable overlay on broken hardware.  There
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/bttv/README linux/Documentation/video4linux/bttv/README
--- linux.orig/Documentation/video4linux/bttv/README	2001-08-05 20:15:05.000000000 +0000
+++ linux/Documentation/video4linux/bttv/README	2002-08-12 22:14:02.000000000 +0000
@@ -58,6 +58,9 @@
 		the helper modules.
 MAKEDEV:	a script to create the special files for v4l
 CARDLIST:	List of all supported cards
+Cards:		more detailed descriptions of known TV cards:
+		OEM name variants, used i2c chips, ...
+		also includes non-bttv cards.
 
 Loading just the bttv modules isn't enouth for most cards.  The
 drivers for the i2c tuner/sound chips must also be loaded.  bttv tries
@@ -73,6 +76,12 @@
 video but no sound you've very likely specified the wrong (or no)
 card type.  A list of supported cards is in CARDLIST.
 
+For the WinTV/PVR you need one firmware file from the driver CD:
+hcwamc.rbf.  The file is in the pvr45xxx.exe archive (self-extracting
+zip file, unzip can unpack it).  Put it into the /etc/pvr directory or
+use the firm_altera=<path> insmod option to point the driver to the
+location of the file.
+
 If your card isn't listed in CARDLIST or if you have trouble making
 audio work, you should read the Sound-FAQ.
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/bttv/README.freeze linux/Documentation/video4linux/bttv/README.freeze
--- linux.orig/Documentation/video4linux/bttv/README.freeze	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/video4linux/bttv/README.freeze	2002-08-12 22:14:09.000000000 +0000
@@ -46,6 +46,11 @@
 the PCI bus. The bt848/878 chips have a few workarounds for known
 incompatibilities, see README.quirks.
 
+Some folks report that increasing the pci latency helps too,
+althrought I'm not sure whenever this really fixes the problems or
+only makes it less likely to happen.  Both bttv and btaudio have a
+insmod option to set the PCI latency of the device.
+
 Some mainboard have problems to deal correctly with multiple devices
 doing DMA at the same time.  bttv + ide seems to cause this sometimes,
 if this is the case you likely see freezes only with video and hard disk
@@ -56,6 +61,9 @@
 other
 -----
 
+If you use some binary-only yunk (like nvidia module) try to reproduce
+the problem without.
+
 IRQ sharing is known to cause problems in some cases.  It works just
 fine in theory and many configurations.  Neverless it might be worth a
 try to shuffle around the PCI cards to give bttv another IRQ or make
@@ -63,3 +71,4 @@
 VGA cards seems to cause trouble sometimes.  I've also seen funny
 effects with bttv sharing the IRQ with the ACPI bridge (and
 apci-enabled kernel).
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/bttv/Tuners linux/Documentation/video4linux/bttv/Tuners
--- linux.orig/Documentation/video4linux/bttv/Tuners	2001-10-17 21:19:20.000000000 +0000
+++ linux/Documentation/video4linux/bttv/Tuners	2002-08-12 22:13:58.000000000 +0000
@@ -1,3 +1,16 @@
+1) Tuner Programming
+====================
+There are some flavors of Tuner programming APIs.
+These differ mainly by the bandswitch byte.
+
+    L= LG_API       (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04)
+    P= PHILIPS_API  (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04)
+    T= TEMIC_API    (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01)
+    A= ALPS_API     (VHF_LO=0x14, VHF_HI=0x12, UHF=0x11)
+    M= PHILIPS_MK3  (VHF_LO=0x01, VHF_HI=0x02, UHF=0x04, radio=0x19)
+
+2) Tuner Manufacturers
+======================
 
 SAMSUNG Tuner identification: (e.g. TCPM9091PD27)
   TCP [ABCJLMNQ] 90[89][125] [DP] [ACD] 27 [ABCD]
@@ -10,6 +23,7 @@
    M= BG+I+DK
    N= NTSC 
    Q= BG+I+DK+LL
+ [89]: ?
  [125]:
    2: No FM
    5: With FM
@@ -23,43 +37,49 @@
  [ABCD]:
    3-wire/I2C tuning, 2-band/3-band
 
+ These Tuners are PHILIPS_API compatible.
+
 Philips Tuner identification: (e.g. FM1216MF)
-  F[IRMQ]12[1345]{MF|ME|MP}
-  [IRMQ]:
-   I: Tuner Series
-   R: Tuner + Radio IF
-   M: Tuner + FM
-   Q,MR: specials
+  F[IRMQ]12[1345]6{MF|ME|MP}
+  F[IRMQ]:
+   FI12x6: Tuner Series
+   FR12x6: Tuner + Radio IF
+   FM12x6: Tuner + FM
+   FQ12x6: special
+   FMR12x6: special
    TD15xx: Digital Tuner ATSC
-  [1345]
-   1: PAL BG
-   3: NTSC
-   4: PAL I
-   5: Pal DK
+  12[1345]6:
+   1216: PAL BG
+   1236: NTSC
+   1246: PAL I
+   1256: Pal DK
   {MF|ME|MP}
-   MF: w/ Secam
-   ME: BD DK I LL
-   MP: BG DK I
+   MF: BG LL w/ Secam (Multi France)
+   ME: BG DK I LL   (Multi Europe)
+   MP: BG DK I      (Multi PAL)
    MR: BG DK M (?)
    MG: BG DKI M (?)
+  MK2 series PHILIPS_API, most tuners are compatible to this one !
+  MK3 series introduced in 2002 w/ PHILIPS_MK3_API
 
 Temic Tuner identification: (.e.g 4006FH5)
    4[01][0136][269]F[HYNR]5
-    40x2: Tuner (5V/33V), different I2C programming from Philips !
+    40x2: Tuner (5V/33V), TEMIC_API.
     40x6: Tuner 5V
     41xx: Tuner compact
     40x9: Tuner+FM compact
    [0136]
-    0: PAL BG
-    1: Pal DK, Secam LL
-    3: NTSC
-    6: PAL I
+    xx0x: PAL BG
+    xx1x: Pal DK, Secam LL
+    xx3x: NTSC
+    xx6x: PAL I
    F[HYNR]5
     FH5: Pal BG
     FY5: others
     FN5: multistandard
     FR5: w/ FM radio
    3X xxxx: order number with specific connector
+  Note: Only 40x2 series has TEMIC_API, all newer tuners have PHILIPS_API.
 
 LG Innotek Tuner:
   TPI8NSR11 : NTSC J/M    (TPI8NSR01 w/FM)  (P,210/497)
@@ -76,13 +96,20 @@
   TADC-H002F: NTSC (L,175/410?; 2-B, C-W+11, W+12-69)
   TADC-M201D: PAL D/K+B/G+I (L,143/425)  (sound control at I2C address 0xc8)
   TADC-T003F: NTSC Taiwan  (L,175/410?; 2-B, C-W+11, W+12-69)
-
-  (API,Lo-Hi-takeover/Hi-UHF-takeover)
-   I2C APIs:
-    L= LG programming (VHF_LO=0x01, VHF_HI=0x02, UHF=0x08, radio=0x04)
-    P= Philips progr. (VHF_LO=0xA0, VHF_HI=0x90, UHF=0x30, radio=0x04)
-    T= Temic progr.   (VHF_LO=0x02, VHF_HI=0x04, UHF=0x01)
   Suffix: 
     P= Standard phono female socket
     D= IEC female socket
     F= F-connector
+
+Other Tuners:
+TCL2002MB-1 : PAL BG + DK       =TUNER_LG_PAL_NEW_TAPC
+TCL2002MB-1F: PAL BG + DK w/FM  =PHILIPS_PAL
+TCL2002MI-2 : PAL I		= ??
+
+ALPS Tuners:
+   Most are LG_API compatible
+   TSCH6 has ALPS_API (TSCH5 ?)
+   TSBE1 has extra API 05,02,08 Control_byte=0xCB Source:(1)
+
+Lit.
+(1) conexant100029b-PCI-Decoder-ApplicationNote.pdf
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/video4linux/meye.txt linux/Documentation/video4linux/meye.txt
--- linux.orig/Documentation/video4linux/meye.txt	2002-08-03 00:39:42.000000000 +0000
+++ linux/Documentation/video4linux/meye.txt	2002-08-12 22:14:08.000000000 +0000
@@ -86,7 +86,7 @@
 
 	MEYEIOC_SYNC
 		Takes as an argument the buffer number you want to sync.
-		This ioctl blocks untils the buffer is filled and ready
+		This ioctl blocks until the buffer is filled and ready
 		for the application to use. It returns the buffer size.
 
 	MEYEIOC_STILLCAPT
@@ -106,7 +106,7 @@
 		
 	- mjpeg hardware playback doesn't work (depends on overlay...)
 
-	- rewrite the driver to use some commun video4linux API for snapshot
+	- rewrite the driver to use some common video4linux API for snapshot
 	  and mjpeg capture. Unfortunately, video4linux1 does not permit it,
 	  the BUZ API seems to be targeted to TV cards only. The video4linux 2
 	  API may be an option, if it goes into the kernel (maybe 2.5 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/x86_64/BUGS linux/Documentation/x86_64/BUGS
--- linux.orig/Documentation/x86_64/BUGS	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/x86_64/BUGS	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,10 @@
+Some known problems:
+
+-- Compiling the kernel with -j for parallel makes is not completely safe
+due to missing dependencies with offset.h. Usually it is safe when it 
+already exists, but not always.
+
+Current hack is to rerun make depend manually when you change anything
+that would touch offset.h (see arch/x86-64/tools/offset.c on what that is).
+Do not use -j with depend. 
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Documentation/x86_64/mm.txt linux/Documentation/x86_64/mm.txt
--- linux.orig/Documentation/x86_64/mm.txt	1970-01-01 00:00:00.000000000 +0000
+++ linux/Documentation/x86_64/mm.txt	2002-08-12 22:14:10.000000000 +0000
@@ -0,0 +1,194 @@
+The paging design used on the x86-64 linux kernel port in 2.4.x provides:
+
+o	per process virtual address space limit of 512 Gigabytes
+o	top of userspace stack located at address 0x0000007fffffffff
+o	PAGE_OFFSET = 0xffff800000000000
+o	start of the kernel mapping =  0x0000010000000000
+o	global RAM per system 508*512GB=254 Terabytes
+o	no need of any common code change
+o       512GB of vmalloc/ioremap space
+
+Description:
+        x86-64 has a 4 level page structure, similar to ia32 PSE but with
+        some extensions. Each level consits of a 4K page with 512 64bit
+        entries. The levels are named in Linux PML4, PGD, PMD, PTE; AMD calls them
+        PML4E, PDPE, PDE, PTE respectively. For direct and kernel mapping
+        only 3 levels are used with the PMD pointing to 2MB pages.
+          
+	Userspace is able to modify and it sees only the 3rd/2nd/1st level
+	pagetables (pgd_offset() implicitly walks the 1st slot of the 4th
+	level pagetable and it returns an entry into the 3rd level pagetable).
+	This is where the per-process 512 Gigabytes limit cames from.
+
+	The common code pgd is the PDPE, the pmd is the PDE, the
+	pte is the PTE. The PML4 remains invisible to the common
+	code.
+
+	Since the per-process limit is 512 Gigabytes (due to kernel common
+	code 3 level pagetable limitation), the higher virtual address mapped
+	into userspace is 0x7fffffffff and it makes sense to use it
+	as the top of the userspace stack to allow the stack to grow as
+	much as possible.
+
+	The kernel mapping and the direct memory mapping are split. Direct memory
+	mapping starts directly after userspace after a 512GB gap, while 
+	kernel mapping is at the end of (negative) virtual address space to exploit 
+	the kernel code model. There is no support for discontig memory, this
+	implies that kernel mapping/vmalloc/ioremap/module mapping are not 
+	represented in their "real" mapping in mem_map, but only with their
+	direct mapped (but normally not used) alias.
+	
+Future:
+
+	During 2.5.x we can break the 512 Gigabytes per-process limit
+	possibly by removing from the common code any knowledge about the
+	architectural dependent physical layout of the virtual to physical
+	mapping.
+
+	Once the 512 Gigabytes limit will be removed the kernel stack will
+	be moved (most probably to virtual address 0x00007fffffffffff).
+	Nothing	will break in userspace due that move, as nothing breaks
+	in IA32 compiling the kernel with CONFIG_2G.
+
+Linus agreed on not breaking common code and to live with the 512 Gigabytes
+per-process limitation for the 2.4.x timeframe and he has given me and Andi
+some very useful hints... (thanks! :)
+
+Thanks also to H. Peter Anvin for his interesting and useful suggestions on
+the x86-64-discuss lists!
+
+Current PML4 Layout:
+	Each CPU has an PML4 page that never changes. 
+	Each slot is 512GB of virtual memory. 
+ 
+        0    user space pgd or 40MB low mapping at bootup.  Changed at context switch.
+        1    unmapped
+        2    __PAGE_OFFSET - start of direct mapping of physical memory
+        ...  direct mapping in further slots as needed.
+        510  vmalloc and ioremap space
+	511  kernel code mapping, fixmaps and modules.  
+
+Other memory management related issues follows:
+
+PAGE_SIZE:
+
+	If somebody is wondering why these days we still have a so small
+	4k pagesize (16 or 32 kbytes would be much better for performance
+	of course), the PAGE_SIZE have to remain 4k for 32bit apps to
+	provide 100% backwards compatible IA32 API (we can't allow silent
+	fs corruption or as best a loss of coherency with the page cache
+	by allocating MAP_SHARED areas in MAP_ANONYMOUS memory with a
+	do_mmap_fake). I think it could be possible to have a dynamic page
+	size between 32bit and 64bit apps but it would need extremely
+	intrusive changes in the common code as first for page cache and
+	we sure don't want to depend on them right now even if the
+	hardware would support that.
+
+PAGETABLE SIZE:
+
+	In turn we can't afford to have pagetables larger than 4k because
+	we could not be able to allocate them due physical memory
+	fragmentation, and failing to allocate the kernel stack is a minor
+	issue compared to failing the allocation of a pagetable. If we
+	fail the allocation of a pagetable the only thing we can do is to
+	sched_yield polling the freelist (deadlock prone) or to segfault
+	the task (not even the sighandler would be sure to run).
+
+KERNEL STACK:
+
+	1st stage:
+
+	The kernel stack will be at first allocated with an order 2 allocation
+	(16k) (the utilization of the stack for a 64bit platform really
+	isn't exactly the double of a 32bit platform because the local
+	variables may not be all 64bit wide, but not much less). This will
+	make things even worse than they are right now on IA32 with
+	respect of failing fork/clone due memory fragmentation.
+
+	2nd stage:
+
+	We'll benchmark if reserving one register as task_struct
+	pointer will improve performance of the kernel (instead of
+	recalculating the task_struct pointer starting from the stack
+	pointer each time). My guess is that recalculating will be faster
+	but it worth a try.
+
+		If reserving one register for the task_struct pointer
+		will be faster we can as well split task_struct and kernel
+		stack. task_struct can be a slab allocation or a
+		PAGE_SIZEd allocation, and the kernel stack can then be
+		allocated in a order 1 allocation. Really this is risky,
+		since 8k on a 64bit platform is going to be less than 7k
+		on a 32bit platform but we could try it out. This would
+		reduce the fragmentation problem of an order of magnitude
+		making it equal to the current IA32.
+
+		We must also consider the x86-64 seems to provide in hardware a
+		per-irq stack that could allow us to remove the irq handler
+		footprint from the regular per-process-stack, so it could allow
+		us to live with a smaller kernel stack compared to the other
+		linux architectures.
+
+	3rd stage:
+
+	Before going into production if we still have the order 2
+	allocation we can add a sysctl that allows the kernel stack to be
+	allocated with vmalloc during memory fragmentation. This have to
+	remain turned off during benchmarks :) but it should be ok in real
+	life.
+
+Order of PAGE_CACHE_SIZE and other allocations:
+
+	On the long run we can increase the PAGE_CACHE_SIZE to be
+	an order 2 allocations and also the slab/buffercache etc.ec..
+	could be all done with order 2 allocations. To make the above
+	to work we should change lots of common code thus it can be done
+	only once the basic port will be in a production state. Having
+	a working PAGE_CACHE_SIZE would be a benefit also for
+	IA32 and other architectures of course.
+
+vmalloc:
+	vmalloc should be outside the first 512GB to keep that space free
+	for the user space. It needs an own pgd to work on in common code. 
+	It currently gets an own pgd in the 510th slot of the per CPU PML4.
+	
+PML4: 
+        Each CPU as an own PML4 (=top level of the 4 level page hierarchy). On 
+        context switch the first slot is rewritten to the pgd of the new process 
+        and CR3 is flushed.
+    
+Modules: 
+	Modules need to be in the same 4GB range as the core kernel. Otherwise
+	a GOT would be needed. Modules are currently at 0xffffffffa0000000
+        to 0xffffffffafffffff. This is inbetween the kernel text and the 
+        vsyscall/fixmap mappings.
+
+Vsyscalls: 
+        Vsyscalls have a reserved space near the end of user space that is 
+        acessible by user space. This address is part of the ABI and cannot be
+        changed. They have ffffffffff600000 to ffffffffffe00000 (but only 
+        some small space at the beginning is allocated and known to user space 
+        currently). See vsyscall.c for more details. 
+
+Fixmaps: 
+        Fixed mappings set up at boot. Used to access IO APIC and some other hardware. 
+        These are at the end of vsyscall space (ffffffffffe00000) downwards, 
+        but are not accessible by user space of course.
+
+Early mapping:
+        On a 120TB memory system bootmem could use upto 3.5GB
+        of memory for its bootmem bitmap. To avoid having to map 3.5GB by hand
+        for bootmem's purposes the full direct mapping is created before bootmem
+        is initialized. The direct mapping needs some memory for its page tables,
+        these are directly taken from the physical memory after the kernel. To
+        access these pages they need to be mapped, this is done by a temporary 
+        mapping with a few spare static 2MB PMD entries.
+
+Unsolved issues: 
+	 2MB pages for user space - may need to add a highmem zone for that again to 
+	 avoid fragmentation.
+  
+Andrea <andrea@suse.de> SuSE
+Andi Kleen <ak@suse.de> SuSE
+
+$Id$
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/MAINTAINERS linux/MAINTAINERS
--- linux.orig/MAINTAINERS	2002-08-03 00:39:42.000000000 +0000
+++ linux/MAINTAINERS	2002-08-12 22:14:02.000000000 +0000
@@ -266,6 +266,12 @@
 W:	http://bluez.sf.net
 S:	Maintained
 
+BLUETOOTH SUBSYSTEM (PC Card Drivers)
+P:	Marcel Holtmann
+M:	marcel@holtmann.org
+W:	http://www.holtmann.org/linux/bluetooth/
+S:	Maintained
+
 BTTV VIDEO4LINUX DRIVER
 P:	Gerd Knorr
 M:	kraxel@bytesex.org
@@ -1101,8 +1107,6 @@
 NETWORKING [IPv4/IPv6]
 P:	David S. Miller
 M:	davem@redhat.com
-P:	Andi Kleen
-M:	ak@muc.de
 P:	Alexey Kuznetsov
 M:	kuznet@ms2.inr.ac.ru
 P:	Pekka Savola (ipv6)
@@ -1541,6 +1545,13 @@
 M:	hch@infradead.org
 S:	Maintained
 
+TI GRAPH LINK USB (SilverLink) CABLE DRIVER
+P:      Romain Lievin
+M:      roms@lpg.ticalc.org
+P:      Julien Blache
+M:      jb@technologeek.org
+S:      Maintained
+
 TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER
 P:	Stephane Dalton
 M:	sdalton@videotron.ca
@@ -1856,6 +1867,13 @@
 M:	mingo@redhat.com
 S:	Maintained
 
+X86-64 port
+P:	Andi Kleen
+M:	ak@suse.de
+L:	discuss@x86-64.org
+W:	http://www.x86-64.org
+S:	Maintained
+
 YAM DRIVER FOR AX.25
 P:	Jean-Paul Roubelat
 M:	jpr@f6fbb.org
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/Makefile linux/Makefile
--- linux.orig/Makefile	2002-08-03 00:39:46.000000000 +0000
+++ linux/Makefile	2002-08-12 22:14:05.000000000 +0000
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 19
-EXTRAVERSION =
+SUBLEVEL = 20
+EXTRAVERSION = -pre2
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -170,7 +170,7 @@
 DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus_all.o
 DRIVERS-$(CONFIG_ZORRO) += drivers/zorro/driver.o
 DRIVERS-$(CONFIG_FC4) += drivers/fc4/fc4.a
-DRIVERS-$(CONFIG_PPC) += drivers/macintosh/macintosh.o
+DRIVERS-$(CONFIG_PPC32) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_MAC) += drivers/macintosh/macintosh.o
 DRIVERS-$(CONFIG_ISAPNP) += drivers/pnp/pnp.o
 DRIVERS-$(CONFIG_SGI_IP22) += drivers/sgi/sgi.a
@@ -369,7 +369,7 @@
 TAGS: dummy
 	{ find include/asm-${ARCH} -name '*.h' -print ; \
 	find include -type d \( -name "asm-*" -o -name config \) -prune -o -name '*.h' -print ; \
-	find $(SUBDIRS) init arch/${ARCH} -name '*.[chS]' ; } | grep -v SCCS | etags -
+	find $(SUBDIRS) init arch/${ARCH} -name '*.[chS]' ; } | grep -v SCCS | grep -v '\.svn' | etags -
 
 # Exuberant ctags works better with -I
 tags: dummy
@@ -487,7 +487,7 @@
 
 dep-files: scripts/mkdep archdep include/linux/version.h
 	scripts/mkdep -- init/*.c > .depend
-	scripts/mkdep -- `find $(FINDHPATH) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
+	scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend
 	$(MAKE) $(patsubst %,_sfdep_%,$(SUBDIRS)) _FASTDEP_ALL_SUB_DIRS="$(SUBDIRS)"
 ifdef CONFIG_MODVERSIONS
 	$(MAKE) update-modverfile
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/alpha/config.in linux/arch/alpha/config.in
--- linux.orig/arch/alpha/config.in	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/alpha/config.in	2002-08-12 22:14:09.000000000 +0000
@@ -250,9 +250,9 @@
 fi
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-   bool 'Discontiguous Memory Support' CONFIG_DISCONTIGMEM
+   bool 'Discontiguous Memory Support (EXPERIMENTAL)' CONFIG_DISCONTIGMEM
    if [ "$CONFIG_DISCONTIGMEM" = "y" ]; then
-      bool ' NUMA Support' CONFIG_NUMA
+      bool ' NUMA Support (EXPERIMENTAL)' CONFIG_NUMA
    fi
 fi
 
@@ -360,7 +360,7 @@
 mainmenu_option next_comment
 comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
-bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
+bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
   source drivers/cdrom/Config.in
 fi
@@ -423,3 +423,5 @@
 fi
 
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- linux.orig/arch/alpha/kernel/traps.c	2001-11-20 23:49:31.000000000 +0000
+++ linux/arch/alpha/kernel/traps.c	2002-08-12 22:14:10.000000000 +0000
@@ -167,6 +167,11 @@
 	dik_show_trace(sp);
 }
 
+void dump_stack(void)
+{
+	show_stack(NULL);
+}
+
 void
 die_if_kernel(char * str, struct pt_regs *regs, long err, unsigned long *r9_15)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/arm/config.in linux/arch/arm/config.in
--- linux.orig/arch/arm/config.in	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/arm/config.in	2002-08-12 22:14:07.000000000 +0000
@@ -417,7 +417,7 @@
 fi
 
 source drivers/pci/Config.in
-bool 'Support hot-pluggable devices' CONFIG_HOTPLUG
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
 if [ "$CONFIG_HOTPLUG" = "y" ]; then
    source drivers/pcmcia/Config.in
 else
@@ -503,7 +503,7 @@
    mainmenu_option next_comment
    comment 'Network device support'
 
-   bool 'Network device support?' CONFIG_NETDEVICES
+   bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
       source drivers/net/Config.in
    fi
@@ -530,7 +530,7 @@
 mainmenu_option next_comment
 comment 'SCSI support'
 
-tristate 'SCSI support?' CONFIG_SCSI
+tristate 'SCSI support' CONFIG_SCSI
 
 if [ "$CONFIG_SCSI" != "n" ]; then
    source drivers/scsi/Config.in
@@ -618,7 +618,7 @@
    mainmenu_option next_comment
    comment 'Sound'
 
-   tristate 'Sound support' CONFIG_SOUND
+   tristate 'Sound card support' CONFIG_SOUND
    if [ "$CONFIG_SOUND" != "n" ]; then
       source drivers/sound/Config.in
    fi
@@ -655,3 +655,5 @@
 dep_bool '    Kernel low-level debugging messages via footbridge serial port' CONFIG_DEBUG_DC21285_PORT $CONFIG_DEBUG_LL $CONFIG_FOOTBRIDGE
 dep_bool '    Kernel low-level debugging messages via UART2' CONFIG_DEBUG_CLPS711X_UART2 $CONFIG_DEBUG_LL $CONFIG_ARCH_CLPS711X
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/cris/config.in linux/arch/cris/config.in
--- linux.orig/arch/cris/config.in	2002-02-25 19:37:52.000000000 +0000
+++ linux/arch/cris/config.in	2002-08-12 22:14:00.000000000 +0000
@@ -253,4 +253,6 @@
 if [ "$CONFIG_PROFILE" = "y" ]; then
   int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
 fi
+
+source lib/Config.in
 endmenu
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/cris/drivers/usb-host.c linux/arch/cris/drivers/usb-host.c
--- linux.orig/arch/cris/drivers/usb-host.c	2002-02-25 19:37:52.000000000 +0000
+++ linux/arch/cris/drivers/usb-host.c	2002-08-12 22:14:13.000000000 +0000
@@ -193,17 +193,17 @@
 static USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4)));
 static USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4)));
 
-static urb_t *URB_List[NBR_OF_EP_DESC];
+static struct urb *URB_List[NBR_OF_EP_DESC];
 static kmem_cache_t *usb_desc_cache;
 static struct usb_bus *etrax_usb_bus;
 
 #ifdef USB_DEBUG_DESC
-static void dump_urb (purb_t purb);
+static void dump_urb (struct urb *urb);
 #endif
 static void init_rx_buffers(void);
-static int etrax_rh_unlink_urb (urb_t *urb);
-static void etrax_rh_send_irq(urb_t *urb);
-static void etrax_rh_init_int_timer(urb_t *urb);
+static int etrax_rh_unlink_urb (struct urb *urb);
+static void etrax_rh_send_irq(struct urb *urb);
+static void etrax_rh_init_int_timer(struct urb *urb);
 static void etrax_rh_int_timer_do(unsigned long ptr);
 
 static void etrax_usb_setup_epid(int epid, char devnum, char endpoint,
@@ -214,13 +214,13 @@
 static void etrax_usb_free_epid(int epid);
 static void cleanup_sb(USB_SB_Desc_t *sb);
 
-static void etrax_usb_do_ctrl_hw_add(urb_t *urb, int epid, char maxlen);
-static void etrax_usb_do_bulk_hw_add(urb_t *urb, int epid, char maxlen);
+static void etrax_usb_do_ctrl_hw_add(struct urb *urb, int epid, char maxlen);
+static void etrax_usb_do_bulk_hw_add(struct urb *urb, int epid, char maxlen);
 
-static int etrax_usb_submit_ctrl_urb(urb_t *urb);
+static int etrax_usb_submit_ctrl_urb(struct urb *urb);
 
-static int etrax_usb_submit_urb(urb_t *urb);
-static int etrax_usb_unlink_urb(urb_t *urb);
+static int etrax_usb_submit_urb(struct urb *urb);
+static int etrax_usb_unlink_urb(struct urb *urb);
 static int etrax_usb_get_frame_number(struct usb_device *usb_dev);
 static int etrax_usb_allocate_dev(struct usb_device *usb_dev);
 static int etrax_usb_deallocate_dev(struct usb_device *usb_dev);
@@ -229,7 +229,7 @@
 static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs);
 static void etrax_usb_hc_intr_top_half(int irq, void *vhc, struct pt_regs *regs);
 
-static int etrax_rh_submit_urb (urb_t *urb);
+static int etrax_rh_submit_urb (struct urb *urb);
 
 static int etrax_usb_hc_init(void);
 static void etrax_usb_hc_cleanup(void);
@@ -244,24 +244,24 @@
 };
 
 #ifdef USB_DEBUG_DESC
-static void dump_urb(purb_t purb)
+static void dump_urb(struct urb *urb)
 {
-	printk("\nurb                   :0x%08X\n", purb);
-	printk("next                  :0x%08X\n", purb->next);
-	printk("dev                   :0x%08X\n", purb->dev);
-	printk("pipe                  :0x%08X\n", purb->pipe);
-	printk("status                :%d\n", purb->status);
-	printk("transfer_flags        :0x%08X\n", purb->transfer_flags);
-	printk("transfer_buffer       :0x%08X\n", purb->transfer_buffer);
-	printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
-	printk("actual_length         :%d\n", purb->actual_length);
-	printk("setup_packet          :0x%08X\n", purb->setup_packet);
-	printk("start_frame           :%d\n", purb->start_frame);
-	printk("number_of_packets     :%d\n", purb->number_of_packets);
-	printk("interval              :%d\n", purb->interval);
-	printk("error_count           :%d\n", purb->error_count);
-	printk("context               :0x%08X\n", purb->context);
-	printk("complete              :0x%08X\n\n", purb->complete);
+	printk("\nurb                   :0x%08X\n", urb);
+	printk("next                  :0x%08X\n", urb->next);
+	printk("dev                   :0x%08X\n", urb->dev);
+	printk("pipe                  :0x%08X\n", urb->pipe);
+	printk("status                :%d\n", urb->status);
+	printk("transfer_flags        :0x%08X\n", urb->transfer_flags);
+	printk("transfer_buffer       :0x%08X\n", urb->transfer_buffer);
+	printk("transfer_buffer_length:%d\n", urb->transfer_buffer_length);
+	printk("actual_length         :%d\n", urb->actual_length);
+	printk("setup_packet          :0x%08X\n", urb->setup_packet);
+	printk("start_frame           :%d\n", urb->start_frame);
+	printk("number_of_packets     :%d\n", urb->number_of_packets);
+	printk("interval              :%d\n", urb->interval);
+	printk("error_count           :%d\n", urb->error_count);
+	printk("context               :0x%08X\n", urb->context);
+	printk("complete              :0x%08X\n\n", urb->complete);
 }
 
 static void dump_in_desc(USB_IN_Desc_t *in)
@@ -425,7 +425,7 @@
 }
 
 
-static int etrax_usb_unlink_intr_urb(urb_t *urb)
+static int etrax_usb_unlink_intr_urb(struct urb *urb)
 {
 	USB_EP_Desc_t *tmp_ep;
 	USB_EP_Desc_t *first_ep;
@@ -511,7 +511,7 @@
 	} while (tmp_ep != first_ep);
 }
 
-static int etrax_usb_submit_intr_urb(urb_t *urb)
+static int etrax_usb_submit_intr_urb(struct urb *urb)
 {
 	USB_EP_Desc_t *tmp_ep;
 	USB_EP_Desc_t *first_ep;
@@ -641,7 +641,7 @@
 
 static void handle_intr_transfer_attn(int epid, int status)
 {
-	urb_t *old_urb;
+	struct urb *old_urb;
 
 	DBFENTER;
 
@@ -694,7 +694,7 @@
 	DBFEXIT;
 }
 
-static int etrax_rh_unlink_urb (urb_t *urb)
+static int etrax_rh_unlink_urb (struct urb *urb)
 {
 	etrax_hc_t *hc;
 	
@@ -711,7 +711,7 @@
 	return 0;
 }
 
-static void etrax_rh_send_irq(urb_t *urb)
+static void etrax_rh_send_irq(struct urb *urb)
 {
 	__u16 data = 0;
 	etrax_hc_t *hc = urb->dev->bus->hcpriv;
@@ -744,7 +744,7 @@
 /*	DBFEXIT; */
 }
 
-static void etrax_rh_init_int_timer(urb_t *urb)
+static void etrax_rh_init_int_timer(struct urb *urb)
 {
 	etrax_hc_t *hc;
 	
@@ -763,12 +763,12 @@
 
 static void etrax_rh_int_timer_do(unsigned long ptr)
 {
-	urb_t *urb;
+	struct urb *urb;
 	etrax_hc_t *hc;
 	
 /*	DBFENTER; */
 	
-	urb = (urb_t*)ptr;
+	urb = (struct urb*)ptr;
 	hc = urb->dev->bus->hcpriv;
 	
 	if (hc->rh.send) {
@@ -910,7 +910,7 @@
 	return -1;
 }
 
-static int etrax_usb_submit_bulk_urb(urb_t *urb)
+static int etrax_usb_submit_bulk_urb(struct urb *urb)
 {
 	int epid;
 	char devnum;
@@ -919,7 +919,7 @@
 	char out_traffic;
 	char slow;
 
-	urb_t *tmp_urb;
+	struct urb *tmp_urb;
 	
 	unsigned long flags;
 	
@@ -969,7 +969,7 @@
 	return 0;
 }
 
-static void etrax_usb_do_bulk_hw_add(urb_t *urb, int epid, char maxlen)
+static void etrax_usb_do_bulk_hw_add(struct urb *urb, int epid, char maxlen)
 {
 	USB_SB_Desc_t *sb_desc_1;
 
@@ -1086,7 +1086,7 @@
 
 static void handle_bulk_transfer_attn(int epid, int status)
 {
-	urb_t *old_urb;
+	struct urb *old_urb;
 	etrax_urb_priv_t *hc_priv;
 	unsigned long flags;
 
@@ -1166,7 +1166,7 @@
 
 /* ---------------------------------------------------------------------------- */
 
-static int etrax_usb_submit_ctrl_urb(urb_t *urb)
+static int etrax_usb_submit_ctrl_urb(struct urb *urb)
 {
 	int epid;
 	char devnum;
@@ -1175,7 +1175,7 @@
 	char out_traffic;
 	char slow;
 
-	urb_t *tmp_urb;
+	struct urb *tmp_urb;
 	
 	unsigned long flags;
 	
@@ -1225,7 +1225,7 @@
 	return 0;
 }
 
-static void etrax_usb_do_ctrl_hw_add(urb_t *urb, int epid, char maxlen)
+static void etrax_usb_do_ctrl_hw_add(struct urb *urb, int epid, char maxlen)
 {
 	USB_SB_Desc_t *sb_desc_1;
 	USB_SB_Desc_t *sb_desc_2;
@@ -1364,7 +1364,7 @@
 	DBFEXIT;
 }
 
-static int etrax_usb_submit_urb(urb_t *urb)
+static int etrax_usb_submit_urb(struct urb *urb)
 {
 	etrax_hc_t *hc;
 	int rval = -EINVAL;
@@ -1411,7 +1411,7 @@
 	return rval;
 }
 
-static int etrax_usb_unlink_urb(urb_t *urb)
+static int etrax_usb_unlink_urb(struct urb *urb)
 {
 	etrax_hc_t *hc = urb->dev->bus->hcpriv;
 	int epid;
@@ -1455,8 +1455,8 @@
 	cli();
 	
 	for (epid = 0; epid < 32; epid++) {
-		urb_t *u = URB_List[epid];
-		urb_t *prev = NULL;
+		struct urb *u = URB_List[epid];
+		struct urb *prev = NULL;
 		int pos = 0;
 
 		for (; u; u = u->next) {
@@ -1557,7 +1557,7 @@
 static void etrax_usb_rx_interrupt(int irq, void *vhc, struct pt_regs *regs)
 {
 	int epid = 0;
-	urb_t *urb;
+	struct urb *urb;
 	etrax_urb_priv_t *urb_priv;
 		
 	*R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do);
@@ -1655,7 +1655,7 @@
 
 static void handle_control_transfer_attn(int epid, int status)
 {
-	urb_t *old_urb;
+	struct urb *old_urb;
 	etrax_urb_priv_t *hc_priv;	
 
 	DBFENTER;
@@ -1981,12 +1981,12 @@
 	DBFEXIT;
 }
 
-static int etrax_rh_submit_urb(urb_t *urb)
+static int etrax_rh_submit_urb(struct urb *urb)
 {
 	struct usb_device *usb_dev = urb->dev;
 	etrax_hc_t *hc = usb_dev->bus->hcpriv;
 	unsigned int pipe = urb->pipe;
-	devrequest *cmd = (devrequest *) urb->setup_packet;
+	struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet;
 	void *data = urb->transfer_buffer;
 	int leni = urb->transfer_buffer_length;
 	int len = 0;
@@ -2010,10 +2010,10 @@
 		return 0;
 	}
 
-	bmRType_bReq = cmd->requesttype | cmd->request << 8;
-	wValue = le16_to_cpu(cmd->value);
-	wIndex = le16_to_cpu(cmd->index);
-	wLength = le16_to_cpu(cmd->length);
+	bmRType_bReq = cmd->bRequestType | cmd->bRequest << 8;
+	wValue = le16_to_cpu(cmd->wValue);
+	wIndex = le16_to_cpu(cmd->wIndex);
+	wLength = le16_to_cpu(cmd->wLength);
 
 	dbg_rh("bmRType_bReq : 0x%04X (%d)", bmRType_bReq, bmRType_bReq);
 	dbg_rh("wValue       : 0x%04X (%d)", wValue, wValue);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/cris/kernel/traps.c linux/arch/cris/kernel/traps.c
--- linux.orig/arch/cris/kernel/traps.c	2002-02-25 19:37:52.000000000 +0000
+++ linux/arch/cris/kernel/traps.c	2002-08-12 22:14:25.000000000 +0000
@@ -230,8 +230,12 @@
 #endif	
 }
 
-/* This is normally the 'Oops' routine */
+void dump_stack(void)
+{
+	show_stack(NULL);
+}
 
+/* This is normally the 'Oops' routine */
 void 
 die_if_kernel(const char * str, struct pt_regs * regs, long err)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- linux.orig/arch/i386/boot/compressed/misc.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/boot/compressed/misc.c	2002-08-12 22:14:22.000000000 +0000
@@ -9,6 +9,8 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
+#define STANDALONE
+
 #include <linux/linkage.h>
 #include <linux/vmalloc.h>
 #include <linux/tty.h>
@@ -124,10 +126,6 @@
 static int vidport;
 static int lines, cols;
 
-#ifdef CONFIG_MULTIQUAD
-static void * const xquad_portio = NULL;
-#endif
-
 #include "../../../../lib/inflate.c"
 
 static void *malloc(int size)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/config.in linux/arch/i386/config.in
--- linux.orig/arch/i386/config.in	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/config.in	2002-08-12 22:14:13.000000000 +0000
@@ -5,7 +5,6 @@
 mainmenu_name "Linux Kernel Configuration"
 
 define_bool CONFIG_X86 y
-define_bool CONFIG_ISA y
 define_bool CONFIG_SBUS n
 
 define_bool CONFIG_UID16 y
@@ -54,6 +53,7 @@
    define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
    define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
    define_bool CONFIG_X86_PPRO_FENCE y
+   define_bool CONFIG_X86_F00F_WORKS_OK n
 else
    define_bool CONFIG_X86_WP_WORKS_OK y
    define_bool CONFIG_X86_INVLPG y
@@ -69,12 +69,14 @@
    define_bool CONFIG_X86_USE_STRING_486 y
    define_bool CONFIG_X86_ALIGNMENT_16 y
    define_bool CONFIG_X86_PPRO_FENCE y
+   define_bool CONFIG_X86_F00F_WORKS_OK n
 fi
 if [ "$CONFIG_M586" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
    define_bool CONFIG_X86_USE_STRING_486 y
    define_bool CONFIG_X86_ALIGNMENT_16 y
    define_bool CONFIG_X86_PPRO_FENCE y
+   define_bool CONFIG_X86_F00F_WORKS_OK n
 fi
 if [ "$CONFIG_M586TSC" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -82,6 +84,7 @@
    define_bool CONFIG_X86_ALIGNMENT_16 y
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_PPRO_FENCE y
+   define_bool CONFIG_X86_F00F_WORKS_OK n
 fi
 if [ "$CONFIG_M586MMX" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -90,6 +93,7 @@
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_PPRO_FENCE y
+   define_bool CONFIG_X86_F00F_WORKS_OK n
 fi
 if [ "$CONFIG_M686" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -98,6 +102,7 @@
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
    define_bool CONFIG_X86_PPRO_FENCE y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MPENTIUMIII" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -105,6 +110,7 @@
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MPENTIUM4" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 7
@@ -112,6 +118,7 @@
    define_bool CONFIG_X86_GOOD_APIC y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MK6" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -126,11 +133,13 @@
    define_bool CONFIG_X86_USE_3DNOW y
    define_bool CONFIG_X86_PGE y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MELAN" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 4
    define_bool CONFIG_X86_USE_STRING_486 y
    define_bool CONFIG_X86_ALIGNMENT_16 y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MCYRIXIII" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -142,12 +151,14 @@
 if [ "$CONFIG_MCRUSOE" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
    define_bool CONFIG_X86_TSC y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MWINCHIPC6" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
    define_bool CONFIG_X86_ALIGNMENT_16 y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
    define_bool CONFIG_X86_OOSTORE y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MWINCHIP2" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -155,6 +166,7 @@
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
    define_bool CONFIG_X86_OOSTORE y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 if [ "$CONFIG_MWINCHIP3D" = "y" ]; then
    define_int  CONFIG_X86_L1_CACHE_SHIFT 5
@@ -162,6 +174,7 @@
    define_bool CONFIG_X86_TSC y
    define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
    define_bool CONFIG_X86_OOSTORE y
+   define_bool CONFIG_X86_F00F_WORKS_OK y
 fi
 
 bool 'Machine Check Exception' CONFIG_X86_MCE
@@ -177,14 +190,19 @@
 	"off    CONFIG_NOHIGHMEM \
 	 4GB    CONFIG_HIGHMEM4G \
 	 64GB   CONFIG_HIGHMEM64G" off
-if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
+if [ "$CONFIG_HIGHMEM4G" = "y" -o "$CONFIG_HIGHMEM64G" = "y" ]; then
    define_bool CONFIG_HIGHMEM y
+else
+   define_bool CONFIG_HIGHMEM n
 fi
 if [ "$CONFIG_HIGHMEM64G" = "y" ]; then
-   define_bool CONFIG_HIGHMEM y
    define_bool CONFIG_X86_PAE y
 fi
 
+if [ "$CONFIG_HIGHMEM" = "y" ]; then
+   bool 'HIGHMEM I/O support' CONFIG_HIGHIO
+fi
+
 bool 'Math emulation' CONFIG_MATH_EMULATION
 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 bool 'Symmetric multi-processing support' CONFIG_SMP
@@ -218,6 +236,7 @@
    define_bool CONFIG_X86_VISWS_APIC y
    define_bool CONFIG_X86_LOCAL_APIC y
    define_bool CONFIG_PCI y
+   define_bool CONFIG_ISA n
 else
    if [ "$CONFIG_SMP" = "y" ]; then
       define_bool CONFIG_X86_IO_APIC y
@@ -236,6 +255,7 @@
          define_bool CONFIG_PCI_DIRECT y
       fi
    fi
+   bool 'ISA bus support' CONFIG_ISA
 fi
 
 source drivers/pci/Config.in
@@ -366,14 +386,16 @@
 fi
 endmenu
 
-mainmenu_option next_comment
-comment 'Old CD-ROM drivers (not SCSI, not IDE)'
-
-bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
-if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-   source drivers/cdrom/Config.in
+if [ "$CONFIG_ISA" = "y" ]; then
+    mainmenu_option next_comment
+    comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+
+    bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
+    if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+       source drivers/cdrom/Config.in
+    fi
+    endmenu
 fi
-endmenu
 
 #
 # input before char - char/joystick depends on it. As does USB.
@@ -417,6 +439,7 @@
 
 bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
 if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+   bool '  Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW
    bool '  Debug high memory support' CONFIG_DEBUG_HIGHMEM
    bool '  Debug memory allocations' CONFIG_DEBUG_SLAB
    bool '  Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
@@ -426,3 +449,5 @@
 fi
 
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- linux.orig/arch/i386/kernel/apic.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/apic.c	2002-08-12 22:14:19.000000000 +0000
@@ -1050,7 +1050,7 @@
 /*
  * Local APIC timer interrupt. This is the most natural way for doing
  * local interrupts, but local timer interrupts can be emulated by
- * broadcast interrupts too. [in case the hw doesnt support APIC timers]
+ * broadcast interrupts too. [in case the hw doesn't support APIC timers]
  *
  * [ if a single-CPU system runs an SMP kernel then we call the local
  *   interrupt as well. Thus we cannot inline the local irq ... ]
@@ -1130,7 +1130,7 @@
 	   6: Received illegal vector
 	   7: Illegal register address
 	*/
-	printk (KERN_ERR "APIC error on CPU%d: %02lx(%02lx)\n",
+	printk (KERN_INFO "APIC error on CPU%d: %02lx(%02lx)\n",
 	        smp_processor_id(), v , v1);
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- linux.orig/arch/i386/kernel/apm.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/apm.c	2002-08-12 22:14:02.000000000 +0000
@@ -847,6 +847,7 @@
 			case 1: apm_idle_done = 1;
 				break;
 			default: /* BIOS refused */
+				break;
 			}
 		}
 		if (original_pm_idle)
@@ -862,14 +863,6 @@
 		apm_do_busy();
 }
 
-#ifdef CONFIG_SMP
-static int apm_magic(void * unused)
-{
-	while (1)
-		schedule();
-}
-#endif
-
 /**
  *	apm_power_off	-	ask the BIOS to power off
  *
@@ -897,10 +890,11 @@
 	 */
 #ifdef CONFIG_SMP
 	/* Some bioses don't like being called from CPU != 0 */
-	while (cpu_number_map(smp_processor_id()) != 0) {
-		kernel_thread(apm_magic, NULL,
-			CLONE_FS | CLONE_FILES | CLONE_SIGHAND | SIGCHLD);
+	if (cpu_number_map(smp_processor_id()) != 0) {
+		current->cpus_allowed = 1;
 		schedule();
+		if (unlikely(cpu_number_map(smp_processor_id()) != 0))
+			BUG();
 	}
 #endif
 	if (apm_info.realmode_power_off)
@@ -1661,6 +1655,21 @@
 	strcpy(current->comm, "kapmd");
 	sigfillset(&current->blocked);
 
+#ifdef CONFIG_SMP
+	/* 2002/08/01 - WT
+	 * This is to avoid random crashes at boot time during initialization
+	 * on SMP systems in case of "apm=power-off" mode. Seen on ASUS A7M266D.
+	 * Some bioses don't like being called from CPU != 0.
+	 * Method suggested by Ingo Molnar.
+	 */
+	if (cpu_number_map(smp_processor_id()) != 0) {
+		current->cpus_allowed = 1;
+		schedule();
+		if (unlikely(cpu_number_map(smp_processor_id()) != 0))
+			BUG();
+	}
+#endif
+	
 	if (apm_info.connection_version == 0) {
 		apm_info.connection_version = apm_info.bios.version;
 		if (apm_info.connection_version > 0x100) {
@@ -1707,7 +1716,7 @@
 		}
 	}
 
-	if (debug && (smp_num_cpus == 1)) {
+	if (debug) {
 		error = apm_get_power_status(&bx, &cx, &dx);
 		if (error)
 			printk(KERN_INFO "apm: power status not available\n");
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- linux.orig/arch/i386/kernel/dmi_scan.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/dmi_scan.c	2002-08-12 22:14:15.000000000 +0000
@@ -190,7 +190,6 @@
  *	KT7 series. On these it seems the newer BIOS has fixed them. The
  *	rule needs to be improved to match specific BIOS revisions with
  *	corruption problems
- */ 
  
 static __init int disable_ide_dma(struct dmi_blacklist *d)
 {
@@ -204,6 +203,7 @@
 #endif	
 	return 0;
 }
+ */ 
 
 /* 
  * Reboot options and system auto-detection code provided by
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- linux.orig/arch/i386/kernel/io_apic.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/io_apic.c	2002-08-12 22:14:14.000000000 +0000
@@ -716,7 +716,7 @@
 	entry.vector = vector;
 
 	/*
-	 * The timer IRQ doesnt have to know that behind the
+	 * The timer IRQ doesn't have to know that behind the
 	 * scene we have a 8259A-master in AEOI mode ...
 	 */
 	irq_desc[0].handler = &ioapic_edge_irq_type;
@@ -1586,7 +1586,7 @@
 	printk(" failed.\n");
 
 	if (nmi_watchdog) {
-		printk(KERN_WARNING "timer doesnt work through the IO-APIC - disabling NMI Watchdog!\n");
+		printk(KERN_WARNING "timer doesn't work through the IO-APIC - disabling NMI Watchdog!\n");
 		nmi_watchdog = 0;
 	}
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- linux.orig/arch/i386/kernel/irq.c	2001-10-25 20:53:46.000000000 +0000
+++ linux/arch/i386/kernel/irq.c	2002-08-12 22:14:03.000000000 +0000
@@ -577,6 +577,20 @@
 	irq_desc_t *desc = irq_desc + irq;
 	struct irqaction * action;
 	unsigned int status;
+#ifdef CONFIG_DEBUG_STACKOVERFLOW
+	long esp;
+
+	/* Debugging check for stack overflow: is there less than 1KB free? */
+	__asm__ __volatile__("andl %%esp,%0" : "=r" (esp) : "0" (8191));
+	if (unlikely(esp < (sizeof(struct task_struct) + 1024))) {
+		extern void show_stack(unsigned long *);
+
+		printk("do_IRQ: stack overflow: %ld\n",
+			esp - sizeof(struct task_struct));
+		__asm__ __volatile__("movl %%esp,%0" : "=r" (esp));
+		show_stack((void *)esp);
+	}
+#endif
 
 	kstat.irqs[cpu][irq]++;
 	spin_lock(&desc->lock);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c
--- linux.orig/arch/i386/kernel/mpparse.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/mpparse.c	2002-08-12 22:14:13.000000000 +0000
@@ -115,6 +115,8 @@
 		case 0x0F:
 			if (model == 0x00)
 				return("Pentium 4(tm)");
+			if (model == 0x02)
+				return("Pentium 4(tm) XEON(tm)");
 			if (model == 0x0F)
 				return("Special controller");
 	}
@@ -815,7 +817,7 @@
 
 /*
  * The Visual Workstation is Intel MP compliant in the hardware
- * sense, but it doesnt have a BIOS(-configuration table).
+ * sense, but it doesn't have a BIOS(-configuration table).
  * No problem for Linux.
  */
 void __init find_visws_smp(void)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- linux.orig/arch/i386/kernel/setup.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/setup.c	2002-08-12 22:14:19.000000000 +0000
@@ -171,10 +171,14 @@
 extern int root_mountflags;
 extern char _text, _etext, _edata, _end;
 
+static int have_cpuid_p(void) __init;
+
 static int disable_x86_serial_nr __initdata = 1;
 static int disable_x86_fxsr __initdata = 0;
 static int disable_x86_ht __initdata = 0;
 
+extern int blk_nohighio;
+
 int enable_acpi_smp_table;
 
 #if defined(CONFIG_AGP) || defined(CONFIG_AGP_MODULE)
@@ -871,13 +875,17 @@
 void __init setup_arch(char **cmdline_p)
 {
 	unsigned long bootmap_size, low_mem_size;
-	unsigned long start_pfn, max_pfn, max_low_pfn;
+	unsigned long start_pfn, max_low_pfn;
 	int i;
 
 #ifdef CONFIG_VISWS
 	visws_get_board_type_and_rev();
 #endif
 
+#ifndef CONFIG_HIGHIO
+	blk_nohighio = 1;
+#endif
+
  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
  	drive_info = DRIVE_INFO;
  	screen_info = SCREEN_INFO;
@@ -1206,6 +1214,14 @@
 __setup("notsc", tsc_setup);
 #endif
 
+static int __init highio_setup(char *str)
+{
+	printk("i386: disabling HIGHMEM block I/O\n");
+	blk_nohighio = 1;
+	return 1;
+}
+__setup("nohighio", highio_setup);
+
 static int __init get_model_name(struct cpuinfo_x86 *c)
 {
 	unsigned int *v;
@@ -1534,7 +1550,7 @@
  * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
  * order to identify the Cyrix CPU model after we're out of setup.c
  *
- * Actually since bugs.h doesnt even reference this perhaps someone should
+ * Actually since bugs.h doesn't even reference this perhaps someone should
  * fix the documentation ???
  */
 static unsigned char Cx86_dir0_msb __initdata = 0;
@@ -2227,31 +2243,69 @@
 
 extern void trap_init_f00f_bug(void);
 
+#define LVL_1_INST      1
+#define LVL_1_DATA      2
+#define LVL_2           3
+#define LVL_3           4
+
+struct _cache_table
+{
+        unsigned char descriptor;
+        char cache_type;
+        short size;
+};
+
+/* all the cache descriptor types we care about (no TLB or trace cache entries) */
+static struct _cache_table cache_table[] __initdata =
+{
+	{ 0x06, LVL_1_INST, 8 },
+	{ 0x08, LVL_1_INST, 16 },
+	{ 0x0A, LVL_1_DATA, 8 },
+	{ 0x0C, LVL_1_DATA, 16 },
+	{ 0x22, LVL_3,      512 },
+	{ 0x23, LVL_3,      1024 },
+	{ 0x25, LVL_3,      2048 },
+	{ 0x29, LVL_3,      4096 },
+	{ 0x41, LVL_2,      128 },
+	{ 0x42, LVL_2,      256 },
+	{ 0x43, LVL_2,      512 },
+	{ 0x44, LVL_2,      1024 },
+	{ 0x45, LVL_2,      2048 },
+	{ 0x66, LVL_1_DATA, 8 },
+	{ 0x67, LVL_1_DATA, 16 },
+	{ 0x68, LVL_1_DATA, 32 },
+	{ 0x79, LVL_2,      128 },
+	{ 0x7A, LVL_2,      256 },
+	{ 0x7B, LVL_2,      512 },
+	{ 0x7C, LVL_2,      1024 },
+	{ 0x82, LVL_2,      256 },
+	{ 0x84, LVL_2,      1024 },
+	{ 0x85, LVL_2,      2048 },
+	{ 0x00, 0, 0}
+};
+
 static void __init init_intel(struct cpuinfo_x86 *c)
 {
-#ifndef CONFIG_M686
-	static int f00f_workaround_enabled = 0;
-#endif
-	char *p = NULL;
 	unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
+	char *p = NULL;
+#ifndef CONFIG_X86_F00F_WORKS_OK
+	static int f00f_workaround_enabled = 0;
 
-#ifndef CONFIG_M686
 	/*
 	 * All current models of Pentium and Pentium with MMX technology CPUs
 	 * have the F0 0F bug, which lets nonpriviledged users lock up the system.
 	 * Note that the workaround only should be initialized once...
 	 */
 	c->f00f_bug = 0;
-	if ( c->x86 == 5 ) {
+	if (c->x86 == 5) {
 		c->f00f_bug = 1;
-		if ( !f00f_workaround_enabled ) {
+		if (!f00f_workaround_enabled) {
 			trap_init_f00f_bug();
 			printk(KERN_NOTICE "Intel Pentium with F0 0F bug - workaround enabled.\n");
 			f00f_workaround_enabled = 1;
 		}
 	}
-#endif
-
+#endif /* CONFIG_X86_F00F_WORKS_OK */
 
 	if (c->cpuid_level > 1) {
 		/* supports eax=2  call */
@@ -2273,83 +2327,31 @@
 			/* Byte 0 is level count, not a descriptor */
 			for ( j = 1 ; j < 16 ; j++ ) {
 				unsigned char des = dp[j];
-				unsigned char dl, dh;
-				unsigned int cs;
-
-				dh = des >> 4;
-				dl = des & 0x0F;
+				unsigned char k = 0;
 
-				/* Black magic... */
-
-				switch ( dh )
+				/* look up this descriptor in the table */
+				while (cache_table[k].descriptor != 0)
 				{
-				case 0:
-					switch ( dl ) {
-					case 6:
-						/* L1 I cache */
-						l1i += 8;
-						break;
-					case 8:
-						/* L1 I cache */
-						l1i += 16;
-						break;
-					case 10:
-						/* L1 D cache */
-						l1d += 8;
-						break;
-					case 12:
-						/* L1 D cache */
-						l1d += 16;
-						break;
-					default:;
-						/* TLB, or unknown */
-					}
-					break;
-				case 2:
-					if ( dl ) {
-						/* L3 cache */
-						cs = (dl-1) << 9;
-						l3 += cs;
-					}
-					break;
-				case 4:
-					if ( c->x86 > 6 && dl ) {
-						/* P4 family */
-						/* L3 cache */
-						cs = 128 << (dl-1);
-						l3 += cs;
+					if (cache_table[k].descriptor == des) {
+						switch (cache_table[k].cache_type) {
+						case LVL_1_INST:
+							l1i += cache_table[k].size;
+							break;
+						case LVL_1_DATA:
+							l1d += cache_table[k].size;
+							break;
+						case LVL_2:
+							l2 += cache_table[k].size;
+							break;
+						case LVL_3:
+							l3 += cache_table[k].size;
+							break;
+						}
+
 						break;
 					}
-					/* else same as 8 - fall through */
-				case 8:
-					if ( dl ) {
-						/* L2 cache */
-						cs = 128 << (dl-1);
-						l2 += cs;
-					}
-					break;
-				case 6:
-					if (dl > 5) {
-						/* L1 D cache */
-						cs = 8<<(dl-6);
-						l1d += cs;
-					}
-					break;
-				case 7:
-					if ( dl >= 8 ) 
-					{
-						/* L2 cache */
-						cs = 64<<(dl-8);
-						l2 += cs;
-					} else {
-						/* L0 I cache, count as L1 */
-						cs = dl ? (16 << (dl-1)) : 12;
-						l1i += cs;
-					}
-					break;
-				default:
-					/* TLB, or something else we don't know about */
-					break;
+
+					k++;
 				}
 			}
 		}
@@ -2426,7 +2428,7 @@
 			if (smp_num_siblings != NR_SIBLINGS) {
 				printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings);
 				smp_num_siblings = 1;
-				goto too_many_siblings;
+				return;
 			}
 			tmp = smp_num_siblings;
 			while ((tmp & 1) == 0) {
@@ -2448,7 +2450,6 @@
 		}
 
 	}
-too_many_siblings:
 #endif
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- linux.orig/arch/i386/kernel/smp.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/smp.c	2002-08-12 22:14:03.000000000 +0000
@@ -66,7 +66,7 @@
  *	an L1cache=Writethrough or L1cache=off option.
  *
  *		B stepping CPUs may hang. There are hardware work arounds
- *	for this. We warn about it in case your board doesnt have the work
+ *	for this. We warn about it in case your board doesn't have the work
  *	arounds. Basically thats so I can tell anyone with a B stepping
  *	CPU and SMP problems "tough".
  *
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- linux.orig/arch/i386/kernel/traps.c	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/i386/kernel/traps.c	2002-08-12 22:14:07.000000000 +0000
@@ -40,9 +40,9 @@
 
 #include <asm/smp.h>
 #include <asm/pgalloc.h>
+#include <asm/fixmap.h>
 
 #ifdef CONFIG_X86_VISWS_APIC
-#include <asm/fixmap.h>
 #include <asm/cobalt.h>
 #include <asm/lithium.h>
 #endif
@@ -186,6 +186,14 @@
 	show_trace(esp);
 }
 
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+	show_stack(0);
+}
+
 void show_registers(struct pt_regs *regs)
 {
 	int i;
@@ -758,35 +766,17 @@
 
 #endif /* CONFIG_MATH_EMULATION */
 
-#ifndef CONFIG_M686
+#ifndef CONFIG_X86_F00F_WORKS_OK
 void __init trap_init_f00f_bug(void)
 {
-	unsigned long page;
-	pgd_t * pgd;
-	pmd_t * pmd;
-	pte_t * pte;
-
-	/*
-	 * Allocate a new page in virtual address space, 
-	 * move the IDT into it and write protect this page.
-	 */
-	page = (unsigned long) vmalloc(PAGE_SIZE);
-	pgd = pgd_offset(&init_mm, page);
-	pmd = pmd_offset(pgd, page);
-	pte = pte_offset(pmd, page);
-	__free_page(pte_page(*pte));
-	*pte = mk_pte_phys(__pa(&idt_table), PAGE_KERNEL_RO);
-	/*
-	 * Not that any PGE-capable kernel should have the f00f bug ...
-	 */
-	__flush_tlb_all();
-
 	/*
 	 * "idt" is magic - it overlaps the idt_descr
 	 * variable so that updating idt will automatically
 	 * update the idt descriptor..
 	 */
-	idt = (struct desc_struct *)page;
+	__set_fixmap(FIX_F00F, __pa(&idt_table), PAGE_KERNEL_RO);
+	idt = (struct desc_struct *)__fix_to_virt(FIX_F00F);
+
 	__asm__ __volatile__("lidt %0": "=m" (idt_descr));
 }
 #endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ia64/config.in linux/arch/ia64/config.in
--- linux.orig/arch/ia64/config.in	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/ia64/config.in	2002-08-12 22:14:20.000000000 +0000
@@ -75,15 +75,15 @@
 
 if [ "$CONFIG_IA64_SGI_SN1" = "y" ] || [ "$CONFIG_IA64_SGI_SN2" = "y" ]; then
 	define_bool CONFIG_IA64_SGI_SN y
-	bool '  Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG n
+	bool '  Enable extra debugging code' CONFIG_IA64_SGI_SN_DEBUG
 	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN_SIM
 	bool '  Enable autotest (llsc). Option to run cache test instead of booting' \
-			CONFIG_IA64_SGI_AUTOTEST n
+			CONFIG_IA64_SGI_AUTOTEST
 	define_bool CONFIG_DEVFS_FS y
 	if [ "$CONFIG_DEVFS_FS" = "y" ]; then
-	  bool '    Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG n
+	  bool '    Enable DEVFS Debug Code' CONFIG_DEVFS_DEBUG
 	fi
-	bool '  Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL y
+	bool '  Enable protocol mode for the L1 console' CONFIG_SERIAL_SGI_L1_PROTOCOL
 	define_bool CONFIG_DISCONTIGMEM y
 	define_bool CONFIG_IA64_MCA y
 	define_bool CONFIG_NUMA y
@@ -195,7 +195,7 @@
 mainmenu_option next_comment
 comment 'CD-ROM drivers (not for SCSI or IDE/ATAPI drives)'
 
-bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
+bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
 if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
   source drivers/cdrom/Config.in
 fi
@@ -239,6 +239,8 @@
 
 source drivers/usb/Config.in
 
+source lib/Config.in
+
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    source net/bluetooth/Config.in
 fi
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ia64/sn/fakeprom/README linux/arch/ia64/sn/fakeprom/README
--- linux.orig/arch/ia64/sn/fakeprom/README	2002-08-03 00:39:42.000000000 +0000
+++ linux/arch/ia64/sn/fakeprom/README	2002-08-12 22:14:19.000000000 +0000
@@ -71,7 +71,7 @@
     1GB*<dn>, where dn is the digit number. The amount of memory
     is 8MB*2**<d>. (If <d> = 0, the memory size is 0).
 
-    SN1 doesnt support dimms this small but small memory systems 
+    SN1 doesn't support dimms this small but small memory systems 
     boot faster on Medusa.
 
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/m68k/config.in linux/arch/m68k/config.in
--- linux.orig/arch/m68k/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/m68k/config.in	2002-08-12 22:14:24.000000000 +0000
@@ -141,7 +141,7 @@
    fi
    dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
    if [ "$CONFIG_PRINTER" != "n" ]; then
-      bool '    Support IEEE1284 status readback' CONFIG_PARPORT_1284
+      bool '    IEEE 1284 transfer modes' CONFIG_PARPORT_1284
    fi
 fi
 
@@ -539,7 +539,7 @@
 mainmenu_option next_comment
 comment 'Sound support'
 
-tristate 'Sound support' CONFIG_SOUND
+tristate 'Sound card support' CONFIG_SOUND
 if [ "$CONFIG_SOUND" != "n" ]; then
    source drivers/sound/dmasound/Config.in
 fi
@@ -565,3 +565,5 @@
 fi
 
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/mips/au1000/common/usbdev.c linux/arch/mips/au1000/common/usbdev.c
--- linux.orig/arch/mips/au1000/common/usbdev.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/mips/au1000/common/usbdev.c	2002-08-12 22:14:02.000000000 +0000
@@ -866,7 +866,7 @@
 
 // SETUP packet request parser
 static void
-process_setup (struct usb_serial* serial, devrequest* setup)
+process_setup (struct usb_serial* serial, struct usb_ctrlrequest* setup)
 {
 	int desc_len, strnum;
 
@@ -874,7 +874,7 @@
 
 	switch (setup->request) {
 	case USB_REQ_SET_ADDRESS:
-		serial->address = le16_to_cpu(setup->value);
+		serial->address = le16_to_cpu(setup->wValue);
 		dbg(__FUNCTION__ ": our address=%d", serial->address);
 		if (serial->address > 127 || serial->state == CONFIGURED) {
 			// usb spec doesn't tell us what to do, so just go to
@@ -887,8 +887,8 @@
 			serial->state = DEFAULT;
 		break;
 	case USB_REQ_GET_DESCRIPTOR:
-		desc_len = le16_to_cpu(setup->length);
-		switch (le16_to_cpu(setup->value) >> 8) {
+		desc_len = le16_to_cpu(setup->wLength);
+		switch (le16_to_cpu(setup->wValue) >> 8) {
 		case USB_DT_DEVICE:
 			// send device descriptor!
 			desc_len = desc_len > serial->dev_desc->bLength ?
@@ -901,7 +901,7 @@
 			// If the config descr index in low-byte of
 			// setup->value	is valid, send config descr,
 			// otherwise stall ep0.
-			if ((le16_to_cpu(setup->value) & 0xff) == 0) {
+			if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
 				// send config descriptor!
 				if (desc_len <= USB_DT_CONFIG_SIZE) {
 					dbg("sending partial config desc, size=%d",
@@ -943,7 +943,7 @@
 		case USB_DT_STRING:
 			// If the string descr index in low-byte of setup->value
 			// is valid, send string descr, otherwise stall ep0.
-			strnum = le16_to_cpu(setup->value) & 0xff;
+			strnum = le16_to_cpu(setup->wValue) & 0xff;
 			if (strnum >= 0 && strnum < 6) {
 				struct usb_string_descriptor *desc =
 				    serial->str_desc[strnum];
@@ -957,7 +957,7 @@
 			break;
 		default:	// Invalid request
 			dbg("invalid get desc=%d, stalled",
-			    le16_to_cpu(setup->value) >> 8);
+			    le16_to_cpu(setup->wValue) >> 8);
 			endpoint_stall(&serial->ep_ctrl);	// Stall endpoint 0
 			break;
 		}
@@ -967,7 +967,7 @@
 		break;
 	case USB_REQ_GET_INTERFACE:
 		// interface must be zero.
-		if ((le16_to_cpu(setup->index) & 0xff) ||
+		if ((le16_to_cpu(setup->wIndex) & 0xff) ||
 		    serial->state == ADDRESS) {
 			// FIXME: respond with "request error". how?
 		} else if (serial->state == CONFIGURED) {
@@ -981,9 +981,9 @@
 		if (serial->state == ADDRESS) {
 			// FIXME: respond with "request error". how?
 		} else if (serial->state == CONFIGURED) {
-			serial->interface = le16_to_cpu(setup->index) & 0xff;
+			serial->interface = le16_to_cpu(setup->wIndex) & 0xff;
 			serial->alternate_setting =
-			    le16_to_cpu(setup->value) & 0xff;
+			    le16_to_cpu(setup->wValue) & 0xff;
 			// interface and alternate_setting must be zero
 			if (serial->interface || serial->alternate_setting) {
 				// FIXME: respond with "request error". how?
@@ -992,7 +992,7 @@
 		break;
 	case USB_REQ_SET_CONFIGURATION:
 		// set active config to low-byte of serial.value
-		serial->configuration = le16_to_cpu(setup->value) & 0xff;
+		serial->configuration = le16_to_cpu(setup->wValue) & 0xff;
 		dbg("set config, config=%d", serial->configuration);
 		if (!serial->configuration && serial->state > DEFAULT)
 			serial->state = ADDRESS;
@@ -1009,7 +1009,7 @@
 		break;
 	case USB_REQ_GET_STATUS:
 		// FIXME: looks like the h/w handles this one
-		switch (setup->requesttype) {
+		switch (setup->bRequestType) {
 		case 0x80:	// Device
 			// FIXME: send device status
 			break;
@@ -1027,16 +1027,16 @@
 	case USB_REQ_CLEAR_FEATURE:
 		switch (setup->requesttype) {
 		case 0x00:	// Device
-			if ((le16_to_cpu(setup->value) & 0xff) == 1)
+			if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
 				serial->remote_wakeup_en = 0;
 			else
 				endpoint_stall(&serial->ep_ctrl);
 			break;
 		case 0x02:	// End Point
-			if ((le16_to_cpu(setup->value) & 0xff) == 0) {
+			if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
 				endpoint_t *ep =
 				    epnum_to_ep(serial,
-						    le16_to_cpu(setup->index) & 0xff);
+						    le16_to_cpu(setup->wIndex) & 0xff);
 
 				endpoint_unstall(ep);
 				endpoint_reset_datatoggle(ep);
@@ -1046,18 +1046,18 @@
 		}
 		break;
 	case USB_REQ_SET_FEATURE:
-		switch (setup->requesttype) {
+		switch (setup->bRequestType) {
 		case 0x00:	// Device
-			if ((le16_to_cpu(setup->value) & 0xff) == 1)
+			if ((le16_to_cpu(setup->wValue) & 0xff) == 1)
 				serial->remote_wakeup_en = 1;
 			else
 				endpoint_stall(&serial->ep_ctrl);
 			break;
 		case 0x02:	// End Point
-			if ((le16_to_cpu(setup->value) & 0xff) == 0) {
+			if ((le16_to_cpu(setup->wValue) & 0xff) == 0) {
 				endpoint_t *ep =
 				    epnum_to_ep(serial,
-						    le16_to_cpu(setup->index) & 0xff);
+						    le16_to_cpu(setup->wIndex) & 0xff);
 
 				endpoint_stall(ep);
 			} else
@@ -1100,14 +1100,14 @@
 	
 		// SETUP packet received ?
 		//if (cs & USBDEV_CS_SU) { FIXME: uncomment!
-			if (pkt->size == sizeof(devrequest)) {
-				devrequest setup;
+			if (pkt->size == sizeof(struct usb_ctrlrequest)) {
+				struct usb_ctrlrequest setup;
 			if ((cs & (USBDEV_CS_NAK | USBDEV_CS_ACK)) ==
 			    USBDEV_CS_ACK)
 					dbg("got SETUP");
 				else
 					dbg("got NAK SETUP, cs=%08x", cs);
-			memcpy(&setup, pkt->bufptr, sizeof(devrequest));
+			memcpy(&setup, pkt->bufptr, sizeof(struct usb_ctrlrequest));
 				process_setup(serial, &setup);
 			//} else  FIXME: uncomment!
 			//dbg(__FUNCTION__ ": wrong size SETUP received");
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/mips/config.in linux/arch/mips/config.in
--- linux.orig/arch/mips/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/mips/config.in	2002-08-12 22:14:23.000000000 +0000
@@ -632,3 +632,5 @@
    bool 'Run uncached' CONFIG_MIPS_UNCACHED
 fi
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/mips/dec/wbflush.c linux/arch/mips/dec/wbflush.c
--- linux.orig/arch/mips/dec/wbflush.c	2001-10-05 19:06:51.000000000 +0000
+++ linux/arch/mips/dec/wbflush.c	2002-08-12 22:14:25.000000000 +0000
@@ -97,7 +97,7 @@
 }
 
 /*
- * The DS500/2x0 doesnt need to write back the WB.
+ * The DS500/2x0 doesn't need to write back the WB.
  */
 static void wbflush_kn03(void)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/mips64/config.in linux/arch/mips64/config.in
--- linux.orig/arch/mips64/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/mips64/config.in	2002-08-12 22:14:05.000000000 +0000
@@ -336,3 +336,5 @@
    bool 'Run uncached' CONFIG_MIPS_UNCACHED
 fi
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/mips64/kernel/irq.c linux/arch/mips64/kernel/irq.c
--- linux.orig/arch/mips64/kernel/irq.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/mips64/kernel/irq.c	2002-08-12 22:13:59.000000000 +0000
@@ -48,7 +48,7 @@
 {
 	/*
 	 * 'what should we do if we get a hw irq event on an illegal vector'.
-	 * each architecture has to answer this themselves, it doesnt deserve
+	 * each architecture has to answer this themselves, it doesn't deserve
 	 * a generic callback i think.
 	 */
 	printk("unexpected interrupt %d\n", irq);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/mips64/math-emu/ieee754.c linux/arch/mips64/math-emu/ieee754.c
--- linux.orig/arch/mips64/math-emu/ieee754.c	2001-07-02 20:56:41.000000000 +0000
+++ linux/arch/mips64/math-emu/ieee754.c	2002-08-12 22:14:09.000000000 +0000
@@ -3,7 +3,7 @@
  *
  * BUGS
  * not much dp done
- * doesnt generate IEEE754_INEXACT
+ * doesn't generate IEEE754_INEXACT
  *
  */
 /*
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/Makefile linux/arch/parisc/Makefile
--- linux.orig/arch/parisc/Makefile	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/Makefile	2002-08-12 22:14:15.000000000 +0000
@@ -17,12 +17,28 @@
 # Mike Shaver, Helge Deller and Martin K. Petersen
 #
 
+ifdef CONFIG_PARISC64
+LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux64.lds $(LDFLAGS)
+CROSS_COMPILE := hppa64-linux-
+UTS_MACHINE := parisc64
+#CFLAGS += -b hppa64-linux
+
+else
+LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS)
+MACHINE	:= $(subst 64,,$(shell uname -m))
+ifneq (${MACHINE},parisc)
+# cross compilation
+CROSS_COMPILE := hppa-linux-
+endif
+endif
+
+OFFSET_H := $(TOPDIR)/include/asm-parisc/offset.h
 FINAL_LD=$(CROSS_COMPILE)ld --warn-common --warn-section-align 
 
 CPP=$(CC) -E
 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
 LDFLAGS =
-LINKFLAGS =-T $(TOPDIR)/arch/parisc/vmlinux.lds $(LDFLAGS)
+
 
 CFLAGS_PIPE := -pipe
 CFLAGS_NSR  := -fno-strength-reduce
@@ -32,25 +48,48 @@
 # enable them by default.
 CFLAGS += -mno-space-regs -mfast-indirect-calls
 
-# If we become able to compile for specific platforms, this should be
-# conditional on that.
-CFLAGS += -mschedule=7200
-
 # No fixed-point multiply
 CFLAGS += -mdisable-fpregs
 
-HEAD = arch/parisc/kernel/head.o 
+# Without this, "ld -r" results in .text sections that are too big
+# (> 0x40000) for branches to reach stubs.
+CFLAGS += -ffunction-sections
+
+# select which processor to optimise for
+ifdef CONFIG_PA7100
+CFLAGS += -march=1.1 -mschedule=7100
+endif
+
+ifdef CONFIG_PA7200
+CFLAGS += -march=1.1 -mschedule=7200
+endif
+
+ifdef CONFIG_PA7100LC
+CFLAGS += -march=1.1 -mschedule=7100LC
+endif
+
+ifdef CONFIG_PA8X00
+CFLAGS += -march=2.0 -mschedule=8000
+endif
+
+ASFLAGS := -D__ASSEMBLY__ -traditional
+
+HEAD := arch/parisc/kernel/head.o 
 
 SUBDIRS := $(SUBDIRS) $(addprefix arch/parisc/, tools kernel mm lib hpux)
 CORE_FILES :=  $(addprefix arch/parisc/, kernel/pdc_cons.o kernel/process.o \
 	lib/lib.a mm/mm.o kernel/kernel.o hpux/hpux.o) \
 	$(CORE_FILES) arch/parisc/kernel/init_task.o
+CLEAN_FILES := $(CLEAN_FILES) arch/parisc/tools/offset.[hs] 
+
+ifdef CONFIG_PARISC64
+HEAD := arch/parisc/kernel/head64.o
+endif
+
 LIBS := `$(CC) -print-libgcc-file-name` $(TOPDIR)/arch/parisc/lib/lib.a $(LIBS) 
 
-ifdef CONFIG_MATH_EMULATION
 SUBDIRS := $(SUBDIRS) arch/parisc/math-emu
-DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.a
-endif
+DRIVERS := $(DRIVERS) arch/parisc/math-emu/math.o
 
 ifdef CONFIG_KWDB
 SUBDIRS := $(SUBDIRS) arch/parisc/kdb
@@ -67,7 +106,7 @@
 	$(MAKE) linuxsubdirs SUBDIRS=arch/parisc/mm
 
 palo: vmlinux
-	export TOPDIR=`pwd`; export CONFIG_STI_CONSOLE=$(CONFIG_STI_CONSOLE); \
+	export TOPDIR=`pwd`; \
 	unset STRIP LDFLAGS CPP CPPFLAGS AFLAGS CFLAGS CC LD; cd ../palo && make lifimage
 
 Image: palo
@@ -84,8 +123,14 @@
 
 install: 
 
+archmrproper:
+	rm -f $(OFFSET_H)
+
 archclean:
 
-archmrproper:
+archdep: $(OFFSET_H)
+
+$(OFFSET_H): include/linux/version.h
+	$(MAKE) -C $(TOPDIR)/arch/$(ARCH)/tools all
 
-archdep:
+.PHONY: $(OFFSET_H)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/config.in linux/arch/parisc/config.in
--- linux.orig/arch/parisc/config.in	2001-04-18 00:19:25.000000000 +0000
+++ linux/arch/parisc/config.in	2002-08-12 22:14:27.000000000 +0000
@@ -52,7 +52,7 @@
 comment 'Loadable module support'
 bool 'Enable loadable module support' CONFIG_MODULES
 if [ "$CONFIG_MODULES" = "y" ]; then
-  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+  bool 'Set version information on all module symbols' CONFIG_MODVERSIONS
   bool 'Kernel module loader' CONFIG_KMOD
 fi
 endmenu
@@ -208,3 +208,4 @@
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
 
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/defconfig linux/arch/parisc/defconfig
--- linux.orig/arch/parisc/defconfig	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/defconfig	2002-08-12 22:14:02.000000000 +0000
@@ -1,8 +1,10 @@
 #
-# Automatically generated by make menuconfig: don't edit
+# Automatically generated make config: don't edit
 #
 CONFIG_PARISC=y
 # CONFIG_UID16 is not set
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_RWSEM_XCHGADD_ALGORITHM is not set
 
 #
 # Code maturity level options
@@ -10,44 +12,70 @@
 CONFIG_EXPERIMENTAL=y
 
 #
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# Processor type
+#
+# CONFIG_PA7100 is not set
+# CONFIG_PA7200 is not set
+# CONFIG_PA7100LC is not set
+# CONFIG_PA8X00 is not set
+# CONFIG_PA11 is not set
+
+#
 # General options
 #
 # CONFIG_SMP is not set
+CONFIG_CHASSIS_LCD_LED=y
 # CONFIG_KWDB is not set
-CONFIG_GSC=y
 CONFIG_IOMMU_CCIO=y
+CONFIG_GSC=y
 CONFIG_GSC_LASI=y
+CONFIG_GSC_WAX=y
+CONFIG_EISA=y
+CONFIG_ISA=y
 CONFIG_PCI=y
 CONFIG_GSC_DINO=y
 CONFIG_PCI_LBA=y
 CONFIG_IOSAPIC=y
 CONFIG_IOMMU_SBA=y
-
-#
-# Loadable module support
-#
-CONFIG_MODULES=y
-# CONFIG_MODVERSIONS is not set
-CONFIG_KMOD=y
+CONFIG_SUPERIO=y
+CONFIG_PCI_NAMES=y
 
 #
 # General setup
 #
+CONFIG_HOTPLUG=y
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
-CONFIG_BINFMT_SOM=y
+CONFIG_KCORE_ELF=y
 CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_SOM=y
 # CONFIG_BINFMT_MISC is not set
-# CONFIG_BINFMT_JAVA is not set
+# CONFIG_PM is not set
 
 #
 # Parallel port support
 #
 CONFIG_PARPORT=y
-# CONFIG_PARPORT_PC is not set
+CONFIG_PARPORT_PC=y
+CONFIG_PARPORT_PC_CML1=y
+# CONFIG_PARPORT_SERIAL is not set
+# CONFIG_PARPORT_PC_FIFO is not set
+# CONFIG_PARPORT_PC_SUPERIO is not set
+# CONFIG_PARPORT_PC_PCMCIA is not set
+# CONFIG_PARPORT_AMIGA is not set
+# CONFIG_PARPORT_MFC3 is not set
+# CONFIG_PARPORT_ATARI is not set
 CONFIG_PARPORT_GSC=y
+# CONFIG_PARPORT_SUNBPP is not set
 # CONFIG_PARPORT_OTHER is not set
 # CONFIG_PARPORT_1284 is not set
 
@@ -60,33 +88,54 @@
 # CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
-# CONFIG_BLK_DEV_LOOP is not set
+CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_INITRD=y
 
 #
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_MD_RAID0=y
+CONFIG_MD_RAID1=y
+CONFIG_MD_RAID5=y
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_BLK_DEV_LVM is not set
+
+#
 # Networking options
 #
-# CONFIG_PACKET is not set
-# CONFIG_NETLINK is not set
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+CONFIG_NETLINK_DEV=y
 # CONFIG_NETFILTER is not set
-# CONFIG_FILTER is not set
+CONFIG_FILTER=y
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_DHCP is not set
 CONFIG_IP_PNP_BOOTP=y
 # CONFIG_IP_PNP_RARP is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
+# CONFIG_IP_MROUTE is not set
+# CONFIG_ARPD is not set
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
+# CONFIG_VLAN_8021Q is not set
+
+#
+#  
+#
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
@@ -106,36 +155,181 @@
 # CONFIG_NET_SCHED is not set
 
 #
+# ATA/IDE/MFM/RLL support
+#
+CONFIG_IDE=y
+
+#
+# IDE, ATA and ATAPI Block devices
+#
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_HD_IDE is not set
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_IDEDISK is not set
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
+# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
+# CONFIG_BLK_DEV_IDEDISK_IBM is not set
+# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set
+# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set
+# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set
+# CONFIG_BLK_DEV_IDEDISK_WD is not set
+# CONFIG_BLK_DEV_COMMERIAL is not set
+# CONFIG_BLK_DEV_TIVO is not set
+# CONFIG_BLK_DEV_IDECS is not set
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_CMD640 is not set
+# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
+# CONFIG_BLK_DEV_ISAPNP is not set
+# CONFIG_BLK_DEV_RZ1000 is not set
+CONFIG_BLK_DEV_IDEPCI=y
+# CONFIG_IDEPCI_SHARE_IRQ is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+CONFIG_BLK_DEV_ADMA=y
+# CONFIG_BLK_DEV_OFFBOARD is not set
+# CONFIG_IDEDMA_PCI_AUTO is not set
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_PCI_WIP is not set
+# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_AEC62XX_TUNING is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_WDC_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_AMD74XX_OVERRIDE is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_HPT34X_AUTODMA is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+CONFIG_BLK_DEV_NS87415=y
+# CONFIG_BLK_DEV_OPTI621 is not set
+# CONFIG_BLK_DEV_PDC202XX is not set
+# CONFIG_PDC202XX_BURST is not set
+# CONFIG_PDC202XX_FORCE is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIS5513 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_IDE_CHIPSETS is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_DMA_NONPCI is not set
+# CONFIG_BLK_DEV_IDE_MODES is not set
+# CONFIG_BLK_DEV_ATARAID is not set
+# CONFIG_BLK_DEV_ATARAID_PDC is not set
+# CONFIG_BLK_DEV_ATARAID_HPT is not set
+
+#
 # SCSI support
 #
 CONFIG_SCSI=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 CONFIG_BLK_DEV_SR=y
 # CONFIG_BLK_DEV_SR_VENDOR is not set
 CONFIG_SR_EXTRA_DEVS=2
 CONFIG_CHR_DEV_SG=y
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_DEBUG_QUEUES is not set
 # CONFIG_SCSI_MULTI_LUN is not set
 # CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
 
 #
 # SCSI low-level drivers
 #
-CONFIG_SCSI_LASI=y
-CONFIG_SCSI_ZALON=y
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AHA152X is not set
+# CONFIG_SCSI_AHA1542 is not set
+# CONFIG_SCSI_AHA1740 is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC7XXX_OLD is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_IN2000 is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_SCSI_CPQFCTS is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_EATA_DMA is not set
+# CONFIG_SCSI_EATA_PIO is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_PPA is not set
+# CONFIG_SCSI_IMM is not set
+# CONFIG_SCSI_NCR53C406A is not set
+CONFIG_SCSI_LASI700=y
+CONFIG_53C700_MEM_MAPPED=y
+CONFIG_53C700_LE_ON_BE=y
+CONFIG_53C700_USE_CONSISTENT=y
+# CONFIG_SCSI_NCR53C7xx is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_NCR53C8XX is not set
 CONFIG_SCSI_SYM53C8XX=y
+CONFIG_SCSI_ZALON=y
 CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=8
 CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32
 CONFIG_SCSI_NCR53C8XX_SYNC=20
 # CONFIG_SCSI_NCR53C8XX_PROFILE is not set
 # CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set
+# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set
+# CONFIG_SCSI_NCR53C8XX_SYMBIOS_COMPAT is not set
+# CONFIG_SCSI_PAS16 is not set
+# CONFIG_SCSI_PCI2000 is not set
+# CONFIG_SCSI_PCI2220I is not set
+# CONFIG_SCSI_PSI240I is not set
+# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_QLOGIC_ISP is not set
+# CONFIG_SCSI_QLOGIC_FC is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_SIM710 is not set
+# CONFIG_SCSI_SYM53C416 is not set
+# CONFIG_SCSI_DC390T is not set
+# CONFIG_SCSI_T128 is not set
+# CONFIG_SCSI_U14_34F is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_SCSI_PCMCIA is not set
 
 #
 # Network device support
 #
 CONFIG_NETDEVICES=y
-CONFIG_LASI_82596=y
 
 #
 # ARCnet devices
@@ -145,12 +339,18 @@
 # CONFIG_BONDING is not set
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
-# CONFIG_NET_SB1000 is not set
+# CONFIG_ETHERTAP is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
+CONFIG_LASI_82596=y
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNGEM is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
@@ -165,23 +365,31 @@
 # CONFIG_AC3200 is not set
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
-# CONFIG_DE4X5 is not set
 CONFIG_TULIP=y
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+# CONFIG_DE4X5 is not set
 # CONFIG_DGRS is not set
 # CONFIG_DM9102 is not set
 # CONFIG_EEPRO100 is not set
 # CONFIG_LNE390 is not set
+# CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
 # CONFIG_NE2K_PCI is not set
 # CONFIG_NE3210 is not set
 # CONFIG_ES3210 is not set
-# CONFIG_RTL8129 is not set
+# CONFIG_8139CP is not set
 # CONFIG_8139TOO is not set
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_NEW_RX_RESET is not set
 # CONFIG_SIS900 is not set
 # CONFIG_EPIC100 is not set
 # CONFIG_SUNDANCE is not set
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_RHINE_MMIO is not set
 # CONFIG_WINBOND_840 is not set
 # CONFIG_NET_POCKET is not set
 
@@ -189,6 +397,9 @@
 # Ethernet (1000 Mbit)
 #
 # CONFIG_ACENIC is not set
+# CONFIG_DL2K is not set
+# CONFIG_MYRI_SBUS is not set
+# CONFIG_NS83820 is not set
 # CONFIG_HAMACHI is not set
 # CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
@@ -217,12 +428,27 @@
 # CONFIG_WAN is not set
 
 #
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
+# Input core support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_KEYBDEV=y
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+
+#
 # Character devices
 #
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_GSC_PS2=y
-CONFIG_HIL=y
 CONFIG_SERIAL=y
 CONFIG_SERIAL_CONSOLE=y
 CONFIG_SERIAL_GSC=y
@@ -243,12 +469,45 @@
 # Mice
 #
 # CONFIG_BUSMOUSE is not set
-# CONFIG_MOUSE is not set
+CONFIG_MOUSE=y
+CONFIG_PSMOUSE=y
+# CONFIG_82C710_MOUSE is not set
+# CONFIG_PC110_PAD is not set
+
+#
+# Joysticks
+#
+# CONFIG_INPUT_GAMEPORT is not set
+# CONFIG_INPUT_NS558 is not set
+# CONFIG_INPUT_LIGHTNING is not set
+# CONFIG_INPUT_PCIGAME is not set
+# CONFIG_INPUT_CS461X is not set
+# CONFIG_INPUT_EMU10K1 is not set
+CONFIG_INPUT_SERIO=y
+# CONFIG_INPUT_SERPORT is not set
 
 #
 # Joysticks
 #
-# CONFIG_JOYSTICK is not set
+# CONFIG_INPUT_ANALOG is not set
+# CONFIG_INPUT_A3D is not set
+# CONFIG_INPUT_ADI is not set
+# CONFIG_INPUT_COBRA is not set
+# CONFIG_INPUT_GF2K is not set
+# CONFIG_INPUT_GRIP is not set
+# CONFIG_INPUT_INTERACT is not set
+# CONFIG_INPUT_TMDC is not set
+# CONFIG_INPUT_SIDEWINDER is not set
+# CONFIG_INPUT_IFORCE_USB is not set
+# CONFIG_INPUT_IFORCE_232 is not set
+# CONFIG_INPUT_WARRIOR is not set
+# CONFIG_INPUT_MAGELLAN is not set
+# CONFIG_INPUT_SPACEORB is not set
+# CONFIG_INPUT_SPACEBALL is not set
+# CONFIG_INPUT_STINGER is not set
+# CONFIG_INPUT_DB9 is not set
+# CONFIG_INPUT_GAMECON is not set
+# CONFIG_INPUT_TURBOGRAFX is not set
 # CONFIG_QIC02_TAPE is not set
 
 #
@@ -271,27 +530,67 @@
 # CONFIG_DRM is not set
 
 #
+# PCMCIA character devices
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
+
+#
+# HIL support
+#
+CONFIG_HIL=y
+# CONFIG_HIL_KBD_BASIC is not set
+
+#
+#  HIL driver core support
+#
+CONFIG_HP_SDC=y
+# CONFIG_HP_SDC_RTC is not set
+CONFIG_HIL_MLC=y
+CONFIG_HP_SDC_MLC=y
+
+#
+#  HIL device driver
+#
+CONFIG_HIL_KBD=y
+CONFIG_HIL_PTR=y
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
 # File systems
 #
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
+CONFIG_EXT3_FS=y
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
 # CONFIG_FAT_FS is not set
 # CONFIG_MSDOS_FS is not set
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
 # CONFIG_JFFS_FS is not set
+# CONFIG_JFFS2_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_TMPFS is not set
 # CONFIG_RAMFS is not set
 CONFIG_ISO9660_FS=y
-# CONFIG_JOLIET is not set
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
 # CONFIG_MINIX_FS is not set
+# CONFIG_VXFS_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
@@ -299,13 +598,12 @@
 # CONFIG_DEVFS_FS is not set
 # CONFIG_DEVFS_MOUNT is not set
 # CONFIG_DEVFS_DEBUG is not set
-# CONFIG_DEVPTS_FS is not set
+CONFIG_DEVPTS_FS=y
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
-# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
 # CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
@@ -315,13 +613,15 @@
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
+# CONFIG_INTERMEZZO_FS is not set
 CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
+CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-# CONFIG_NFSD_V3 is not set
+CONFIG_NFSD=y
+CONFIG_NFSD_V3=y
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
 # CONFIG_NCPFS_PACKET_SIGNING is not set
@@ -330,22 +630,60 @@
 # 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
+# CONFIG_ZISOFS_FS is not set
+# CONFIG_ZLIB_FS_INFLATE is not set
 
 #
 # Partition Types
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
+# CONFIG_SMB_NLS is not set
+CONFIG_NLS=y
 
 #
-# Sound Drivers
+# Native Language Support
 #
-# CONFIG_SOUND is not set
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
 
 #
 # Console drivers
@@ -354,8 +692,171 @@
 #
 # Frame-buffer support
 #
-# CONFIG_FB is not set
-# CONFIG_STI_CONSOLE is not set
+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_CYBER2000 is not set
+CONFIG_FB_STI=y
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB32=y
+CONFIG_FBCON_STI=y
+# CONFIG_FBCON_FONTWIDTH8_ONLY is not set
+# CONFIG_FBCON_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_STI_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FBCON=y
+CONFIG_FBCON_FONT=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_SUN12x22=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_CMPCI is not set
+# CONFIG_SOUND_EMU10K1 is not set
+# CONFIG_MIDI_EMU10K1 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_ES1370 is not set
+# CONFIG_SOUND_ES1371 is not set
+# CONFIG_SOUND_ESSSOLO1 is not set
+# CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
+CONFIG_SOUND_HARMONY=y
+# CONFIG_SOUND_RME96XX is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_VIA82CXXX is not set
+# CONFIG_MIDI_VIA82CXXX is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Controllers
+#
+# CONFIG_USB_UHCI is not set
+# CONFIG_USB_UHCI_ALT is not set
+# CONFIG_USB_OHCI is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_AUDIO is not set
+# CONFIG_USB_BLUETOOTH is not set
+# CONFIG_USB_STORAGE is not set
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_HP8200e is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# USB Human Interface Devices (HID)
+#
+# CONFIG_USB_HID is not set
+# CONFIG_USB_HIDDEV is not set
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+# CONFIG_USB_WACOM is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_DC2XX is not set
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_SCANNER is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USB_HPUSBSCSI is not set
+
+#
+# USB Multimedia devices
+#
+
+#
+#   Video4Linux support is needed for USB Multimedia device support
+#
+
+#
+# USB Network adaptors
+#
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_CDCETHER is not set
+# CONFIG_USB_USBNET is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_USS720 is not set
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_BELKIN is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_EMPEG is not set
+# CONFIG_USB_SERIAL_FTDI_SIO is not set
+# CONFIG_USB_SERIAL_VISOR is not set
+# CONFIG_USB_SERIAL_IPAQ is not set
+# CONFIG_USB_SERIAL_IR is not set
+# CONFIG_USB_SERIAL_EDGEPORT is not set
+# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
+# CONFIG_USB_SERIAL_KEYSPAN is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_MCT_U232 is not set
+# CONFIG_USB_SERIAL_KLSI is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_CYBERJACK is not set
+# CONFIG_USB_SERIAL_XIRCOM is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_RIO500 is not set
 
 #
 # Kernel hacking
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/Makefile linux/arch/parisc/hpux/Makefile
--- linux.orig/arch/parisc/hpux/Makefile	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/hpux/Makefile	2002-08-12 22:14:09.000000000 +0000
@@ -7,10 +7,7 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-all: hpux.o
 O_TARGET = hpux.o
-O_OBJS = entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o
-
-.o.S:	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
+obj-y := entry_hpux.o gate.o wrappers.o fs.o ioctl.o sys_hpux.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/entry_hpux.S linux/arch/parisc/hpux/entry_hpux.S
--- linux.orig/arch/parisc/hpux/entry_hpux.S	2001-10-05 19:22:07.000000000 +0000
+++ linux/arch/parisc/hpux/entry_hpux.S	2002-08-12 22:14:14.000000000 +0000
@@ -1,6 +1,6 @@
-/* -----------------------------------------------------------------------------
+/*
  *
- * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+ * Linux/PARISC Project (http://www.parisc-linux.org/)
  *
  * modified by Matthew Wilcox <willy@bofh.ai> 1999-07-26
  */
@@ -10,13 +10,13 @@
 #include <linux/linkage.h>
 #include <asm/unistd.h>
 
-
 	.text
 
 #define ENTRY_NAME(_name_) .word _name_
 
 	.align 4
 	.export hpux_call_table
+	.import hpux_unimplemented_wrapper
 hpux_call_table:
 	ENTRY_NAME(sys_ni_syscall)	/* 0 */
 	ENTRY_NAME(sys_exit)
@@ -36,7 +36,7 @@
 	ENTRY_NAME(sys_chmod)	/* 15 */
 	ENTRY_NAME(sys_chown)
 	ENTRY_NAME(hpux_brk)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_lseek)
 	ENTRY_NAME(sys_getpid)	/* 20 */
 	ENTRY_NAME(hpux_mount)
@@ -46,34 +46,34 @@
 	ENTRY_NAME(sys_stime)	/* 25 */
 	ENTRY_NAME(hpux_ptrace)
 	ENTRY_NAME(sys_alarm)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_pause)
 	ENTRY_NAME(sys_utime)	/* 30 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_access)
 	ENTRY_NAME(hpux_nice)
-	ENTRY_NAME(sys_ni_syscall)	/* 35 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 35 */
 	ENTRY_NAME(sys_sync)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_newstat)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_setpgrp3)
 	ENTRY_NAME(sys_newlstat)	/* 40 */
 	ENTRY_NAME(sys_dup)
 	ENTRY_NAME(hpux_pipe_wrapper)
 	ENTRY_NAME(sys_times)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 45 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 45 */
 	ENTRY_NAME(sys_setgid)
 	ENTRY_NAME(sys_getgid)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 50 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 50 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(hpux_ioctl)
-	ENTRY_NAME(sys_ni_syscall)	/* 55 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 55 */
 	ENTRY_NAME(sys_symlink)
 	ENTRY_NAME(hpux_utssys)
 	ENTRY_NAME(sys_readlink)
@@ -81,218 +81,218 @@
 	ENTRY_NAME(sys_umask)	/* 60 */
 	ENTRY_NAME(sys_chroot)
 	ENTRY_NAME(sys_fcntl)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 65 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 65 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(hpux_sbrk)
-	ENTRY_NAME(sys_ni_syscall)	/* 70 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 70 */
 	ENTRY_NAME(sys_mmap)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 75 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 80 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 75 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 80 */
 	ENTRY_NAME(sys_getpgid)
 	ENTRY_NAME(sys_setpgid)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 85 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(sys_setitimer)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 85 */
+	ENTRY_NAME(sys_getitimer)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_dup2)		/* 90 */
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_newfstat)
 	ENTRY_NAME(sys_select)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 95 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 100 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 105 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 110 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 115 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 95 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 100 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 105 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 110 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 115 */
 	ENTRY_NAME(sys_gettimeofday)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 120 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 120 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_fchown)
 	ENTRY_NAME(sys_fchmod)
-	ENTRY_NAME(sys_ni_syscall)	/* 125 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 125 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_rename)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 130 */
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 130 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(hpux_sysconf)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 135 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 135 */
 	ENTRY_NAME(sys_mkdir)
 	ENTRY_NAME(sys_rmdir)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 140 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 145 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 150 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 155 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 160 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 165 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 170 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 175 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 180 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 185 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 190 */
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 140 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(sys_getrlimit)
+	ENTRY_NAME(sys_setrlimit)      /* 145 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 150 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_lockf)      /* 155 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 160 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 165 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 170 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 175 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 180 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(sys_sigprocmask)      /* 185 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 190 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(hpux_getdomainname)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 195 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 195 */
+	ENTRY_NAME(hpux_statfs)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_waitpid)	/* 200 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 205 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 210 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 215 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 220 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 225 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 230 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 235 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 240 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 245 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 250 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 255 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 260 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 265 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 270 */
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 205 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 210 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 215 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 220 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 225 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 230 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 235 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 240 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 245 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 250 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 255 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 260 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 265 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 270 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_fchdir)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_accept)		/* 275 */
 	ENTRY_NAME(sys_bind)
 	ENTRY_NAME(sys_connect)
@@ -309,227 +309,227 @@
 	ENTRY_NAME(sys_setsockopt)
 	ENTRY_NAME(sys_shutdown)
 	ENTRY_NAME(sys_socket)		/* 290 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 295 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 300 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 305 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 310 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 315 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 320 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 325 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 330 */
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 295 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 300 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 305 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 310 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 315 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 320 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 325 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 330 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_lchown)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 335 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 340 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 345 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 350 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_sysfs)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 335 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 340 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 345 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 350 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(sys_nanosleep)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 355 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 355 */
 	ENTRY_NAME(hpux_getdents)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 360 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 360 */
 	ENTRY_NAME(hpux_fstat64)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 365 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 365 */
 	ENTRY_NAME(hpux_lstat64)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 	ENTRY_NAME(hpux_stat64)
-	ENTRY_NAME(sys_ni_syscall)	/* 370 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 375 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 380 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 385 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 390 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 395 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 400 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 405 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 410 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 415 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 420 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 425 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 430 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 435 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 440 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 445 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 450 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 455 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 460 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 465 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 470 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 475 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 480 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 485 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 490 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 495 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 500 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 505 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)	/* 510 */
-	ENTRY_NAME(sys_ni_syscall)
-	ENTRY_NAME(sys_ni_syscall)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 370 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 375 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 380 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_setpgrp)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 385 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 390 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 395 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 400 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 405 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 410 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 415 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 420 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 425 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 430 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 435 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 440 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 445 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 450 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 455 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 460 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 465 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 470 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 475 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 480 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 485 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 490 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 495 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 500 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 505 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)      /* 510 */
+	ENTRY_NAME(hpux_unimplemented_wrapper)
+	ENTRY_NAME(hpux_unimplemented_wrapper)
 .end
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/fs.c linux/arch/parisc/hpux/fs.c
--- linux.orig/arch/parisc/hpux/fs.c	2001-08-12 22:07:55.000000000 +0000
+++ linux/arch/parisc/hpux/fs.c	2002-08-12 22:14:08.000000000 +0000
@@ -52,7 +52,8 @@
 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
 #define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
 
-static int filldir(void * __buf, const char * name, int namlen, loff_t offset, ino_t ino)
+static int filldir(void * __buf, const char * name, int namlen, loff_t offset,
+		ino_t ino, unsigned int d_type)
 {
 	struct hpux_dirent * dirent;
 	struct getdents_callback * buf = (struct getdents_callback *) __buf;
@@ -83,42 +84,21 @@
 int hpux_getdents(unsigned int fd, struct hpux_dirent *dirent, unsigned int count)
 {
 	struct file * file;
-	struct dentry * dentry;
-	struct inode * inode;
 	struct hpux_dirent * lastdirent;
 	struct getdents_callback buf;
 	int error;
 
-	lock_kernel();
 	error = -EBADF;
 	file = fget(fd);
 	if (!file)
 		goto out;
 
-	dentry = file->f_dentry;
-	if (!dentry)
-		goto out_putf;
-
-	inode = dentry->d_inode;
-	if (!inode)
-		goto out_putf;
-
 	buf.current_dir = dirent;
 	buf.previous = NULL;
 	buf.count = count;
 	buf.error = 0;
 
-	error = -ENOTDIR;
-	if (!file->f_op || !file->f_op->readdir)
-		goto out_putf;
-
-	/*
-	 * Get the inode's semaphore to prevent changes
-	 * to the directory while we read it.
-	 */
-	down(&inode->i_sem);
-	error = file->f_op->readdir(file, &buf, filldir);
-	up(&inode->i_sem);
+	error = vfs_readdir(file, filldir, &buf);
 	if (error < 0)
 		goto out_putf;
 	error = buf.error;
@@ -131,7 +111,6 @@
 out_putf:
 	fput(file);
 out:
-	unlock_kernel();
 	return error;
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/gate.S linux/arch/parisc/hpux/gate.S
--- linux.orig/arch/parisc/hpux/gate.S	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/hpux/gate.S	2002-08-12 22:14:05.000000000 +0000
@@ -1,6 +1,6 @@
-/* ------------------------------------------------------------------------------
+/*
  *
- * Linux/PARISC Project (http://www.thepuffingroup.com/parisc)
+ * Linux/PARISC Project (http://www.parisc-linux.org/)
  *
  * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
  * Licensed under the GNU GPL.
@@ -8,14 +8,23 @@
  * sorry about the wall, puffin..
  */
 
-#define __ASSEMBLY__
 #include <asm/assembly.h>
 #include <asm/offset.h>
 #include <asm/unistd.h>
 #include <asm/errno.h>
 
+#ifdef __LP64__
+	.level          2.0w
+#else
+	.level		1.1
+#endif
 	.text
 
+#ifdef __LP64__
+#define FRAME_SIZE	128
+#else
+#define FRAME_SIZE	64
+#endif
 	.import hpux_call_table
 	.import hpux_syscall_exit,code
 	.export hpux_gateway_page
@@ -23,35 +32,70 @@
 	.align 4096
 hpux_gateway_page:
 	nop
-	mfsp	%sr7,%r1			;! we must set sr3 to the space
-	mtsp	%r1,%sr3			;! of the user before the gate
 #ifdef __LP64__
 #warning NEEDS WORK for 64-bit
 #endif
-	ldw	-64(%r30), %r28			;! 8th argument
+	ldw     -64(%r30), %r29                 ;! 8th argument
 	ldw	-60(%r30), %r19			;! 7th argument
 	ldw	-56(%r30), %r20			;! 6th argument
 	ldw	-52(%r30), %r21			;! 5th argument
-	gate	.+8, %r0			;! become privileged
-	mtsp	%r0,%sr4			;! get kernel space into sr4
-	mtsp	%r0,%sr5			;! get kernel space into sr5
-	mtsp	%r0,%sr6			;! get kernel space into sr6
-	mtsp	%r0,%sr7			;! get kernel space into sr7
-	mfctl	%cr30,%r1			;! get the kernel task ptr
-	mtctl	%r0,%cr30			;! zero it (flag)
-	STREG	%r30,TASK_PT_GR30(%r1)		;! preserve userspace sp
-	STREG	%r2,TASK_PT_GR2(%r1)		;! preserve rp
-	STREG	%r27,TASK_PT_GR27(%r1)		;! user dp
-	STREG	%r31,TASK_PT_GR31(%r1)		;! preserve syscall return ptr
+	gate	.+8, %r0			/* become privileged */
+	mtsp	%r0,%sr4			/* get kernel space into sr4 */
+	mtsp	%r0,%sr5			/* get kernel space into sr5 */
+	mtsp	%r0,%sr6			/* get kernel space into sr6 */
+	mfsp    %sr7,%r1                        /* save user sr7 */
+	mtsp    %r1,%sr3                        /* and store it in sr3 */
+
+	mtctl   %r30,%cr28
+	mfctl   %cr30,%r1
+	xor     %r1,%r30,%r30                   /* ye olde xor trick */
+	xor     %r1,%r30,%r1
+	xor     %r1,%r30,%r30
+	ldo     TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30  /* set up kernel stack */
+
+	/* N.B.: It is critical that we don't set sr7 to 0 until r30
+	 *       contains a valid kernel stack pointer. It is also
+	 *       critical that we don't start using the kernel stack
+	 *       until after sr7 has been set to 0.
+	 */
+
+	mtsp	%r0,%sr7			/* get kernel space into sr7 */
+	STREG   %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1   /* get task ptr in %r1 */
+
+	/* Save some registers for sigcontext and potential task
+	   switch (see entry.S for the details of which ones are
+	   saved/restored).  TASK_PT_PSW is zeroed so we can see whether
+	   a process is on a syscall or not.  For an interrupt the real
+	   PSW value is stored.  This is needed for gdb and sys_ptrace. */
+	STREG	%r0,  TASK_PT_PSW(%r1)
+	STREG	%r2,  TASK_PT_GR2(%r1)		/* preserve rp */
+	STREG   %r19, TASK_PT_GR19(%r1)         /* 7th argument */
+	STREG   %r20, TASK_PT_GR20(%r1)         /* 6th argument */
+	STREG   %r21, TASK_PT_GR21(%r1)         /* 5th argument */
+	STREG   %r22, TASK_PT_GR22(%r1)         /* syscall # */
+	STREG	%r23, TASK_PT_GR23(%r1)		/* 4th argument */
+	STREG	%r24, TASK_PT_GR24(%r1)		/* 3rd argument */
+	STREG	%r25, TASK_PT_GR25(%r1)		/* 2nd argument */
+	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
+	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
+	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
+	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
+	STREG   %r29, TASK_PT_GR29(%r1)         /* 8th argument */
+	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */
+	
+	ldo	TASK_PT_FR0(%r1), %r27		/* save fpregs from the kernel */
+	save_fp	%r27				/* or potential task switch  */
 
-	loadgp					;! setup kernel dp
+	mfctl	%cr11, %r27			/* i.e. SAR */
+	STREG	%r27, TASK_PT_SAR(%r1)
 
-	ldo	TASK_SZ_ALGN+64(%r1),%r30	;! set up kernel stack
+	loadgp
 
 	stw	%r21, -52(%r30)			;! 5th argument
 	stw	%r20, -56(%r30)			;! 6th argument
 	stw	%r19, -60(%r30)			;! 7th argument
-	stw	%r28, -64(%r30)			;! 8th argument
+	stw     %r29, -64(%r30)                 ;! 8th argument
 
 	ldil	L%hpux_call_table, %r21
 	ldo	R%hpux_call_table(%r21), %r21
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/ioctl.c linux/arch/parisc/hpux/ioctl.c
--- linux.orig/arch/parisc/hpux/ioctl.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/hpux/ioctl.c	2002-08-12 22:14:08.000000000 +0000
@@ -19,6 +19,7 @@
  *   TIOCSPGRP
  */
 
+#include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <asm/errno.h>
 #include <asm/ioctl.h>
@@ -54,10 +55,6 @@
 	case 't':
 		result = hpux_ioctl_t(fd, cmd, arg);
 		break;
-	default:
-		/* If my mother ever sees this, I hope she disowns me.
-		 * Take this out after NYLWE. */
-		result = sys_ioctl(fd, cmd, arg);
 	}
 	return result;
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/sys_hpux.c linux/arch/parisc/hpux/sys_hpux.c
--- linux.orig/arch/parisc/hpux/sys_hpux.c	2001-08-09 23:41:36.000000000 +0000
+++ linux/arch/parisc/hpux/sys_hpux.c	2002-08-12 22:14:21.000000000 +0000
@@ -9,6 +9,9 @@
 #include <linux/utsname.h>
 #include <asm/errno.h>
 #include <asm/uaccess.h>
+#include <linux/vmalloc.h>
+#include <asm/pgalloc.h>
+#include <linux/slab.h>
 
 unsigned long sys_brk(unsigned long addr);
  
@@ -41,6 +44,17 @@
 	return sys_waitpid(-1, stat_loc, 0);
 }
 
+int hpux_setpgrp(void)
+{
+	extern int sys_setpgid(int, int);
+	return sys_setpgid(0,0);
+}
+
+int hpux_setpgrp3(void)
+{
+	return hpux_setpgrp();
+}
+
 #define _SC_CPU_VERSION	10001
 #define _SC_OPEN_MAX	4
 #define CPU_PA_RISC1_1	0x210
@@ -129,6 +143,66 @@
 	return err;
 }
 
+/*
+ * Wrapper for hpux statfs call. At the moment, just calls the linux native one
+ * and ignores the extra fields at the end of the hpux statfs struct.
+ *
+ */
+
+typedef int32_t hpux_fsid_t[2];              /* file system ID type */
+typedef uint16_t hpux_site_t;
+
+struct hpux_statfs {
+     int32_t f_type;                    /* type of info, zero for now */
+     int32_t f_bsize;                   /* fundamental file system block size */
+     int32_t f_blocks;                  /* total blocks in file system */
+     int32_t f_bfree;                   /* free block in fs */
+     int32_t f_bavail;                  /* free blocks avail to non-superuser */
+     int32_t f_files;                   /* total file nodes in file system */
+     int32_t f_ffree;                   /* free file nodes in fs */
+     hpux_fsid_t  f_fsid;                    /* file system ID */
+     int32_t f_magic;                   /* file system magic number */
+     int32_t f_featurebits;             /* file system features */
+     int32_t f_spare[4];                /* spare for later */
+     hpux_site_t  f_cnode;                   /* cluster node where mounted */
+     int16_t f_pad;
+};
+
+/* hpux statfs */
+int hpux_statfs(const char *path, struct hpux_statfs *buf)
+{
+	int error;
+	int len;
+	char *kpath;
+
+	len = strlen_user((char *)path); 
+
+	kpath = (char *) kmalloc(len+1, GFP_KERNEL);
+	if ( !kpath ) {
+	printk(KERN_DEBUG "failed to kmalloc kpath\n");
+	return 0;
+	}
+
+	if ( copy_from_user(kpath, (char *)path, len+1) ) {
+	printk(KERN_DEBUG "failed to copy_from_user kpath\n");
+	kfree(kpath);
+	return 0;
+	}
+
+	printk(KERN_DEBUG "hpux_statfs(\"%s\",-)\n", kpath);
+
+	kfree(kpath);
+
+	/* just fake it, beginning of structures match */
+	extern int sys_statfs(const char *, struct statfs *);
+	error = sys_statfs(path, (struct statfs *) buf);
+
+	/* ignoring rest of statfs struct, but it should be zeros. Need to do 
+		something with f_fsid[1], which is the fstype for sysfs */
+
+	return error;
+}
+
 
 /*  This function is called from hpux_utssys(); HP-UX implements
  *  uname() as an option to utssys().
@@ -333,3 +407,541 @@
 	unlock_kernel();
 	return error;
 }
+
+/* lies - says it works, but it really didn't lock anything */
+int hpux_lockf(int fildes, int function, off_t size)
+{
+	return 0;
+}
+
+int hpux_sysfs(int opcode, unsigned long arg1, unsigned long arg2)
+{
+	char *fsname = NULL;
+	int len = 0;
+	int fstype;
+
+/*Unimplemented HP-UX syscall emulation. Syscall #334 (sysfs)
+  Args: 1 80057bf4 0 400179f0 0 0 0 */
+	printk(KERN_DEBUG "in hpux_sysfs\n");
+	printk(KERN_DEBUG "hpux_sysfs called with opcode = %d\n", opcode);
+	printk(KERN_DEBUG "hpux_sysfs called with arg1='%lx'\n", arg1);
+
+	if ( opcode == 1 ) { /* GETFSIND */	
+		len = strlen_user((char *)arg1);
+		printk(KERN_DEBUG "len of arg1 = %d\n", len);
+
+		fsname = (char *) kmalloc(len+1, GFP_KERNEL);
+		if ( !fsname ) {
+			printk(KERN_DEBUG "failed to kmalloc fsname\n");
+			return 0;
+		}
+
+		if ( copy_from_user(fsname, (char *)arg1, len+1) ) {
+			printk(KERN_DEBUG "failed to copy_from_user fsname\n");
+			kfree(fsname);
+			return 0;
+		}
+
+		printk(KERN_DEBUG "that is '%s' as (char *)\n", fsname);
+		if ( !strcmp(fsname, "hfs") ) {
+			fstype = 0;
+		} else {
+			fstype = 0;
+		};
+
+		kfree(fsname);
+
+		printk(KERN_DEBUG "returning fstype=%d\n", fstype);
+		return fstype; /* something other than default */
+	}
+
+
+	return 0;
+}
+
+
+/* Table of syscall names and handle for unimplemented routines */
+static const char *syscall_names[] = {
+	"nosys",                  /* 0 */
+	"exit",                  
+	"fork",                  
+	"read",                  
+	"write",                 
+	"open",                   /* 5 */
+	"close",                 
+	"wait",                  
+	"creat",                 
+	"link",                  
+	"unlink",                 /* 10 */
+	"execv",                 
+	"chdir",                 
+	"time",                  
+	"mknod",                 
+	"chmod",                  /* 15 */
+	"chown",                 
+	"brk",                   
+	"lchmod",                
+	"lseek",                 
+	"getpid",                 /* 20 */
+	"mount",                 
+	"umount",                
+	"setuid",                
+	"getuid",                
+	"stime",                  /* 25 */
+	"ptrace",                
+	"alarm",                 
+	NULL,                    
+	"pause",                 
+	"utime",                  /* 30 */
+	"stty",                  
+	"gtty",                  
+	"access",                
+	"nice",                  
+	"ftime",                  /* 35 */
+	"sync",                  
+	"kill",                  
+	"stat",                  
+	"setpgrp3",              
+	"lstat",                  /* 40 */
+	"dup",                   
+	"pipe",                  
+	"times",                 
+	"profil",                
+	"ki_call",                /* 45 */
+	"setgid",                
+	"getgid",                
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 50 */
+	"acct",                  
+	"set_userthreadid",      
+	NULL,                    
+	"ioctl",                 
+	"reboot",                 /* 55 */
+	"symlink",               
+	"utssys",                
+	"readlink",              
+	"execve",                
+	"umask",                  /* 60 */
+	"chroot",                
+	"fcntl",                 
+	"ulimit",                
+	NULL,                    
+	NULL,                     /* 65 */
+	"vfork",                 
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 70 */
+	"mmap",                  
+	NULL,                    
+	"munmap",                
+	"mprotect",              
+	"madvise",                /* 75 */
+	"vhangup",               
+	"swapoff",               
+	NULL,                    
+	"getgroups",             
+	"setgroups",              /* 80 */
+	"getpgrp2",              
+	"setpgid/setpgrp2",      
+	"setitimer",             
+	"wait3",                 
+	"swapon",                 /* 85 */
+	"getitimer",             
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	"dup2",                   /* 90 */
+	NULL,                    
+	"fstat",                 
+	"select",                
+	NULL,                    
+	"fsync",                  /* 95 */
+	"setpriority",           
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	"getpriority",            /* 100 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 105 */
+	NULL,                    
+	NULL,                    
+	"sigvector",             
+	"sigblock",              
+	"sigsetmask",             /* 110 */
+	"sigpause",              
+	"sigstack",              
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 115 */
+	"gettimeofday",          
+	"getrusage",             
+	NULL,                    
+	NULL,                    
+	"readv",                  /* 120 */
+	"writev",                
+	"settimeofday",          
+	"fchown",                
+	"fchmod",                
+	NULL,                     /* 125 */
+	"setresuid",             
+	"setresgid",             
+	"rename",                
+	"truncate",              
+	"ftruncate",              /* 130 */
+	NULL,                    
+	"sysconf",               
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 135 */
+	"mkdir",                 
+	"rmdir",                 
+	NULL,                    
+	"sigcleanup",            
+	"setcore",                /* 140 */
+	NULL,                    
+	"gethostid",             
+	"sethostid",             
+	"getrlimit",             
+	"setrlimit",              /* 145 */
+	NULL,                    
+	NULL,                    
+	"quotactl",              
+	"get_sysinfo",           
+	NULL,                     /* 150 */
+	"privgrp",               
+	"rtprio",                
+	"plock",                 
+	NULL,                    
+	"lockf",                  /* 155 */
+	"semget",                
+	NULL,                    
+	"semop",                 
+	"msgget",                
+	NULL,                     /* 160 */
+	"msgsnd",                
+	"msgrcv",                
+	"shmget",                
+	NULL,                    
+	"shmat",                  /* 165 */
+	"shmdt",                 
+	NULL,                    
+	"csp/nsp_init",          
+	"cluster",               
+	"mkrnod",                 /* 170 */
+	"test",                  
+	"unsp_open",             
+	NULL,                    
+	"getcontext",            
+	"osetcontext",            /* 175 */
+	"bigio",                 
+	"pipenode",              
+	"lsync",                 
+	"getmachineid",          
+	"cnodeid/mysite",         /* 180 */
+	"cnodes/sitels",         
+	"swapclients",           
+	"rmtprocess",            
+	"dskless_stats",         
+	"sigprocmask",            /* 185 */
+	"sigpending",            
+	"sigsuspend",            
+	"sigaction",             
+	NULL,                    
+	"nfssvc",                 /* 190 */
+	"getfh",                 
+	"getdomainname",         
+	"setdomainname",         
+	"async_daemon",          
+	"getdirentries",          /* 195 */
+	"statfs",                
+	"fstatfs",               
+	"vfsmount",              
+	NULL,                    
+	"waitpid",                /* 200 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 205 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 210 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 215 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 220 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	"sigsetreturn",          
+	"sigsetstatemask",        /* 225 */
+	"bfactl",                
+	"cs",                    
+	"cds",                   
+	NULL,                    
+	"pathconf",               /* 230 */
+	"fpathconf",             
+	NULL,                    
+	NULL,                    
+	"nfs_fcntl",             
+	"ogetacl",                /* 235 */
+	"ofgetacl",              
+	"osetacl",               
+	"ofsetacl",              
+	"pstat",                 
+	"getaudid",               /* 240 */
+	"setaudid",              
+	"getaudproc",            
+	"setaudproc",            
+	"getevent",              
+	"setevent",               /* 245 */
+	"audwrite",              
+	"audswitch",             
+	"audctl",                
+	"ogetaccess",            
+	"fsctl",                  /* 250 */
+	"ulconnect",             
+	"ulcontrol",             
+	"ulcreate",              
+	"uldest",                
+	"ulrecv",                 /* 255 */
+	"ulrecvcn",              
+	"ulsend",                
+	"ulshutdown",            
+	"swapfs",                
+	"fss",                    /* 260 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 265 */
+	NULL,                    
+	"tsync",                 
+	"getnumfds",             
+	"poll",                  
+	"getmsg",                 /* 270 */
+	"putmsg",                
+	"fchdir",                
+	"getmount_cnt",          
+	"getmount_entry",        
+	"accept",                 /* 275 */
+	"bind",                  
+	"connect",               
+	"getpeername",           
+	"getsockname",           
+	"getsockopt",             /* 280 */
+	"listen",                
+	"recv",                  
+	"recvfrom",              
+	"recvmsg",               
+	"send",                   /* 285 */
+	"sendmsg",               
+	"sendto",                
+	"setsockopt",            
+	"shutdown",              
+	"socket",                 /* 290 */
+	"socketpair",            
+	"proc_open",             
+	"proc_close",            
+	"proc_send",             
+	"proc_recv",              /* 295 */
+	"proc_sendrecv",         
+	"proc_syscall",          
+	"ipccreate",             
+	"ipcname",               
+	"ipcnamerase",            /* 300 */
+	"ipclookup",             
+	"ipcselect",             
+	"ipcconnect",            
+	"ipcrecvcn",             
+	"ipcsend",                /* 305 */
+	"ipcrecv",               
+	"ipcgetnodename",        
+	"ipcsetnodename",        
+	"ipccontrol",            
+	"ipcshutdown",            /* 310 */
+	"ipcdest",               
+	"semctl",                
+	"msgctl",                
+	"shmctl",                
+	"mpctl",                  /* 315 */
+	"exportfs",              
+	"getpmsg",               
+	"putpmsg",               
+	"strioctl",              
+	"msync",                  /* 320 */
+	"msleep",                
+	"mwakeup",               
+	"msem_init",             
+	"msem_remove",           
+	"adjtime",                /* 325 */
+	"kload",                 
+	"fattach",               
+	"fdetach",               
+	"serialize",             
+	"statvfs",                /* 330 */
+	"fstatvfs",              
+	"lchown",                
+	"getsid",                
+	"sysfs",                 
+	NULL,                     /* 335 */
+	NULL,                    
+	"sched_setparam",        
+	"sched_getparam",        
+	"sched_setscheduler",    
+	"sched_getscheduler",     /* 340 */
+	"sched_yield",           
+	"sched_get_priority_max",
+	"sched_get_priority_min",
+	"sched_rr_get_interval", 
+	"clock_settime",          /* 345 */
+	"clock_gettime",         
+	"clock_getres",          
+	"timer_create",          
+	"timer_delete",          
+	"timer_settime",          /* 350 */
+	"timer_gettime",         
+	"timer_getoverrun",      
+	"nanosleep",             
+	"toolbox",               
+	NULL,                     /* 355 */
+	"getdents",              
+	"getcontext",            
+	"sysinfo",               
+	"fcntl64",               
+	"ftruncate64",            /* 360 */
+	"fstat64",               
+	"getdirentries64",       
+	"getrlimit64",           
+	"lockf64",               
+	"lseek64",                /* 365 */
+	"lstat64",               
+	"mmap64",                
+	"setrlimit64",           
+	"stat64",                
+	"truncate64",             /* 370 */
+	"ulimit64",              
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                     /* 375 */
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	NULL,                    
+	"setcontext",             /* 380 */
+	"sigaltstack",           
+	"waitid",                
+	"setpgrp",               
+	"recvmsg2",              
+	"sendmsg2",               /* 385 */
+	"socket2",               
+	"socketpair2",           
+	"setregid",              
+	"lwp_create",            
+	"lwp_terminate",          /* 390 */
+	"lwp_wait",              
+	"lwp_suspend",           
+	"lwp_resume",            
+	"lwp_self",              
+	"lwp_abort_syscall",      /* 395 */
+	"lwp_info",              
+	"lwp_kill",              
+	"ksleep",                
+	"kwakeup",               
+	"ksleep_abort",           /* 400 */
+	"lwp_proc_info",         
+	"lwp_exit",              
+	"lwp_continue",          
+	"getacl",                
+	"fgetacl",                /* 405 */
+	"setacl",                
+	"fsetacl",               
+	"getaccess",             
+	"lwp_mutex_init",        
+	"lwp_mutex_lock_sys",     /* 410 */
+	"lwp_mutex_unlock",      
+	"lwp_cond_init",         
+	"lwp_cond_signal",       
+	"lwp_cond_broadcast",    
+	"lwp_cond_wait_sys",      /* 415 */
+	"lwp_getscheduler",      
+	"lwp_setscheduler",      
+	"lwp_getprivate",        
+	"lwp_setprivate",        
+	"lwp_detach",             /* 420 */
+	"mlock",                 
+	"munlock",               
+	"mlockall",              
+	"munlockall",            
+	"shm_open",               /* 425 */
+	"shm_unlink",            
+	"sigqueue",              
+	"sigwaitinfo",           
+	"sigtimedwait",          
+	"sigwait",                /* 430 */
+	"aio_read",              
+	"aio_write",             
+	"lio_listio",            
+	"aio_error",             
+	"aio_return",             /* 435 */
+	"aio_cancel",            
+	"aio_suspend",           
+	"aio_fsync",             
+	"mq_open",               
+	"mq_unlink",              /* 440 */
+	"mq_send",               
+	"mq_receive",            
+	"mq_notify",             
+	"mq_setattr",            
+	"mq_getattr",             /* 445 */
+	"ksem_open",             
+	"ksem_unlink",           
+	"ksem_close",            
+	"ksem_destroy",          
+	"lw_sem_incr",            /* 450 */
+	"lw_sem_decr",           
+	"lw_sem_read",           
+	"mq_close",              
+};
+static const int syscall_names_max = 453;
+
+int
+hpux_unimplemented(unsigned long arg1,unsigned long arg2,unsigned long arg3,
+		   unsigned long arg4,unsigned long arg5,unsigned long arg6,
+		   unsigned long arg7,unsigned long sc_num)
+{
+	/* NOTE: sc_num trashes arg8 for the few syscalls that actually
+	 * have a valid 8th argument.
+	 */
+	const char *name = NULL;
+	if ( sc_num <= syscall_names_max && sc_num >= 0 ) {
+		name = syscall_names[sc_num];
+	}
+
+	if ( name ) {
+		printk(KERN_DEBUG "Unimplemented HP-UX syscall emulation. Syscall #%lu (%s)\n",
+		sc_num, name);
+	} else {
+		printk(KERN_DEBUG "Unimplemented unknown HP-UX syscall emulation. Syscall #%lu\n",
+		sc_num);
+	}
+	
+	printk(KERN_DEBUG "  Args: %lx %lx %lx %lx %lx %lx %lx\n",
+		arg1, arg2, arg3, arg4, arg5, arg6, arg7);
+
+	return -ENOSYS;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/hpux/wrappers.S linux/arch/parisc/hpux/wrappers.S
--- linux.orig/arch/parisc/hpux/wrappers.S	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/hpux/wrappers.S	2002-08-12 22:14:15.000000000 +0000
@@ -1,5 +1,5 @@
-/*------------------------------------------------------------------------------
- * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+/*
+ * Linux/PARISC Project (http://www.parisc-linux.org/)
  *
  * HP-UX System Call Wrapper routines and System Call Return Path
  *
@@ -29,7 +29,6 @@
 	.level		1.1
 	.text
 
-#define __ASSEMBLY__
 #include <asm/assembly.h>
 #include <asm/signal.h>
 
@@ -81,6 +80,7 @@
 
 
 	.export hpux_fork_wrapper
+	.export hpux_child_return
 	.import sys_fork
 
 hpux_fork_wrapper:
@@ -91,12 +91,10 @@
 	stw	%r2,-20(%r30)
 	ldo	64(%r30),%r30
 	stw	%r2,PT_GR19(%r1)	;! save for child
-	stw	%r30,PT_GR20(%r1)	;! save for child
-	ldil	L%child_return,%r3
-	ldo	R%child_return(%r3),%r3
-	stw	%r3,PT_GR21(%r1)	;! save for child
+	stw	%r30,PT_GR21(%r1)	;! save for child
 
-	ldw	TASK_PT_GR30(%r1),%r25
+	ldw     PT_GR30(%r1),%r25
+	mtctl   %r25,%cr29
 	copy	%r1,%r24
 	bl	sys_clone,%r2
 	ldi	SIGCHLD,%r26
@@ -130,7 +128,10 @@
 
 	/* Set the return value for the child */
 
-child_return:
+hpux_child_return:
+	bl	schedule_tail, %r2
+	nop
+
 	ldw TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
 	b fork_return
 	copy %r0,%r28
@@ -242,3 +243,10 @@
 no_error:
 	b syscall_exit
 	nop
+
+	.export hpux_unimplemented_wrapper
+	.import hpux_unimplemented
+
+hpux_unimplemented_wrapper:
+	b hpux_unimplemented
+	stw %r22,-64(%r30)  /* overwrite arg8 with syscall number */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/Makefile linux/arch/parisc/kernel/Makefile
--- linux.orig/arch/parisc/kernel/Makefile	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/Makefile	2002-08-12 22:14:13.000000000 +0000
@@ -7,26 +7,30 @@
 #
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
-all: kernel.o init_task.o pdc_cons.o process.o head.o
-O_TARGET = kernel.o
-O_OBJS = 
+ifdef CONFIG_PARISC64
+all: kernel.o init_task.o pdc_cons.o process.o head64.o unaligned.o perf.o perf_asm.o
+else
+all: kernel.o init_task.o pdc_cons.o process.o head.o unaligned.o
+endif
 
-# Object file lists.
+O_TARGET = kernel.o
 
 obj-y		:=
 obj-m		:=
 obj-n		:=
 obj-		:=
 
-obj-y		+= cache.o setup.o traps.o time.o irq.o \
-		syscall.o entry.o sys_parisc.o pdc.o ptrace.o hardware.o \
-		inventory.o drivers.o semaphore.o pa7300lc.o pci-dma.o \
-		signal.o hpmc.o \
-		real1.o real2.o led.o parisc_ksyms.o
+obj-y           += cache.o pacache.o setup.o traps.o time.o irq.o \
+		pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
+		ptrace.o hardware.o inventory.o drivers.o semaphore.o \
+		signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
+		processor.o power.o
 
-export-objs	:= parisc_ksyms.o
+export-objs	:= parisc_ksyms.o superio.o keyboard.o
 
 
+obj-$(CONFIG_SMP) += smp.o irq_smp.o
+obj-$(CONFIG_PA11) += pci-dma.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_VT) += keyboard.o
 obj-$(CONFIG_PCI_LBA) += lba_pci.o
@@ -37,16 +41,11 @@
 # Only use one of them: ccio-rm-dma is for PCX-W systems *only*
 # obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
 obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
-
-.o.S:	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $*.S -o $*.o
-
-# Translate to Rules.make lists.
-
-O_OBJS          := $(filter-out $(export-objs), $(obj-y))
-OX_OBJS         := $(filter     $(export-objs), $(obj-y))
-M_OBJS          := $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS         := $(sort $(filter     $(export-objs), $(obj-m)))
-MI_OBJS		:= $(sort $(filter-out $(export-objs), $(int-m)))
-MIX_OBJS	:= $(sort $(filter     $(export-objs), $(int-m)))
+obj-$(CONFIG_CHASSIS_LCD_LED) += led.o 
+obj-$(CONFIG_SUPERIO) += superio.o
+obj-$(CONFIG_PARISC64) += binfmt_elf32.o sys_parisc32.o \
+		ioctl32.o signal32.o
+# only supported for PCX-W/U in 64-bit mode at the moment
+obj-$(CONFIG_PARISC64) += perf.o perf_asm.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/binfmt_elf32.c linux/arch/parisc/kernel/binfmt_elf32.c
--- linux.orig/arch/parisc/kernel/binfmt_elf32.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/binfmt_elf32.c	2002-08-12 22:14:21.000000000 +0000
@@ -0,0 +1,93 @@
+/*
+ * Support for 32-bit Linux/Parisc ELF binaries on 64 bit kernels
+ *
+ * Copyright (C) 2000 John Marvin
+ * Copyright (C) 2000 Hewlett Packard Co.
+ *
+ * Heavily inspired from various other efforts to do the same thing
+ * (ia64,sparc64/mips64)
+ */
+
+/* Make sure include/asm-parisc/elf.h does the right thing */
+
+#define ELF_CLASS	ELFCLASS32
+
+typedef unsigned int elf_greg_t;
+
+#include <linux/spinlock.h>
+#include <asm/processor.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/elfcore.h>
+#include "sys32.h"		/* struct timeval32 */
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+	struct elf_siginfo pr_info;	/* Info associated with signal */
+	short	pr_cursig;		/* Current signal */
+	unsigned int pr_sigpend;	/* Set of pending signals */
+	unsigned int pr_sighold;	/* Set of held signals */
+	pid_t	pr_pid;
+	pid_t	pr_ppid;
+	pid_t	pr_pgrp;
+	pid_t	pr_sid;
+	struct timeval32 pr_utime;	/* User time */
+	struct timeval32 pr_stime;	/* System time */
+	struct timeval32 pr_cutime;	/* Cumulative user time */
+	struct timeval32 pr_cstime;	/* Cumulative system time */
+	elf_gregset_t pr_reg;	/* GP registers */
+	int pr_fpvalid;		/* True if math co-processor being used.  */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+	char	pr_state;	/* numeric process state */
+	char	pr_sname;	/* char for pr_state */
+	char	pr_zomb;	/* zombie */
+	char	pr_nice;	/* nice val */
+	unsigned int pr_flag;	/* flags */
+	u16	pr_uid;
+	u16	pr_gid;
+	pid_t	pr_pid, pr_ppid, pr_pgrp, pr_sid;
+	/* Lots missing */
+	char	pr_fname[16];	/* filename of executable */
+	char	pr_psargs[ELF_PRARGSZ];	/* initial part of arg list */
+};
+
+#define elf_addr_t	unsigned int
+typedef unsigned int elf_caddr_t;
+#define init_elf_binfmt init_elf32_binfmt
+
+#define ELF_PLATFORM  ("PARISC32\0")
+
+#define ELF_CORE_COPY_REGS(dst, pt)	\
+	memset(dst, 0, sizeof(dst));	/* don't leak any "random" bits */ \
+	{	int i; \
+		for (i = 0; i < 32; i++) dst[i] = (elf_greg_t) pt->gr[i]; \
+		for (i = 0; i < 8; i++) dst[32 + i] = (elf_greg_t) pt->sr[i]; \
+	} \
+	dst[40] = (elf_greg_t) pt->iaoq[0]; dst[41] = (elf_greg_t) pt->iaoq[1]; \
+	dst[42] = (elf_greg_t) pt->iasq[0]; dst[43] = (elf_greg_t) pt->iasq[1]; \
+	dst[44] = (elf_greg_t) pt->sar;   dst[45] = (elf_greg_t) pt->iir; \
+	dst[46] = (elf_greg_t) pt->isr;   dst[47] = (elf_greg_t) pt->ior; \
+	dst[48] = (elf_greg_t) mfctl(22); dst[49] = (elf_greg_t) mfctl(0); \
+	dst[50] = (elf_greg_t) mfctl(24); dst[51] = (elf_greg_t) mfctl(25); \
+	dst[52] = (elf_greg_t) mfctl(26); dst[53] = (elf_greg_t) mfctl(27); \
+	dst[54] = (elf_greg_t) mfctl(28); dst[55] = (elf_greg_t) mfctl(29); \
+	dst[56] = (elf_greg_t) mfctl(30); dst[57] = (elf_greg_t) mfctl(31); \
+	dst[58] = (elf_greg_t) mfctl( 8); dst[59] = (elf_greg_t) mfctl( 9); \
+	dst[60] = (elf_greg_t) mfctl(12); dst[61] = (elf_greg_t) mfctl(13); \
+	dst[62] = (elf_greg_t) mfctl(10); dst[63] = (elf_greg_t) mfctl(15);
+
+/*
+ * We should probably use this macro to set a flag somewhere to indicate
+ * this is a 32 on 64 process. We could use PER_LINUX_32BIT, or we
+ * could set a processor dependent flag in the thread_struct.
+ */
+
+#define SET_PERSONALITY(ex, ibcs2) \
+	current->personality = PER_LINUX_32BIT
+
+#include "../../../fs/binfmt_elf.c"
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/cache.c linux/arch/parisc/kernel/cache.c
--- linux.orig/arch/parisc/kernel/cache.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/cache.c	2002-08-12 22:14:17.000000000 +0000
@@ -15,202 +15,85 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/seq_file.h>
 
 #include <asm/pdc.h>
 #include <asm/cache.h>
 #include <asm/system.h>
 #include <asm/page.h>
 #include <asm/pgalloc.h>
+#include <asm/processor.h>
+
+int split_tlb;
+int dcache_stride;
+int icache_stride;
 
 struct pdc_cache_info cache_info;
-#ifndef __LP64__
+#ifndef CONFIG_PA20
 static struct pdc_btlb_info btlb_info;
 #endif
 
-
-void __flush_page_to_ram(unsigned long address)
-{
-	__flush_dcache_range(address, PAGE_SIZE);
-	__flush_icache_range(address, PAGE_SIZE);
-}
-
-
-
-void flush_data_cache(void)
+#ifdef CONFIG_SMP
+void
+flush_data_cache(void)
 {
-	register unsigned long base   = cache_info.dc_base;
-	register unsigned long count  = cache_info.dc_count;
-	register unsigned long loop   = cache_info.dc_loop;
-	register unsigned long stride = cache_info.dc_stride;
-	register unsigned long addr;
-	register long i, j;
-
-	for(i=0,addr=base; i<count; i++,addr+=stride)
-		for(j=0; j<loop; j++)
-			fdce(addr);
-}
-		
-static inline void flush_data_tlb_space(void)
-{
-	unsigned long base   = cache_info.dt_off_base;
-	unsigned long count  = cache_info.dt_off_count;
-	unsigned long stride = cache_info.dt_off_stride;
-	unsigned long loop   = cache_info.dt_loop;
-
-	unsigned long addr;
-	long i,j;
-	
-	for(i=0,addr=base; i<count; i++,addr+=stride)
-		for(j=0; j<loop; j++)
-			pdtlbe(addr);
-}
-
-
-
-void flush_data_tlb(void)
-{
-	unsigned long base   = cache_info.dt_sp_base;
-	unsigned long count  = cache_info.dt_sp_count;
-	unsigned long stride = cache_info.dt_sp_stride;
-	unsigned long space;
-	unsigned long old_sr1;
-	long i;
-	
-	old_sr1 = mfsp(1);
-	
-	for(i=0,space=base; i<count; i++, space+=stride) {
-		mtsp(space,1);
-		flush_data_tlb_space();
-	}
-
-	mtsp(old_sr1, 1);
+	smp_call_function((void (*)(void *))flush_data_cache_local, NULL, 1, 1);
+	flush_data_cache_local();
 }
+#endif
 
-static inline void flush_instruction_tlb_space(void)
+void
+flush_cache_all_local(void)
 {
-	unsigned long base   = cache_info.it_off_base;
-	unsigned long count  = cache_info.it_off_count;
-	unsigned long stride = cache_info.it_off_stride;
-	unsigned long loop   = cache_info.it_loop;
-
-	unsigned long addr;
-	long i,j;
-	
-	for(i=0,addr=base; i<count; i++,addr+=stride)
-		for(j=0; j<loop; j++)
-			pitlbe(addr);
-}
-
-void flush_instruction_tlb(void)
-{
-	unsigned long base   = cache_info.it_sp_base;
-	unsigned long count  = cache_info.it_sp_count;
-	unsigned long stride = cache_info.it_sp_stride;
-	unsigned long space;
-	unsigned long old_sr1;
-	unsigned int i;
-	
-	old_sr1 = mfsp(1);
-	
-	for(i=0,space=base; i<count; i++, space+=stride) {
-		mtsp(space,1);
-		flush_instruction_tlb_space();
-	}
-
-	mtsp(old_sr1, 1);
+	flush_instruction_cache_local();
+	flush_data_cache_local();
 }
 
+/* flushes EVERYTHING (tlb & cache) */
 
-void __flush_tlb_space(unsigned long space)
+void
+flush_all_caches(void)
 {
-	unsigned long old_sr1;
-
-	old_sr1 = mfsp(1);
-	mtsp(space, 1);
-	
-	flush_data_tlb_space();
-	flush_instruction_tlb_space();
-
-	mtsp(old_sr1, 1);
+	flush_cache_all();
+	flush_tlb_all();
 }
 
-
-void flush_instruction_cache(void)
+void
+update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte)
 {
-	register unsigned long base   = cache_info.ic_base;
-	register unsigned long count  = cache_info.ic_count;
-	register unsigned long loop   = cache_info.ic_loop;
-	register unsigned long stride = cache_info.ic_stride;
-	register unsigned long addr;
-	register long i, j;
-	unsigned long old_sr1;
-	
-	old_sr1 = mfsp(1);
-	mtsp(0,1);
+	struct page *page = pte_page(pte);
 
-	/*
-	 * Note: fice instruction has 3 bit space field, so one must
-	 *       be specified (otherwise you are justing using whatever
-	 *       happens to be in sr0).
-	 */
+	if (VALID_PAGE(page) && page->mapping &&
+	    test_bit(PG_dcache_dirty, &page->flags)) {
 
-	for(i=0,addr=base; i<count; i++,addr+=stride)
-		for(j=0; j<loop; j++)
-			fice(addr);
-
-	mtsp(old_sr1, 1);
-}
-
-/* not yet ... fdc() needs to be implemented in cache.h !
-void flush_datacache_range( unsigned int base, unsigned int end )
-{
-    register long offset,offset_add;
-    offset_add = ( (1<<(cache_info.dc_conf.cc_block-1)) * 
-		    cache_info.dc_conf.cc_line ) << 4;
-    for (offset=base; offset<=end; offset+=offset_add)
-	fdc(space,offset);
-    fdc(space,end);
-}
-*/
-
-/* flushes code and data-cache */
-void flush_all_caches(void)
-{
-	flush_instruction_cache();
-	flush_data_cache();
-
-	flush_instruction_tlb();
-	flush_data_tlb();
-
-	asm volatile("sync");
-	asm volatile("syncdma");
-	asm volatile("sync");
+		flush_kernel_dcache_page(page_address(page));
+		clear_bit(PG_dcache_dirty, &page->flags);
+	}
 }
 
-int get_cache_info(char *buffer)
+void
+show_cache_info(struct seq_file *m)
 {
-	char *p = buffer;
-
-	p += sprintf(p, "I-cache\t\t: %ld KB\n", 
+	seq_printf(m, "I-cache\t\t: %ld KB\n", 
 		cache_info.ic_size/1024 );
-	p += sprintf(p, "D-cache\t\t: %ld KB (%s)%s\n", 
+	seq_printf(m, "D-cache\t\t: %ld KB (%s)%s\n", 
 		cache_info.dc_size/1024,
 		(cache_info.dc_conf.cc_wt ? "WT":"WB"),
 		(cache_info.dc_conf.cc_sh ? " - shared I/D":"")
 	);
 
-	p += sprintf(p, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
+	seq_printf(m, "ITLB entries\t: %ld\n" "DTLB entries\t: %ld%s\n",
 		cache_info.it_size,
 		cache_info.dt_size,
 		cache_info.dt_conf.tc_sh ? " - shared with ITLB":""
 	);
 		
-#ifndef __LP64__
+#ifndef CONFIG_PA20
 	/* BTLB - Block TLB */
 	if (btlb_info.max_size==0) {
-		p += sprintf(p, "BTLB\t\t: not supported\n" );
+		seq_printf(m, "BTLB\t\t: not supported\n" );
 	} else {
-		p += sprintf(p, 
+		seq_printf(m, 
 		"BTLB fixed\t: max. %d pages, pagesize=%d (%dMB)\n"
 		"BTLB fix-entr.\t: %d instruction, %d data (%d combined)\n"
 		"BTLB var-entr.\t: %d instruction, %d data (%d combined)\n",
@@ -225,11 +108,8 @@
 		);
 	}
 #endif
-
-	return p - buffer;
 }
 
-
 void __init 
 cache_init(void)
 {
@@ -237,17 +117,108 @@
 		panic("cache_init: pdc_cache_info failed");
 
 #if 0
-	printk("ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
+	printk(KERN_DEBUG "ic_size %lx dc_size %lx it_size %lx pdc_cache_info %d*long pdc_cache_cf %d\n",
 	    cache_info.ic_size,
 	    cache_info.dc_size,
 	    cache_info.it_size,
 	    sizeof (struct pdc_cache_info) / sizeof (long),
 	    sizeof (struct pdc_cache_cf)
 	);
+
+	printk(KERN_DEBUG "dc base %x dc stride %x dc count %x dc loop %d\n",
+	    cache_info.dc_base,
+	    cache_info.dc_stride,
+	    cache_info.dc_count,
+	    cache_info.dc_loop);
+
+	printk(KERN_DEBUG "dc conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n",
+	    cache_info.dc_conf.cc_alias,
+	    cache_info.dc_conf.cc_block,
+	    cache_info.dc_conf.cc_line,
+	    cache_info.dc_conf.cc_wt,
+	    cache_info.dc_conf.cc_sh,
+	    cache_info.dc_conf.cc_cst,
+	    cache_info.dc_conf.cc_assoc);
+
+	printk(KERN_DEBUG "ic conf: alias %d block %d line %d wt %d sh %d cst %d assoc %d\n",
+	    cache_info.ic_conf.cc_alias,
+	    cache_info.ic_conf.cc_block,
+	    cache_info.ic_conf.cc_line,
+	    cache_info.ic_conf.cc_wt,
+	    cache_info.ic_conf.cc_sh,
+	    cache_info.ic_conf.cc_cst,
+	    cache_info.ic_conf.cc_assoc);
+
+	printk(KERN_DEBUG "dt conf: sh %d page %d cst %d aid %d pad1 %d \n",
+	    cache_info.dt_conf.tc_sh,
+	    cache_info.dt_conf.tc_page,
+	    cache_info.dt_conf.tc_cst,
+	    cache_info.dt_conf.tc_aid,
+	    cache_info.dt_conf.tc_pad1);
+
+	printk(KERN_DEBUG "it conf: sh %d page %d cst %d aid %d pad1 %d \n",
+	    cache_info.it_conf.tc_sh,
+	    cache_info.it_conf.tc_page,
+	    cache_info.it_conf.tc_cst,
+	    cache_info.it_conf.tc_aid,
+	    cache_info.it_conf.tc_pad1);
 #endif
-#ifndef __LP64__
+
+	split_tlb = 0;
+	if (cache_info.dt_conf.tc_sh == 0 || cache_info.dt_conf.tc_sh == 2) {
+
+	    if (cache_info.dt_conf.tc_sh == 2)
+		printk(KERN_WARNING "Unexpected TLB configuration. "
+			"Will flush I/D separately (could be optimized).\n");
+
+	    split_tlb = 1;
+	}
+
+	dcache_stride = ( (1<<(cache_info.dc_conf.cc_block+3)) *
+			 cache_info.dc_conf.cc_line );
+	icache_stride = ( (1<<(cache_info.ic_conf.cc_block+3)) *
+			 cache_info.ic_conf.cc_line );
+#ifndef CONFIG_PA20
 	if(pdc_btlb_info(&btlb_info)<0) {
 		memset(&btlb_info, 0, sizeof btlb_info);
 	}
 #endif
+
+	if ((boot_cpu_data.pdc.capabilities & PDC_MODEL_NVA_MASK) == PDC_MODEL_NVA_UNSUPPORTED) {
+		printk(KERN_WARNING "Only equivalent aliasing supported\n");
+#ifndef CONFIG_SMP
+		panic("SMP kernel required to avoid non-equivalent aliasing");
+#endif
+	}
+}
+
+void disable_sr_hashing(void)
+{
+    int srhash_type;
+
+    if (boot_cpu_data.cpu_type == pcxl2)
+	return; /* pcxl2 doesn't support space register hashing */
+
+    switch (boot_cpu_data.cpu_type) {
+
+    case pcx:
+	BUG(); /* We shouldn't get here. code in setup.c should prevent it */
+	return;
+
+    case pcxs:
+    case pcxt:
+    case pcxt_:
+	srhash_type = SRHASH_PCXST;
+	break;
+
+    case pcxl:
+	srhash_type = SRHASH_PCXL;
+	break;
+
+    default: /* Currently all PA2.0 machines use the same ins. sequence */
+	srhash_type = SRHASH_PA20;
+	break;
+    }
+
+    disable_sr_hashing_asm(srhash_type);
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/ccio-dma.c linux/arch/parisc/kernel/ccio-dma.c
--- linux.orig/arch/parisc/kernel/ccio-dma.c	2001-10-12 22:35:53.000000000 +0000
+++ linux/arch/parisc/kernel/ccio-dma.c	2002-08-12 22:14:07.000000000 +0000
@@ -38,16 +38,19 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/string.h>
+#define PCI_DEBUG
 #include <linux/pci.h>
+#undef PCI_DEBUG
 
 #include <asm/byteorder.h>
 #include <asm/cache.h>		/* for L1_CACHE_BYTES */
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/page.h>
-
+#include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/gsc.h>		/* for gsc_writeN()... */
+#include <asm/hardware.h>       /* for register_module() */
 
 /* 
 ** Choose "ccio" since that's what HP-UX calls it.
@@ -55,12 +58,10 @@
 */
 #define MODULE_NAME "ccio"
 
-/*
-#define DEBUG_CCIO_RES
-#define DEBUG_CCIO_RUN
-#define DEBUG_CCIO_INIT
-#define DUMP_RESMAP
-*/
+#undef DEBUG_CCIO_RES
+#undef DEBUG_CCIO_RUN
+#undef DEBUG_CCIO_INIT
+#undef DEBUG_CCIO_RUN_SG
 
 #include <linux/proc_fs.h>
 #include <asm/runway.h>		/* for proc_runway_root */
@@ -83,68 +84,20 @@
 #define DBG_RES(x...)
 #endif
 
+#ifdef DEBUG_CCIO_RUN_SG
+#define DBG_RUN_SG(x...) printk(x)
+#else
+#define DBG_RUN_SG(x...)
+#endif
+
 #define CCIO_INLINE	/* inline */
-#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
+#define WRITE_U32(value, addr) gsc_writel(value, (u32 *)(addr))
+#define READ_U32(addr) gsc_readl((u32 *)(addr))
 
 #define U2_IOA_RUNWAY 0x580
 #define U2_BC_GSC     0x501
 #define UTURN_IOA_RUNWAY 0x581
 #define UTURN_BC_GSC     0x502
-/* We *can't* support JAVA (T600). Venture there at your own risk. */
-
-static void dump_resmap(void);
-
-static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
-
-static struct pa_iodc_driver ccio_drivers_for[] = {
-
-   {HPHW_IOA, U2_IOA_RUNWAY, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
-
-   {HPHW_IOA, UTURN_IOA_RUNWAY, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
-
-/*
-** FIXME: The following claims the GSC bus port, not the IOA.
-**        And there are two busses below a single I/O TLB.
-**
-** These should go away once we have a real PA bus walk.
-** Firmware wants to tell the PA bus walk code about the GSC ports
-** since they are not "architected" PA I/O devices. Ie a PA bus walk
-** wouldn't discover them. But the PA bus walk code could check
-** the "fixed module table" to add such devices to an I/O Tree
-** and proceed with the recursive, depth first bus walk.
-*/
-   {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xc, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "U2 GSC+ BC", (void *) ccio_driver_callback},
-
-   {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xc, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "Uturn GSC+ BC", (void *) ccio_driver_callback},
-
-   {0,0,0,0,0,0,
-   0,
-   (char *) NULL, (char *) NULL, (void *) NULL }
-};
-
-
-#define IS_U2(id) ( \
-    (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
-    (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC))  \
-)
-
-#define IS_UTURN(id) ( \
-    (((id)->hw_type == HPHW_IOA) && ((id)->hversion == UTURN_IOA_RUNWAY)) || \
-    (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC))  \
-)
-
 
 #define IOA_NORMAL_MODE      0x00020080 /* IO_CONTROL to turn on CCIO        */
 #define CMD_TLB_DIRECT_WRITE 35         /* IO_COMMAND for I/O TLB Writes     */
@@ -176,41 +129,46 @@
         volatile uint32_t   io_io_high;             /* Offset 15 */
 };
 
+struct ioc {
+	struct ioa_registers *ioc_hpa;  /* I/O MMU base address */
+	u8  *res_map;	                /* resource map, bit == pdir entry */
+	u64 *pdir_base;	                /* physical base address */
+	u32 res_hint;	                /* next available IOVP - 
+					   circular search */
+	u32 res_size;		    	/* size of resource map in bytes */
+	spinlock_t res_lock;
+
+#ifdef CONFIG_PROC_FS
+#define CCIO_SEARCH_SAMPLE 0x100
+	unsigned long avg_search[CCIO_SEARCH_SAMPLE];
+	unsigned long avg_idx;		  /* current index into avg_search */
+	unsigned long used_pages;
+	unsigned long msingle_calls;
+	unsigned long msingle_pages;
+	unsigned long msg_calls;
+	unsigned long msg_pages;
+	unsigned long usingle_calls;
+	unsigned long usingle_pages;
+	unsigned long usg_calls;
+	unsigned long usg_pages;
 
-struct ccio_device {
-	struct ccio_device    *next;  /* list of LBA's in system */
-	struct hp_device      *iodc;  /* data about dev from firmware */
-	spinlock_t            ccio_lock;
-
-	struct ioa_registers   *ccio_hpa; /* base address */
-	u64   *pdir_base;   /* physical base address */
-	char  *res_map;     /* resource map, bit == pdir entry */
-
-	int   res_hint;	/* next available IOVP - circular search */
-	int   res_size;	/* size of resource map in bytes */
-	int   chainid_shift; /* specify bit location of chain_id */
-	int   flags;         /* state/functionality enabled */
-#ifdef DELAYED_RESOURCE_CNT
-	dma_addr_t res_delay[DELAYED_RESOURCE_CNT];
+	unsigned short cujo20_bug;
 #endif
 
 	/* STUFF We don't need in performance path */
-	int  pdir_size;     /* in bytes, determined by IOV Space size */
-	int  hw_rev;        /* HW revision of chip */
+	u32 pdir_size; 			/* in bytes, determined by IOV Space size */
+	u32 chainid_shift; 		/* specify bit location of chain_id */
+	struct ioc *next;		/* Linked list of discovered iocs */
+	const char *name;		/* device name from firmware */
+	unsigned int hw_path;           /* the hardware path this ioc is associatd with */
+	struct pci_dev *fake_pci_dev;   /* the fake pci_dev for non-pci devs */
+	struct resource mmio_region[2]; /* The "routed" MMIO regions */
 };
 
-
 /* Ratio of Host MEM to IOV Space size */
 static unsigned long ccio_mem_ratio = 4;
-static struct ccio_device *ccio_list = NULL;
-
-static int ccio_proc_info(char *buffer, char **start, off_t offset, int length);
-static unsigned long ccio_used_bytes = 0;
-static unsigned long ccio_used_pages = 0;
-static int ccio_cujo_bug = 0;
-
-static unsigned long ccio_alloc_size = 0;
-static unsigned long ccio_free_size = 0;
+static struct ioc *ioc_list;
+static int ioc_count;
 
 /**************************************************************
 *
@@ -227,55 +185,41 @@
 *   match the I/O TLB replacement policy.
 *
 ***************************************************************/
-#define PAGES_PER_RANGE 1	/* could increase this to 4 or 8 if needed */
 #define IOVP_SIZE PAGE_SIZE
 #define IOVP_SHIFT PAGE_SHIFT
 #define IOVP_MASK PAGE_MASK
 
 /* Convert from IOVP to IOVA and vice versa. */
 #define CCIO_IOVA(iovp,offset) ((iovp) | (offset))
-#define CCIO_IOVP(iova) ((iova) & ~(IOVP_SIZE-1) )
+#define CCIO_IOVP(iova) ((iova) & IOVP_MASK)
 
 #define PDIR_INDEX(iovp)    ((iovp)>>IOVP_SHIFT)
 #define MKIOVP(pdir_idx)    ((long)(pdir_idx) << IOVP_SHIFT)
 #define MKIOVA(iovp,offset) (dma_addr_t)((long)iovp | (long)offset)
-
-/* CUJO20 KLUDGE start */
-#define CUJO_20_BITMASK    0x0ffff000	/* upper nibble is a don't care   */
-#define CUJO_20_STEP       0x10000000	/* inc upper nibble */
-#define CUJO_20_BADPAGE1   0x01003000	/* pages that hpmc on raven U+    */
-#define CUJO_20_BADPAGE2   0x01607000	/* pages that hpmc on firehawk U+ */
-#define CUJO_20_BADHVERS   0x6821	/* low nibble 1 is cujo rev 2.0 */
-#define CUJO_RAVEN_LOC     0xf1000000UL	/* cujo location on raven U+ */
-#define CUJO_FIREHAWK_LOC  0xf1604000UL	/* cujo location on firehawk U+ */
-/* CUJO20 KLUDGE end */
+#define ROUNDUP(x,y) ((x + ((y)-1)) & ~((y)-1))
 
 /*
 ** Don't worry about the 150% average search length on a miss.
 ** If the search wraps around, and passes the res_hint, it will
 ** cause the kernel to panic anyhow.
 */
-
-/* ioa->res_hint = idx + (size >> 3); \ */
-
-#define CCIO_SEARCH_LOOP(ioa, idx, mask, size)  \
-       for(; res_ptr < res_end; ++res_ptr) \
-       { \
-               if(0 == ((*res_ptr) & mask)) { \
-                       *res_ptr |= mask; \
-                       idx = (int)((unsigned long)res_ptr - (unsigned long)ioa->res_map); \
-                       ioa->res_hint = 0;\
+#define CCIO_SEARCH_LOOP(ioc, res_idx, mask_ptr, size)  \
+       for(; res_ptr < res_end; ++res_ptr) { \
+               if(0 == (*res_ptr & *mask_ptr)) { \
+                       *res_ptr |= *mask_ptr; \
+                       res_idx = (int)((unsigned long)res_ptr - (unsigned long)ioc->res_map); \
+                       ioc->res_hint = res_idx + (size >> 3); \
                        goto resource_found; \
                } \
        }
 
-#define CCIO_FIND_FREE_MAPPING(ioa, idx, mask, size)  { \
-       u##size *res_ptr = (u##size *)&((ioa)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
-       u##size *res_end = (u##size *)&(ioa)->res_map[ioa->res_size]; \
-       CCIO_SEARCH_LOOP(ioa, idx, mask, size); \
-       res_ptr = (u##size *)&(ioa)->res_map[0]; \
-       CCIO_SEARCH_LOOP(ioa, idx, mask, size); \
-}
+#define CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, size) \
+       u##size *res_ptr = (u##size *)&((ioc)->res_map[ioa->res_hint & ~((size >> 3) - 1)]); \
+       u##size *res_end = (u##size *)&(ioc)->res_map[ioa->res_size]; \
+       u##size *mask_ptr = (u##size *)&mask; \
+       CCIO_SEARCH_LOOP(ioc, res_idx, mask_ptr, size); \
+       res_ptr = (u##size *)&(ioc)->res_map[0]; \
+       CCIO_SEARCH_LOOP(ioa, res_idx, mask_ptr, size);
 
 /*
 ** Find available bit in this ioa's resource map.
@@ -290,123 +234,132 @@
 ** o use different search for "large" (eg > 4 pages) or "very large"
 **   (eg > 16 pages) mappings.
 */
+
+/**
+ * ccio_alloc_range - Allocate pages in the ioc's resource map.
+ * @ioc: The I/O Controller.
+ * @pages_needed: The requested number of pages to be mapped into the
+ * I/O Pdir...
+ *
+ * This function searches the resource map of the ioc to locate a range
+ * of available pages for the requested size.
+ */
 static int
-ccio_alloc_range(struct ccio_device *ioa, size_t size)
+ccio_alloc_range(struct ioc *ioc, unsigned long pages_needed)
 {
 	int res_idx;
-	unsigned long mask, flags;
-	unsigned int pages_needed = size >> PAGE_SHIFT;
-
+	unsigned long mask;
+#ifdef CONFIG_PROC_FS
+	unsigned long cr_start = mfctl(16);
+#endif
+	
 	ASSERT(pages_needed);
-	ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
-	ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT));
+	ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE);
+	ASSERT(pages_needed <= BITS_PER_LONG);
 
-	mask = (unsigned long) -1L;
- 	mask >>= BITS_PER_LONG - pages_needed;
-
-	DBG_RES(__FUNCTION__ " size: %d pages_needed %d pages_mask 0x%08lx\n", 
-		size, pages_needed, mask);
-
-	spin_lock_irqsave(&ioa->ccio_lock, flags);
+	mask = ~(~0UL >> pages_needed);
+     
+	DBG_RES("%s() size: %d pages_needed %d mask 0x%08lx\n", 
+		__FUNCTION__, size, pages_needed, mask);
 
 	/*
 	** "seek and ye shall find"...praying never hurts either...
-	** ggg sacrafices another 710 to the computer gods.
+	** ggg sacrifices another 710 to the computer gods.
 	*/
 
 	if(pages_needed <= 8) {
-		CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 8);
+		CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 8);
 	} else if(pages_needed <= 16) {
-		CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 16);
+		CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 16);
 	} else if(pages_needed <= 32) {
-		CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 32);
+		CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 32);
 #ifdef __LP64__
 	} else if(pages_needed <= 64) {
-		CCIO_FIND_FREE_MAPPING(ioa, res_idx, mask, 64)
+		CCIO_FIND_FREE_MAPPING(ioc, res_idx, mask, 64);
 #endif
 	} else {
-		panic(__FILE__ ":" __FUNCTION__ "() Too many pages to map.\n");
+		panic(__FILE__ ": %s() Too many pages to map. pages_needed: %ld\n", 
+		      __FUNCTION__, pages_needed);
 	}
 
-#ifdef DUMP_RESMAP
-	dump_resmap();
-#endif
-	panic(__FILE__ ":" __FUNCTION__ "() I/O MMU is out of mapping resources\n");
+	panic(__FILE__ ": %s() I/O MMU is out of mapping resources.\n", 
+	      __FUNCTION__);
 	
 resource_found:
 	
-	DBG_RES(__FUNCTION__ " res_idx %d mask 0x%08lx res_hint: %d\n",
-		res_idx, mask, ioa->res_hint);
+	DBG_RES("%s() res_idx %d mask 0x%08lx res_hint: %d\n",
+		__FUNCTION__, res_idx, mask, ioc->res_hint);
 
-	ccio_used_pages += pages_needed;
-	ccio_used_bytes += ((pages_needed >> 3) ? (pages_needed >> 3) : 1);
-
-	spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+#ifdef CONFIG_PROC_FS
+	{
+		unsigned long cr_end = mfctl(16);
+		unsigned long tmp = cr_end - cr_start;
+		/* check for roll over */
+		cr_start = (cr_end < cr_start) ?  -(tmp) : (tmp);
+	}
+	ioc->avg_search[ioc->avg_idx++] = cr_start;
+	ioc->avg_idx &= CCIO_SEARCH_SAMPLE - 1;
 
-#ifdef DUMP_RESMAP
-	dump_resmap();
+	ioc->used_pages += pages_needed;
 #endif
 
 	/* 
-	** return the bit address (convert from byte to bit).
+	** return the bit address.
 	*/
-	return (res_idx << 3);
+	return res_idx << 3;
 }
 
-
-#define CCIO_FREE_MAPPINGS(ioa, idx, mask, size) \
-        u##size *res_ptr = (u##size *)&((ioa)->res_map[idx + (((size >> 3) - 1) & ~((size >> 3) - 1))]); \
-        ASSERT((*res_ptr & mask) == mask); \
-        *res_ptr &= ~mask;
-
-/*
-** clear bits in the ioa's resource map
-*/
+#define CCIO_FREE_MAPPINGS(ioc, res_idx, mask, size) \
+        u##size *res_ptr = (u##size *)&((ioc)->res_map[res_idx]); \
+	u##size *mask_ptr = (u##size *)&mask; \
+        ASSERT((*res_ptr & *mask_ptr) == *mask_ptr); \
+        *res_ptr &= ~(*mask_ptr);
+
+/**
+ * ccio_free_range - Free pages from the ioc's resource map.
+ * @ioc: The I/O Controller.
+ * @iova: The I/O Virtual Address.
+ * @pages_mapped: The requested number of pages to be freed from the
+ * I/O Pdir.
+ *
+ * This function frees the resouces allocated for the iova.
+ */
 static void
-ccio_free_range(struct ccio_device *ioa, dma_addr_t iova, size_t size)
+ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped)
 {
-	unsigned long mask, flags;
+	unsigned long mask;
 	unsigned long iovp = CCIO_IOVP(iova);
-	unsigned int res_idx = PDIR_INDEX(iovp)>>3;
-	unsigned int pages_mapped = (size >> IOVP_SHIFT) + !!(size & ~IOVP_MASK);
+	unsigned int res_idx = PDIR_INDEX(iovp) >> 3;
 
-	ASSERT(pages_needed);
-	ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
-	ASSERT(pages_needed < (BITS_PER_LONG - IOVP_SHIFT));
+	ASSERT(pages_mapped);
+	ASSERT((pages_mapped * IOVP_SIZE) <= DMA_CHUNK_SIZE);
+	ASSERT(pages_mapped <= BITS_PER_LONG);
 
-	mask = (unsigned long) -1L;
- 	mask >>= BITS_PER_LONG - pages_mapped;
+	mask = ~(~0UL >> pages_mapped);
 
-	DBG_RES(__FUNCTION__ " res_idx: %d size: %d pages_mapped %d mask 0x%08lx\n", 
-		res_idx, size, pages_mapped, mask);
+	DBG_RES("%s():  res_idx: %d pages_mapped %d mask 0x%08lx\n", 
+		__FUNCTION__, res_idx, pages_mapped, mask);
 
-	spin_lock_irqsave(&ioa->ccio_lock, flags);
+#ifdef CONFIG_PROC_FS
+	ioc->used_pages -= pages_mapped;
+#endif
 
 	if(pages_mapped <= 8) {
-		CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 8);
+		CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 8);
 	} else if(pages_mapped <= 16) {
-		CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 16);
+		CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 16);
 	} else if(pages_mapped <= 32) {
-		CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 32);
+		CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 32);
 #ifdef __LP64__
 	} else if(pages_mapped <= 64) {
-		CCIO_FREE_MAPPINGS(ioa, res_idx, mask, 64);
+		CCIO_FREE_MAPPINGS(ioc, res_idx, mask, 64);
 #endif
 	} else {
-		panic(__FILE__ ":" __FUNCTION__ "() Too many pages to unmap.\n");
+		panic(__FILE__ ":%s() Too many pages to unmap.\n", 
+		      __FUNCTION__);
 	}
-	
-	ccio_used_pages -= (pages_mapped ? pages_mapped : 1);
-	ccio_used_bytes -= ((pages_mapped >> 3) ? (pages_mapped >> 3) : 1);
-
-	spin_unlock_irqrestore(&ioa->ccio_lock, flags);
-
-#ifdef DUMP_RESMAP
-	dump_resmap();
-#endif
 }
 
-
 /****************************************************************
 **
 **          CCIO dma_ops support routines
@@ -416,7 +369,6 @@
 typedef unsigned long space_t;
 #define KERNEL_SPACE 0
 
-
 /*
 ** DMA "Page Type" and Hints 
 ** o if SAFE_DMA isn't set, mapping is for FAST_DMA. SAFE_DMA should be
@@ -466,32 +418,35 @@
 	[PCI_DMA_NONE]           0,            /* not valid */
 };
 
-/*
-** Initialize an I/O Pdir entry
-**
-** Given a virtual address (vba, arg2) and space id, (sid, arg1),
-** load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir
-** entry consists of 8 bytes as shown below (MSB == bit 0):
-**
-**
-** WORD 0:
-** +------+----------------+-----------------------------------------------+
-** | Phys | Virtual Index  |               Phys                            |
-** | 0:3  |     0:11       |               4:19                            |
-** |4 bits|   12 bits      |              16 bits                          |
-** +------+----------------+-----------------------------------------------+
-** WORD 1:
-** +-----------------------+-----------------------------------------------+
-** |      Phys    |  Rsvd  | Prefetch |Update |Rsvd  |Lock  |Safe  |Valid  |
-** |     20:39    |        | Enable   |Enable |      |Enable|DMA   |       |
-** |    20 bits   | 5 bits | 1 bit    |1 bit  |2 bits|1 bit |1 bit |1 bit  |
-** +-----------------------+-----------------------------------------------+
-**
-** The virtual index field is filled with the results of the LCI
-** (Load Coherence Index) instruction.  The 8 bits used for the virtual
-** index are bits 12:19 of the value returned by LCI.
-*/
-
+/**
+ * ccio_io_pdir_entry - Initialize an I/O Pdir.
+ * @pdir_ptr: A pointer into I/O Pdir.
+ * @sid: The Space Identifier.
+ * @vba: The virtual address.
+ * @hints: The DMA Hint.
+ *
+ * Given a virtual address (vba, arg2) and space id, (sid, arg1),
+ * load the I/O PDIR entry pointed to by pdir_ptr (arg0). Each IO Pdir
+ * entry consists of 8 bytes as shown below (MSB == bit 0):
+ *
+ *
+ * WORD 0:
+ * +------+----------------+-----------------------------------------------+
+ * | Phys | Virtual Index  |               Phys                            |
+ * | 0:3  |     0:11       |               4:19                            |
+ * |4 bits|   12 bits      |              16 bits                          |
+ * +------+----------------+-----------------------------------------------+
+ * WORD 1:
+ * +-----------------------+-----------------------------------------------+
+ * |      Phys    |  Rsvd  | Prefetch |Update |Rsvd  |Lock  |Safe  |Valid  |
+ * |     20:39    |        | Enable   |Enable |      |Enable|DMA   |       |
+ * |    20 bits   | 5 bits | 1 bit    |1 bit  |2 bits|1 bit |1 bit |1 bit  |
+ * +-----------------------+-----------------------------------------------+
+ *
+ * The virtual index field is filled with the results of the LCI
+ * (Load Coherence Index) instruction.  The 8 bits used for the virtual
+ * index are bits 12:19 of the value returned by LCI.
+ */ 
 void CCIO_INLINE
 ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, void * vba, unsigned long hints)
 {
@@ -499,8 +454,7 @@
 	register unsigned long ci; /* coherent index */
 
 	/* We currently only support kernel addresses */
-	ASSERT(sid == 0);
-	ASSERT(((unsigned long) vba & 0xf0000000UL) == 0xc0000000UL);
+	ASSERT(sid == KERNEL_SPACE);
 
 	mtsp(sid,1);
 
@@ -524,7 +478,7 @@
 	** and deposit them
 	*/
 	asm volatile ("extrd,u %1,15,4,%0" : "=r" (ci) : "r" (pa));
-	asm volatile ("extrd,u %1,31,16,%0" : "+r" (ci) : "r" (ci));
+	asm volatile ("extrd,u %1,31,16,%0" : "+r" (pa) : "r" (pa));
 	asm volatile ("depd  %1,35,4,%0" : "+r" (pa) : "r" (ci));
 #else
 	pa = 0;
@@ -556,31 +510,39 @@
 	asm volatile("sync");
 }
 
-
-/*
-** Remove stale entries from the I/O TLB.
-** Need to do this whenever an entry in the PDIR is marked invalid.
-*/
+/**
+ * ccio_clear_io_tlb - Remove stale entries from the I/O TLB.
+ * @ioc: The I/O Controller.
+ * @iovp: The I/O Virtual Page.
+ * @byte_cnt: The requested number of bytes to be freed from the I/O Pdir.
+ *
+ * Purge invalid I/O PDIR entries from the I/O TLB.
+ *
+ * FIXME: Can we change the byte_cnt to pages_mapped?
+ */
 static CCIO_INLINE void
-ccio_clear_io_tlb( struct ccio_device *d, dma_addr_t iovp, size_t byte_cnt)
+ccio_clear_io_tlb(struct ioc *ioc, dma_addr_t iovp, size_t byte_cnt)
 {
-	u32 chain_size = 1 << d->chainid_shift;
+	u32 chain_size = 1 << ioc->chainid_shift;
 
-	iovp &= ~(IOVP_SIZE-1);	/* clear offset bits, just want pagenum */
+	iovp &= IOVP_MASK;	/* clear offset bits, just want pagenum */
 	byte_cnt += chain_size;
 
-        while (byte_cnt > chain_size) {
-		WRITE_U32(CMD_TLB_PURGE | iovp, &d->ccio_hpa->io_command);
-                iovp += chain_size;
+	while(byte_cnt > chain_size) {
+		WRITE_U32(CMD_TLB_PURGE | iovp, &ioc->ioc_hpa->io_command);
+		iovp += chain_size;
 		byte_cnt -= chain_size;
-        }
+      }
 }
 
-
-/***********************************************************
+/**
+ * ccio_mark_invalid - Mark the I/O Pdir entries invalid.
+ * @ioc: The I/O Controller.
+ * @iova: The I/O Virtual Address.
+ * @byte_cnt: The requested number of bytes to be freed from the I/O Pdir.
  *
- * Mark the I/O Pdir entries invalid and blow away the
- * corresponding I/O TLB entries.
+ * Mark the I/O Pdir entries invalid and blow away the corresponding I/O
+ * TLB entries.
  *
  * FIXME: at some threshhold it might be "cheaper" to just blow
  *        away the entire I/O TLB instead of individual entries.
@@ -588,25 +550,25 @@
  * FIXME: Uturn has 256 TLB entries. We don't need to purge every
  *        PDIR entry - just once for each possible TLB entry.
  *        (We do need to maker I/O PDIR entries invalid regardless).
- ***********************************************************/
+ *
+ * FIXME: Can we change byte_cnt to pages_mapped?
+ */ 
 static CCIO_INLINE void
-ccio_mark_invalid(struct ccio_device *d, dma_addr_t iova, size_t byte_cnt)
+ccio_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 {
-	u32 iovp = (u32) CCIO_IOVP(iova);
+	u32 iovp = (u32)CCIO_IOVP(iova);
 	size_t saved_byte_cnt;
 
 	/* round up to nearest page size */
-	saved_byte_cnt = byte_cnt = (byte_cnt + IOVP_SIZE - 1) & IOVP_MASK;
+	saved_byte_cnt = byte_cnt = ROUNDUP(byte_cnt, IOVP_SIZE);
 
-	while (byte_cnt > 0) {
+	while(byte_cnt > 0) {
 		/* invalidate one page at a time */
 		unsigned int idx = PDIR_INDEX(iovp);
-		char *pdir_ptr = (char *) &(d->pdir_base[idx]);
-
-		ASSERT( idx < (d->pdir_size/sizeof(u64)));
-
-		pdir_ptr[7] = 0;	/* clear only VALID bit */
+		char *pdir_ptr = (char *) &(ioc->pdir_base[idx]);
 
+		ASSERT(idx < (ioc->pdir_size / sizeof(u64)));
+		pdir_ptr[7] = 0;	/* clear only VALID bit */ 
 		/*
 		** FIXME: PCX_W platforms don't need FDC/SYNC. (eg C360)
 		**   PCX-U/U+ do. (eg C200/C240)
@@ -622,232 +584,485 @@
 	}
 
 	asm volatile("sync");
-	ccio_clear_io_tlb(d, CCIO_IOVP(iova), saved_byte_cnt);
+	ccio_clear_io_tlb(ioc, CCIO_IOVP(iova), saved_byte_cnt);
 }
 
-
 /****************************************************************
 **
 **          CCIO dma_ops
 **
 *****************************************************************/
 
-void __init ccio_init(void)
-{
-	register_driver(ccio_drivers_for);
-}
-
-
-static int ccio_dma_supported( struct pci_dev *dev, u64 mask)
+/**
+ * ccio_dma_supported - Verify the IOMMU supports the DMA address range.
+ * @dev: The PCI device.
+ * @mask: A bit mask describing the DMA address range of the device.
+ *
+ * This function implements the pci_dma_supported function.
+ */
+static int 
+ccio_dma_supported(struct pci_dev *dev, u64 mask)
 {
-	if (dev == NULL) {
-		printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+	if(dev == NULL) {
+		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
 		BUG();
-		return(0);
+		return 0;
 	}
 
 	dev->dma_mask = mask;   /* save it */
 
 	/* only support 32-bit devices (ie PCI/GSC) */
-	return((int) (mask >= 0xffffffffUL));
+	return (int)(mask == 0xffffffffUL);
 }
 
-/*
-** Dump a hex representation of the resource map.
-*/
-
-#ifdef DUMP_RESMAP
-static 
-void dump_resmap()
-{
-	struct ccio_device *ioa = ccio_list;
-	unsigned long *res_ptr = (unsigned long *)ioa->res_map;
-	unsigned long i = 0;
-
-	printk("res_map: ");
-	for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
-		printk("%08lx ", *res_ptr);
-
-	printk("\n");
-}
-#endif
-
-/*
-** map_single returns a fully formed IOVA
-*/
-static dma_addr_t ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
+/**
+ * ccio_map_single - Map an address range into the IOMMU.
+ * @dev: The PCI device.
+ * @addr: The start address of the DMA region.
+ * @size: The length of the DMA region.
+ * @direction: The direction of the DMA transaction (to/from device).
+ *
+ * This function implements the pci_map_single function.
+ */
+static dma_addr_t 
+ccio_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
 {
-	struct ccio_device *ioa = ccio_list;  /* FIXME : see Multi-IOC below */
+	int idx;
+	struct ioc *ioc;
+	unsigned long flags;
 	dma_addr_t iovp;
 	dma_addr_t offset;
 	u64 *pdir_start;
 	unsigned long hint = hint_lookup[direction];
-	int idx;
+
+	ASSERT(dev);
+	ASSERT(dev->sysdata);
+	ASSERT(HBA_DATA(dev->sysdata)->iommu);
+	ioc = GET_IOC(dev);
 
 	ASSERT(size > 0);
 
 	/* save offset bits */
-	offset = ((dma_addr_t) addr) & ~IOVP_MASK;
+	offset = ((unsigned long) addr) & ~IOVP_MASK;
 
 	/* round up to nearest IOVP_SIZE */
-	size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK;
+	size = ROUNDUP(size + offset, IOVP_SIZE);
+	spin_lock_irqsave(&ioc->res_lock, flags);
+
+#ifdef CONFIG_PROC_FS
+	ioc->msingle_calls++;
+	ioc->msingle_pages += size >> IOVP_SHIFT;
+#endif
 
-	idx = ccio_alloc_range(ioa, size);
-	iovp = (dma_addr_t) MKIOVP(idx);
+	idx = ccio_alloc_range(ioc, (size >> IOVP_SHIFT));
+	iovp = (dma_addr_t)MKIOVP(idx);
 
-	DBG_RUN(__FUNCTION__ " 0x%p -> 0x%lx", addr, (long) iovp | offset);
+	pdir_start = &(ioc->pdir_base[idx]);
 
-	pdir_start = &(ioa->pdir_base[idx]);
+	DBG_RUN("%s() 0x%p -> 0x%lx size: %0x%x\n",
+		__FUNCTION__, addr, (long)iovp | offset, size);
 
 	/* If not cacheline aligned, force SAFE_DMA on the whole mess */
-	if ((size % L1_CACHE_BYTES) || ((unsigned long) addr % L1_CACHE_BYTES))
+	if((size % L1_CACHE_BYTES) || ((unsigned long)addr % L1_CACHE_BYTES))
 		hint |= HINT_SAFE_DMA;
 
-	/* round up to nearest IOVP_SIZE */
-	size = (size + IOVP_SIZE - 1) & IOVP_MASK;
-
-	while (size > 0) {
-
+	while(size > 0) {
 		ccio_io_pdir_entry(pdir_start, KERNEL_SPACE, addr, hint);
 
 		DBG_RUN(" pdir %p %08x%08x\n",
 			pdir_start,
 			(u32) (((u32 *) pdir_start)[0]),
-			(u32) (((u32 *) pdir_start)[1])
-			);
+			(u32) (((u32 *) pdir_start)[1]));
+		++pdir_start;
 		addr += IOVP_SIZE;
 		size -= IOVP_SIZE;
-		pdir_start++;
 	}
+
+	spin_unlock_irqrestore(&ioc->res_lock, flags);
+
 	/* form complete address */
 	return CCIO_IOVA(iovp, offset);
 }
 
-
-static void ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
-{
-#ifdef FIXME
-/* Multi-IOC (ie N-class) :  need to lookup IOC from dev
-** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
-** o walking up pcidev->parent dead ends at elroy too
-** o leaves hashing dev->bus->number into some lookup.
-**   (may only work for N-class)
-*/
-	struct ccio_device *ioa = dev->sysdata
-#else
-	struct ccio_device *ioa = ccio_list;
-#endif
-	dma_addr_t offset;
+/**
+ * ccio_unmap_single - Unmap an address range from the IOMMU.
+ * @dev: The PCI device.
+ * @addr: The start address of the DMA region.
+ * @size: The length of the DMA region.
+ * @direction: The direction of the DMA transaction (to/from device).
+ *
+ * This function implements the pci_unmap_single function.
+ */
+static void 
+ccio_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, 
+		  int direction)
+{
+	struct ioc *ioc;
+	unsigned long flags; 
+	dma_addr_t offset = iova & ~IOVP_MASK;
 	
-	offset = iova & ~IOVP_MASK;
-
-	/* round up to nearest IOVP_SIZE */
-	size = (size + offset + IOVP_SIZE - 1) & IOVP_MASK;
+	ASSERT(dev);
+	ASSERT(dev->sysdata);
+	ASSERT(HBA_DATA(dev->sysdata)->iommu);
+	ioc = GET_IOC(dev);
+
+	DBG_RUN("%s() iovp 0x%lx/%x\n",
+		__FUNCTION__, (long)iova, size);
+
+	iova ^= offset;        /* clear offset bits */
+	size += offset;
+	size = ROUNDUP(size, IOVP_SIZE);
 
-	/* Mask off offset */
-	iova &= IOVP_MASK;
+	spin_lock_irqsave(&ioc->res_lock, flags);
 
-	DBG_RUN(__FUNCTION__ " iovp 0x%lx\n", (long) iova);
-
-#ifdef DELAYED_RESOURCE_CNT
-	if (ioa->saved_cnt < DELAYED_RESOURCE_CNT) {
-		ioa->saved_iova[ioa->saved_cnt] = iova;
-		ioa->saved_size[ioa->saved_cnt] = size;
-		ccio_saved_cnt++;
-	} else {
-		do {
+#ifdef CONFIG_PROC_FS
+	ioc->usingle_calls++;
+	ioc->usingle_pages += size >> IOVP_SHIFT;
 #endif
-			ccio_mark_invalid(ioa, iova, size);
-			ccio_free_range(ioa, iova, size);
 
-#ifdef DELAYED_RESOURCE_CNT
-			d->saved_cnt--;
-			iova = ioa->saved_iova[ioa->saved_cnt];
-			size = ioa->saved_size[ioa->saved_cnt];
-		} while (ioa->saved_cnt)
-	}
-#endif
+	ccio_mark_invalid(ioc, iova, size);
+	ccio_free_range(ioc, iova, (size >> IOVP_SHIFT));
+	spin_unlock_irqrestore(&ioc->res_lock, flags);
 }
 
-
-static void * ccio_alloc_consistent (struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+/**
+ * ccio_alloc_consistent - Allocate a consistent DMA mapping.
+ * @dev: The PCI device.
+ * @size: The length of the DMA region.
+ * @dma_handle: The DMA address handed back to the device (not the cpu).
+ *
+ * This function implements the pci_alloc_consistent function.
+ */
+static void * 
+ccio_alloc_consistent(struct pci_dev *dev, size_t size, dma_addr_t *dma_handle)
 {
-	void *ret;
-	unsigned long flags;
-	struct ccio_device *ioa = ccio_list;
-
-	DBG_RUN(__FUNCTION__ " size 0x%x\n",  size);
-
+      void *ret;
 #if 0
 /* GRANT Need to establish hierarchy for non-PCI devs as well
 ** and then provide matching gsc_map_xxx() functions for them as well.
 */
-	if (!hwdev) {
+	if(!hwdev) {
 		/* only support PCI */
 		*dma_handle = 0;
 		return 0;
 	}
 #endif
-	spin_lock_irqsave(&ioa->ccio_lock, flags);
-	ccio_alloc_size += get_order(size);
-	spin_unlock_irqrestore(&ioa->ccio_lock, flags);
-
         ret = (void *) __get_free_pages(GFP_ATOMIC, get_order(size));
 
 	if (ret) {
 		memset(ret, 0, size);
-		*dma_handle = ccio_map_single(hwdev, ret, size, PCI_DMA_BIDIRECTIONAL);
+		*dma_handle = ccio_map_single(dev, ret, size, PCI_DMA_BIDIRECTIONAL);
 	}
-	DBG_RUN(__FUNCTION__ " ret %p\n",  ret);
 
 	return ret;
 }
 
-
-static void ccio_free_consistent (struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+/**
+ * ccio_free_consistent - Free a consistent DMA mapping.
+ * @dev: The PCI device.
+ * @size: The length of the DMA region.
+ * @cpu_addr: The cpu address returned from the ccio_alloc_consistent.
+ * @dma_handle: The device address returned from the ccio_alloc_consistent.
+ *
+ * This function implements the pci_free_consistent function.
+ */
+static void 
+ccio_free_consistent(struct pci_dev *dev, size_t size, void *cpu_addr, 
+		     dma_addr_t dma_handle)
 {
-	unsigned long flags;
-	struct ccio_device *ioa = ccio_list;
+	ccio_unmap_single(dev, dma_handle, size, 0);
+	free_pages((unsigned long)cpu_addr, get_order(size));
+}
 
-	spin_lock_irqsave(&ioa->ccio_lock, flags);
-	ccio_free_size += get_order(size);
-	spin_unlock_irqrestore(&ioa->ccio_lock, flags);
+/*
+** Since 0 is a valid pdir_base index value, can't use that
+** to determine if a value is valid or not. Use a flag to indicate
+** the SG list entry contains a valid pdir index.
+*/
+#define PIDE_FLAG 0x80000000UL
 
-	ccio_unmap_single(hwdev, dma_handle, size, 0);
-	free_pages((unsigned long) vaddr, get_order(size));
+/**
+ * ccio_fill_pdir - Insert coalesced scatter/gather chunks into the I/O Pdir.
+ * @ioc: The I/O Controller.
+ * @startsg: The scatter/gather list of coalesced chunks.
+ * @nents: The number of entries in the scatter/gather list.
+ * @hint: The DMA Hint.
+ *
+ * This function inserts the coalesced scatter/gather list chunks into the
+ * I/O Controller's I/O Pdir.
+ */ 
+static CCIO_INLINE int
+ccio_fill_pdir(struct ioc *ioc, struct scatterlist *startsg, int nents, 
+	       unsigned long hint)
+{
+	struct scatterlist *dma_sg = startsg;	/* pointer to current DMA */
+	int n_mappings = 0;
+	u64 *pdirp = 0;
+	unsigned long dma_offset = 0;
+
+	dma_sg--;
+	while (nents-- > 0) {
+		int cnt = sg_dma_len(startsg);
+		sg_dma_len(startsg) = 0;
+
+		DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n", nents,
+			   (unsigned long)sg_dma_address(startsg), cnt,
+			   startsg->address, startsg->length
+		);
+
+		/*
+		** Look for the start of a new DMA stream
+		*/
+		if(sg_dma_address(startsg) & PIDE_FLAG) {
+			u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG;
+			dma_offset = (unsigned long) pide & ~IOVP_MASK;
+			sg_dma_address(startsg) = 0;
+			dma_sg++;
+			sg_dma_address(dma_sg) = pide;
+			pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]);
+			n_mappings++;
+		}
+
+		/*
+		** Look for a VCONTIG chunk
+		*/
+		if (cnt) {
+			unsigned long vaddr = (unsigned long)startsg->address;
+			ASSERT(pdirp);
+
+			/* Since multiple Vcontig blocks could make up
+			** one DMA stream, *add* cnt to dma_len.
+			*/
+			sg_dma_len(dma_sg) += cnt;
+			cnt += dma_offset;
+			dma_offset=0;	/* only want offset on first chunk */
+			cnt = ROUNDUP(cnt, IOVP_SIZE);
+#ifdef CONFIG_PROC_FS
+			ioc->msg_pages += cnt >> IOVP_SHIFT;
+#endif
+			do {
+				ccio_io_pdir_entry(pdirp, KERNEL_SPACE, 
+						   (void *)vaddr, hint);
+				vaddr += IOVP_SIZE;
+				cnt -= IOVP_SIZE;
+				pdirp++;
+			} while (cnt > 0);
+		}
+		startsg++;
+	}
+	return(n_mappings);
 }
 
+/*
+** First pass is to walk the SG list and determine where the breaks are
+** in the DMA stream. Allocates PDIR entries but does not fill them.
+** Returns the number of DMA chunks.
+**
+** Doing the fill seperate from the coalescing/allocation keeps the
+** code simpler. Future enhancement could make one pass through
+** the sglist do both.
+*/
 
-static int ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+static CCIO_INLINE int
+ccio_coalesce_chunks(struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
-	int tmp = nents;
+	struct scatterlist *vcontig_sg;    /* VCONTIG chunk head */
+	unsigned long vcontig_len;         /* len of VCONTIG chunk */
+	unsigned long vcontig_end;
+	struct scatterlist *dma_sg;        /* next DMA stream head */
+	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
+	int n_mappings = 0;
+
+	while (nents > 0) {
+
+		/*
+		** Prepare for first/next DMA stream
+		*/
+		dma_sg = vcontig_sg = startsg;
+		dma_len = vcontig_len = vcontig_end = startsg->length;
+		vcontig_end += (unsigned long) startsg->address;
+		dma_offset = (unsigned long) startsg->address & ~IOVP_MASK;
+
+		/* PARANOID: clear entries */
+		sg_dma_address(startsg) = 0;
+		sg_dma_len(startsg) = 0;
+
+		/*
+		** This loop terminates one iteration "early" since
+		** it's always looking one "ahead".
+		*/
+		while(--nents > 0) {
+			unsigned long startsg_end;
 
-	DBG_RUN(KERN_WARNING __FUNCTION__ " START\n");
+			startsg++;
+			startsg_end = (unsigned long)startsg->address + 
+				startsg->length;
+
+			/* PARANOID: clear entries */
+			sg_dma_address(startsg) = 0;
+			sg_dma_len(startsg) = 0;
+
+			/*
+			** First make sure current dma stream won't
+			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** next entry.
+			*/   
+			if(ROUNDUP(dma_len + dma_offset + startsg->length,
+				   IOVP_SIZE) > DMA_CHUNK_SIZE)
+				break;
+
+			/*
+			** Append the next transaction?
+			*/
+			if(vcontig_end == (unsigned long) startsg->address) {
+				vcontig_len += startsg->length;
+				vcontig_end += startsg->length;
+				dma_len     += startsg->length;
+				continue;
+			}
+
+			/*
+			** Not virtually contigous.
+			** Terminate prev chunk.
+			** Start a new chunk.
+			**
+			** Once we start a new VCONTIG chunk, dma_offset
+			** can't change. And we need the offset from the first
+			** chunk - not the last one. Ergo Successive chunks
+			** must start on page boundaries and dove tail
+			** with it's predecessor.
+			*/
+			sg_dma_len(vcontig_sg) = vcontig_len;
+
+			vcontig_sg = startsg;
+			vcontig_len = startsg->length;
+			break;
+		}
 
-        /* KISS: map each buffer seperately. */
-	while (nents) {
-		sg_dma_address(sglist) = ccio_map_single(dev, sglist->address, sglist->length, direction);
-		sg_dma_len(sglist) = sglist->length;
-		nents--;
-		sglist++;
+		/*
+		** End of DMA Stream
+		** Terminate last VCONTIG block.
+		** Allocate space for DMA stream.
+		*/
+		sg_dma_len(vcontig_sg) = vcontig_len;
+		dma_len = ROUNDUP(dma_len + dma_offset, IOVP_SIZE);
+		sg_dma_address(dma_sg) =
+			PIDE_FLAG 
+			| (ccio_alloc_range(ioc, (dma_len >> IOVP_SHIFT)) << IOVP_SHIFT)
+			| dma_offset;
+		n_mappings++;
 	}
 
-	DBG_RUN(KERN_WARNING __FUNCTION__ " DONE\n");
-	return tmp;
+	return n_mappings;
 }
 
-
-static void ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
+/**
+ * ccio_map_sg - Map the scatter/gather list into the IOMMU.
+ * @dev: The PCI device.
+ * @sglist: The scatter/gather list to be mapped in the IOMMU.
+ * @nents: The number of entries in the scatter/gather list.
+ * @direction: The direction of the DMA transaction (to/from device).
+ *
+ * This function implements the pci_map_sg function.
+ */
+static int
+ccio_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, 
+	    int direction)
 {
-	DBG_RUN(KERN_WARNING __FUNCTION__ " : unmapping %d entries\n", nents);
-	while (nents) {
-		ccio_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
-		nents--;
-		sglist++;
+	struct ioc *ioc;
+	int coalesced, filled = 0;
+	unsigned long flags;
+	unsigned long hint = hint_lookup[direction];
+	
+	ASSERT(dev);
+	ASSERT(dev->sysdata);
+	ASSERT(HBA_DATA(dev->sysdata)->iommu);
+	ioc = GET_IOC(dev);
+	
+	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
+
+	/* Fast path single entry scatterlists. */
+	if(nents == 1) {
+		sg_dma_address(sglist)= ccio_map_single(dev, sglist->address,
+							sglist->length, 
+							direction);
+		sg_dma_len(sglist)= sglist->length;
+		return 1;
 	}
-	return;
+	
+	spin_lock_irqsave(&ioc->res_lock, flags);
+
+#ifdef CONFIG_PROC_FS
+	ioc->msg_calls++;
+#endif
+
+	/*
+	** First coalesce the chunks and allocate I/O pdir space
+	**
+	** If this is one DMA stream, we can properly map using the
+	** correct virtual address associated with each DMA page.
+	** w/o this association, we wouldn't have coherent DMA!
+	** Access to the virtual address is what forces a two pass algorithm.
+	*/
+	coalesced = ccio_coalesce_chunks(ioc, sglist, nents);
+
+	/*
+	** Program the I/O Pdir
+	**
+	** map the virtual addresses to the I/O Pdir
+	** o dma_address will contain the pdir index
+	** o dma_len will contain the number of bytes to map 
+	** o address contains the virtual address.
+	*/
+	filled = ccio_fill_pdir(ioc, sglist, nents, hint);
+
+	spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+	ASSERT(coalesced == filled);
+	DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled);
+
+	return filled;
 }
 
+/**
+ * ccio_unmap_sg - Unmap the scatter/gather list from the IOMMU.
+ * @dev: The PCI device.
+ * @sglist: The scatter/gather list to be unmapped from the IOMMU.
+ * @nents: The number of entries in the scatter/gather list.
+ * @direction: The direction of the DMA transaction (to/from device).
+ *
+ * This function implements the pci_unmap_sg function.
+ */
+static void 
+ccio_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, 
+	      int direction)
+{
+	struct ioc *ioc;
+
+	ASSERT(dev);
+	ASSERT(dev->sysdata);
+	ASSERT(HBA_DATA(dev->sysdata)->iommu);
+	ioc = GET_IOC(dev);
+
+	DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
+		__FUNCTION__, nents, sglist->address, sglist->length);
+
+#ifdef CONFIG_PROC_FS
+	ioc->usg_calls++;
+#endif
+
+	while(sg_dma_len(sglist) && nents--) {
+
+#ifdef CONFIG_PROC_FS
+		ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
+#endif
+		ccio_unmap_single(dev, sg_dma_address(sglist),
+				  sg_dma_len(sglist), direction);
+		++sglist;
+	}
+
+	DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents);
+}
 
 static struct pci_dma_ops ccio_ops = {
 	ccio_dma_supported,
@@ -861,6 +1076,201 @@
 	NULL,                   /* dma_sync_sg     : ditto */
 };
 
+#ifdef CONFIG_PROC_FS
+static int proc_append(char *src, int len, char **dst, off_t *offset, int *max)
+{
+	if (len < *offset) {
+		*offset -= len;
+		return 0;
+	}
+	if (*offset > 0) {
+		src += *offset;
+		len -= *offset;
+		*offset = 0;
+	}
+	if (len > *max) {
+		len = *max;
+	}
+	memcpy(*dst, src, len);
+	*dst += len;
+	*max -= len;
+	return (*max == 0);
+}
+
+static int ccio_proc_info(char *buf, char **start, off_t offset, int count,
+			  int *eof, void *data)
+{
+	int max = count;
+	char tmp[80]; /* width of an ANSI-standard terminal */
+	struct ioc *ioc = ioc_list;
+
+	while (ioc != NULL) {
+		unsigned int total_pages = ioc->res_size << 3;
+		unsigned long avg = 0, min, max;
+		int j, len;
+
+		len = sprintf(tmp, "%s\n", ioc->name);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "Cujo 2.0 bug    : %s\n",
+			      (ioc->cujo20_bug ? "yes" : "no"));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "IO PDIR size    : %d bytes (%d entries)\n",
+			      total_pages * 8, total_pages);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "IO PDIR entries : %ld free  %ld used (%d%%)\n",
+			      total_pages - ioc->used_pages, ioc->used_pages,
+			      (int)(ioc->used_pages * 100 / total_pages));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		len = sprintf(tmp, "Resource bitmap : %d bytes (%d pages)\n", 
+			ioc->res_size, total_pages);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+		min = max = ioc->avg_search[0];
+		for(j = 0; j < CCIO_SEARCH_SAMPLE; ++j) {
+			avg += ioc->avg_search[j];
+			if(ioc->avg_search[j] > max) 
+				max = ioc->avg_search[j];
+			if(ioc->avg_search[j] < min) 
+				min = ioc->avg_search[j];
+		}
+		avg /= CCIO_SEARCH_SAMPLE;
+		len = sprintf(tmp, "  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
+			      min, avg, max);
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+
+		len = sprintf(tmp, "pci_map_single(): %8ld calls  %8ld pages (avg %d/1000)\n",
+			      ioc->msingle_calls, ioc->msingle_pages,
+			      (int)((ioc->msingle_pages * 1000)/ioc->msingle_calls));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		
+
+		/* KLUGE - unmap_sg calls unmap_single for each mapped page */
+		min = ioc->usingle_calls - ioc->usg_calls;
+		max = ioc->usingle_pages - ioc->usg_pages;
+		len = sprintf(tmp, "pci_unmap_single: %8ld calls  %8ld pages (avg %d/1000)\n",
+			      min, max, (int)((max * 1000)/min));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+ 
+		len = sprintf(tmp, "pci_map_sg()    : %8ld calls  %8ld pages (avg %d/1000)\n",
+			      ioc->msg_calls, ioc->msg_pages,
+			      (int)((ioc->msg_pages * 1000)/ioc->msg_calls));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+		len = sprintf(tmp, "pci_unmap_sg()  : %8ld calls  %8ld pages (avg %d/1000)\n\n\n",
+			      ioc->usg_calls, ioc->usg_pages,
+			      (int)((ioc->usg_pages * 1000)/ioc->usg_calls));
+		if (proc_append(tmp, len, &buf, &offset, &count))
+			break;
+
+		ioc = ioc->next;
+	}
+
+	if (count == 0) {
+		*eof = 1;
+	}
+	return (max - count);
+}
+
+static int ccio_resource_map(char *buf, char **start, off_t offset, int len,
+			     int *eof, void *data)
+{
+	struct ioc *ioc = ioc_list;
+
+	buf[0] = '\0';
+	while (ioc != NULL) {
+		u32 *res_ptr = (u32 *)ioc->res_map;
+		int j;
+
+		for (j = 0; j < (ioc->res_size / sizeof(u32)); j++) {
+			if ((j & 7) == 0)
+				strcat(buf,"\n   ");
+			sprintf(buf, "%s %08x", buf, *res_ptr);
+			res_ptr++;
+		}
+		strcat(buf, "\n\n");
+		ioc = ioc->next;
+		break; /* XXX - remove me */
+	}
+
+	return strlen(buf);
+}
+#endif
+
+/**
+ * ccio_find_ioc - Find the ioc in the ioc_list
+ * @hw_path: The hardware path of the ioc.
+ *
+ * This function searches the ioc_list for an ioc that matches
+ * the provide hardware path.
+ */
+static struct ioc * ccio_find_ioc(int hw_path)
+{
+	int i;
+	struct ioc *ioc;
+
+	ioc = ioc_list;
+	for (i = 0; i < ioc_count; i++) {
+		if (ioc->hw_path == hw_path)
+			return ioc;
+
+		ioc = ioc->next;
+	}
+
+	return NULL;
+}
+
+/**
+ * ccio_get_iommu - Find the iommu which controls this device
+ * @dev: The parisc device.
+ *
+ * This function searches through the registerd IOMMU's and returns the
+ * appropriate IOMMU for the device based upon the devices hardware path.
+ */
+void * ccio_get_iommu(const struct parisc_device *dev)
+{
+	dev = find_pa_parent_type(dev, HPHW_IOA);
+	if (!dev)
+		return NULL;
+
+	return ccio_find_ioc(dev->hw_path);
+}
+
+#define CUJO_20_STEP       0x10000000	/* inc upper nibble */
+
+/* Cujo 2.0 has a bug which will silently corrupt data being transferred
+ * to/from certain pages.  To avoid this happening, we mark these pages
+ * as `used', and ensure that nothing will try to allocate from them.
+ */
+void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp)
+{
+	unsigned int idx;
+	struct ioc *ioc = ccio_get_iommu(dev);
+	u8 *res_ptr;
+
+#ifdef CONFIG_PROC_FS
+	ioc->cujo20_bug = 1;
+#endif
+	res_ptr = ioc->res_map;
+	idx = PDIR_INDEX(iovp) >> 3;
+
+	while (idx < ioc->res_size) {
+ 		res_ptr[idx] |= 0xff;
+		idx += PDIR_INDEX(CUJO_20_STEP) >> 3;
+	}
+}
+
 #if 0
 /* GRANT -  is this needed for U2 or not? */
 
@@ -875,38 +1285,37 @@
 ** I think only Java (K/D/R-class too?) systems don't do this.
 */
 static int
-ccio_get_iotlb_size(struct hp_device *d)
+ccio_get_iotlb_size(struct parisc_device *dev)
 {
-	if(d->spa_shift == 0) {
-		panic(__FUNCTION__ ": Can't determine I/O TLB size.\n");
+	if (dev->spa_shift == 0) {
+		panic("%s() : Can't determine I/O TLB size.\n", __FUNCTION__);
 	}
-	return(1 << d->spa_shift);
+	return (1 << dev->spa_shift);
 }
 #else
 
 /* Uturn supports 256 TLB entries */
 #define CCIO_CHAINID_SHIFT	8
 #define CCIO_CHAINID_MASK	0xff
-
 #endif /* 0 */
 
-
-/*
-** Figure out how big the I/O PDIR should be and alloc it.
-** Also sets variables which depend on pdir size.
-*/
+/**
+ * ccio_ioc_init - Initalize the I/O Controller
+ * @ioc: The I/O Controller.
+ *
+ * Initalize the I/O Controller which includes setting up the
+ * I/O Page Directory, the resource map, and initalizing the
+ * U2/Uturn chip into virtual mode.
+ */
 static void
-ccio_alloc_pdir(struct ccio_device *ioa)
+ccio_ioc_init(struct ioc *ioc)
 {
-	extern unsigned long mem_max;          /* arch.../setup.c */
-
-	u32 iova_space_size = 0;
-	void * pdir_base;
-	int pdir_size, iov_order;
+	int i, iov_order;
+	u32 iova_space_size;
+	unsigned long physmem;
 
 	/*
 	** Determine IOVA Space size from memory size.
-	** Using "mem_max" is a kluge.
 	**
 	** Ideally, PCI drivers would register the maximum number
 	** of DMA they can have outstanding for each device they
@@ -915,15 +1324,18 @@
 	** methods still require some "extra" to support PCI
 	** Hot-Plug/Removal of PCI cards. (aka PCI OLARD).
 	*/
+
 	/* limit IOVA space size to 1MB-1GB */
-	if (mem_max < (ccio_mem_ratio*1024*1024)) {
-		iova_space_size = 1024*1024;
+
+	physmem = num_physpages << PAGE_SHIFT;
+	if(physmem < (ccio_mem_ratio * 1024 * 1024)) {
+		iova_space_size = 1024 * 1024;
 #ifdef __LP64__
-	} else if (mem_max > (ccio_mem_ratio*512*1024*1024)) {
-		iova_space_size = 512*1024*1024;
+	} else if(physmem > (ccio_mem_ratio * 512 * 1024 * 1024)) {
+		iova_space_size = 512 * 1024 * 1024;
 #endif
 	} else {
-		iova_space_size = (u32) (mem_max/ccio_mem_ratio);
+		iova_space_size = (u32)(physmem / ccio_mem_ratio);
 	}
 
 	/*
@@ -933,277 +1345,271 @@
 
 	/* We could use larger page sizes in order to *decrease* the number
 	** of mappings needed.  (ie 8k pages means 1/2 the mappings).
-        **
+	**
 	** Note: Grant Grunder says "Using 8k I/O pages isn't trivial either
 	**   since the pages must also be physically contiguous - typically
 	**   this is the case under linux."
 	*/
 
-	iov_order = get_order(iova_space_size);
+	iov_order = get_order(iova_space_size) >> (IOVP_SHIFT - PAGE_SHIFT);
 	ASSERT(iov_order <= (30 - IOVP_SHIFT));   /* iova_space_size <= 1GB */
 	ASSERT(iov_order >= (20 - IOVP_SHIFT));   /* iova_space_size >= 1MB */
 	iova_space_size = 1 << (iov_order + IOVP_SHIFT);
 
-	ioa->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
+	ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64);
 
-	ASSERT(pdir_size < 4*1024*1024);   /* max pdir size < 4MB */
+	ASSERT(ioc->pdir_size < 4 * 1024 * 1024);   /* max pdir size < 4MB */
 
 	/* Verify it's a power of two */
-	ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
+	ASSERT((1 << get_order(ioc->pdir_size)) == (ioc->pdir_size >> PAGE_SHIFT));
 
-	DBG_INIT(__FUNCTION__ " hpa 0x%p mem %dMB IOV %dMB (%d bits)\n    PDIR size 0x%0x",
-		ioa->ccio_hpa, (int) (mem_max>>20), iova_space_size>>20,
-		iov_order + PAGE_SHIFT, pdir_size);
-
-	ioa->pdir_base =
-	pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
-	if (NULL == pdir_base)
-	{
-		panic(__FILE__ ":" __FUNCTION__ "() could not allocate I/O Page Table\n");
+	DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits) PDIR size 0x%0x",
+		__FUNCTION__, ioc->ioc_hpa, physmem>>20, iova_space_size>>20,
+		 iov_order + PAGE_SHIFT, ioc->pdir_size);
+
+	ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, 
+						 get_order(ioc->pdir_size));
+	if(NULL == ioc->pdir_base) {
+		panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
 	}
-	memset(pdir_base, 0, pdir_size);
+	memset(ioc->pdir_base, 0, ioc->pdir_size);
 
-	ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
+	ASSERT((((unsigned long)ioc->pdir_base) & PAGE_MASK) == (unsigned long)ioc->pdir_base);
+	DBG_INIT(" base %p", ioc->pdir_base);
 
-	DBG_INIT(" base %p", pdir_base);
+	/* resource map size dictated by pdir_size */
+ 	ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3;
+	DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size);
+	
+	ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, 
+					      get_order(ioc->res_size));
+	if(NULL == ioc->res_map) {
+		panic(__FILE__ ":%s() could not allocate resource map\n", __FUNCTION__);
+	}
+	memset(ioc->res_map, 0, ioc->res_size);
+
+	/* Initialize the res_hint to 16 */
+	ioc->res_hint = 16;
+
+	/* Initialize the spinlock */
+	spin_lock_init(&ioc->res_lock);
 
 	/*
 	** Chainid is the upper most bits of an IOVP used to determine
 	** which TLB entry an IOVP will use.
 	*/
-	ioa->chainid_shift = get_order(iova_space_size)+PAGE_SHIFT-CCIO_CHAINID_SHIFT;
-
-	DBG_INIT(" chainid_shift 0x%x\n", ioa->chainid_shift);
-}
-
-
-static void
-ccio_hw_init(struct ccio_device *ioa)
-{
-	int i;
+	ioc->chainid_shift = get_order(iova_space_size) + PAGE_SHIFT - CCIO_CHAINID_SHIFT;
+	DBG_INIT(" chainid_shift 0x%x\n", ioc->chainid_shift);
 
 	/*
 	** Initialize IOA hardware
 	*/
-	WRITE_U32(CCIO_CHAINID_MASK << ioa->chainid_shift, &ioa->ccio_hpa->io_chain_id_mask);
-	WRITE_U32(virt_to_phys(ioa->pdir_base), &ioa->ccio_hpa->io_pdir_base);
+	WRITE_U32(CCIO_CHAINID_MASK << ioc->chainid_shift, 
+		  &ioc->ioc_hpa->io_chain_id_mask);
 
+	WRITE_U32(virt_to_phys(ioc->pdir_base), 
+		  &ioc->ioc_hpa->io_pdir_base);
 
 	/*
 	** Go to "Virtual Mode"
 	*/
-	WRITE_U32(IOA_NORMAL_MODE, &ioa->ccio_hpa->io_control);
+	WRITE_U32(IOA_NORMAL_MODE, &ioc->ioc_hpa->io_control);
 
 	/*
 	** Initialize all I/O TLB entries to 0 (Valid bit off).
 	*/
-	WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_m);
-	WRITE_U32(0, &ioa->ccio_hpa->io_tlb_entry_l);
+	WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_m);
+	WRITE_U32(0, &ioc->ioc_hpa->io_tlb_entry_l);
 
-	for (i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
-		WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioa->chainid_shift)),
-					&ioa->ccio_hpa->io_command);
+	for(i = 1 << CCIO_CHAINID_SHIFT; i ; i--) {
+		WRITE_U32((CMD_TLB_DIRECT_WRITE | (i << ioc->chainid_shift)),
+			  &ioc->ioc_hpa->io_command);
 	}
-
 }
 
-
 static void
-ccio_resmap_init(struct ccio_device *ioa)
+ccio_init_resource(struct resource *res, char *name, unsigned long ioaddr)
 {
-	u32 res_size;
-
-	/*
-	** Ok...we do more than just init resource map
-	*/
-	ioa->ccio_lock = SPIN_LOCK_UNLOCKED;
+	int result;
 
-	ioa->res_hint = 16;    /* next available IOVP - circular search */
-
-	/* resource map size dictated by pdir_size */
-	res_size = ioa->pdir_size/sizeof(u64); /* entries */
-	res_size >>= 3;	/* convert bit count to byte count */
-	DBG_INIT(__FUNCTION__ "() res_size 0x%x\n", res_size);
-
-	ioa->res_size = res_size;
-	ioa->res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
-	if (NULL == ioa->res_map)
-	{
-		panic(__FILE__ ":" __FUNCTION__ "() could not allocate resource map\n");
+	res->flags = IORESOURCE_MEM;
+	res->start = (unsigned long)(signed) __raw_readl(ioaddr) << 16;
+	res->end = (unsigned long)(signed) (__raw_readl(ioaddr + 4) << 16) - 1;
+	if (res->end + 1 == res->start)
+		return;
+	res->name = name;
+	result = request_resource(&iomem_resource, res);
+	if (result < 0) {
+		printk(KERN_ERR 
+		       "%s: failed to claim CCIO bus address space (%p,%p)\n", 
+		       __FILE__, res->start, res->end);
 	}
-	memset(ioa->res_map, 0, res_size);
 }
 
-/* CUJO20 KLUDGE start */
-static struct {
-		u16 hversion;
-		u8  spa;
-		u8  type;
-		u32     foo[3];	/* 16 bytes total */
-} cujo_iodc __attribute__ ((aligned (64)));
-static unsigned long cujo_result[32] __attribute__ ((aligned (16))) = {0,0,0,0};
+static void __init ccio_init_resources(struct ioc *ioc)
+{
+	struct resource *res = ioc->mmio_region;
+	char *name = kmalloc(14, GFP_KERNEL);
 
-/*
-** CUJO 2.0 incorrectly decodes a memory access for specific
-** pages (every page at specific iotlb locations dependent
-** upon where the cujo is flexed - diff on raven/firehawk.
-** resulting in an hpmc and/or silent data corruption.
-** Workaround is to prevent use of those I/O TLB entries
-** by marking the suspect bitmap range entries as busy.
-*/
-static void
-ccio_cujo20_hack(struct ccio_device *ioa)
+	sprintf(name, "GSC Bus [%d/]", ioc->hw_path);
+
+	ccio_init_resource(res, name, (unsigned long)&ioc->ioc_hpa->io_io_low);
+	ccio_init_resource(res + 1, name,
+			(unsigned long)&ioc->ioc_hpa->io_io_low_hv);
+}
+
+static void expand_ioc_area(struct ioc *ioc, unsigned long size,
+		unsigned long min, unsigned long max, unsigned long align)
 {
-	unsigned long status;
-	unsigned int idx;
-	u8 *res_ptr = ioa->res_map;
-	u32 iovp=0x0;
-	unsigned long mask;
+#ifdef NASTY_HACK_FOR_K_CLASS
+	__raw_writel(0xfffff600, (unsigned long)&(ioc->ioc_hpa->io_io_high));
+	ioc->mmio_region[0].end = 0xf5ffffff;
+#endif
+}
 
-	status = pdc_iodc_read( &cujo_result, (void *) CUJO_RAVEN_LOC, 0, &cujo_iodc, 16);
-	if (status == 0) {
-		if (cujo_iodc.hversion==CUJO_20_BADHVERS)
-			iovp = CUJO_20_BADPAGE1;
+static struct resource *ccio_get_resource(struct ioc* ioc,
+		const struct parisc_device *dev)
+{
+	if (!ioc) {
+		return &iomem_resource;
+	} else if ((ioc->mmio_region->start <= dev->hpa) &&
+			(dev->hpa < ioc->mmio_region->end)) {
+		return ioc->mmio_region;
+	} else if (((ioc->mmio_region + 1)->start <= dev->hpa) &&
+			(dev->hpa < (ioc->mmio_region + 1)->end)) {
+		return ioc->mmio_region + 1;
 	} else {
-		status = pdc_iodc_read( &cujo_result, (void *) CUJO_FIREHAWK_LOC, 0, &cujo_iodc, 16);
-		if (status == 0) {
-			if (cujo_iodc.hversion==CUJO_20_BADHVERS)
-				iovp = CUJO_20_BADPAGE2;
-		} else {
-			/* not a defective system */
-			return;
-		}
+		return NULL;
 	}
+}
 
-	printk(MODULE_NAME ": Cujo 2.0 bug needs a work around\n");
-	ccio_cujo_bug = 1;
+int ccio_allocate_resource(const struct parisc_device *dev,
+		struct resource *res, unsigned long size,
+		unsigned long min, unsigned long max, unsigned long align,
+		void (*alignf)(void *, struct resource *, unsigned long),
+		void *alignf_data)
+{
+	struct ioc *ioc = ccio_get_iommu(dev);
+	struct resource *parent = ccio_get_resource(ioc, dev);
+	if (!parent)
+		return -EBUSY;
 
-	/*
-	** mark bit entries that match "bad page"
-	*/
-	idx = PDIR_INDEX(iovp)>>3;
-	mask = 0xff;
-	
-	while(idx * sizeof(u8) < ioa->res_size) {
-		res_ptr[idx] |= mask;
-		idx += (PDIR_INDEX(CUJO_20_STEP)>>3);
-		ccio_used_pages += 8;
-		ccio_used_bytes += 1;
-	}
+	if (!allocate_resource(parent, res, size, min, max, align, alignf,
+			alignf_data))
+		return 0;
+
+	expand_ioc_area(ioc, size, min, max, align);
+	return allocate_resource(parent, res, size, min, max, align, alignf,
+			alignf_data);
 }
-/* CUJO20 KLUDGE end */
 
-#ifdef CONFIG_PROC_FS
-static int ccio_proc_info(char *buf, char **start, off_t offset, int len)
+int ccio_request_resource(const struct parisc_device *dev,
+		struct resource *res)
 {
-	unsigned long i = 0;
-	struct ccio_device *ioa = ccio_list;
-	unsigned long *res_ptr = (unsigned long *)ioa->res_map;
-	unsigned long total_pages = ioa->res_size << 3;            /* 8 bits per byte */
-
-	sprintf(buf, "%s\nCujo 2.0 bug    : %s\n",
-		parisc_getHWdescription(ioa->iodc->hw_type, ioa->iodc->hversion,
-					ioa->iodc->sversion),
-		(ccio_cujo_bug ? "yes" : "no"));
-
-	sprintf(buf, "%sIO pdir size    : %d bytes (%d entries)\n",
-		buf, ((ioa->res_size << 3) * sizeof(u64)), /* 8 bits per byte */
-		ioa->res_size << 3);                       /* 8 bits per byte */
+	struct ioc *ioc = ccio_get_iommu(dev);
+	struct resource *parent = ccio_get_resource(ioc, dev);
+
+	return request_resource(parent, res);
+}
+/**
+ * ccio_probe - Determine if ccio should claim this device.
+ * @dev: The device which has been found
+ *
+ * Determine if ccio should claim this chip (return 0) or not (return 1).
+ * If so, initialize the chip and tell other partners in crime they
+ * have work to do.
+ */
+static int ccio_probe(struct parisc_device *dev)
+{
+	int i;
+	struct ioc *ioc, **ioc_p = &ioc_list;
 	
-	sprintf(buf, "%sResource bitmap : %d bytes (%d pages)\n", 
-		buf, ioa->res_size, ioa->res_size << 3);   /* 8 bits per byte */
+	ioc = kmalloc(sizeof(struct ioc), GFP_KERNEL);
+	if (ioc == NULL) {
+		printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
+		return 1;
+	}
+	memset(ioc, 0, sizeof(struct ioc));
 
-	strcat(buf,  "     	  total:    free:    used:   % used:\n");
-	sprintf(buf, "%sblocks  %8d %8ld %8ld %8ld%%\n", buf, ioa->res_size,
-		ioa->res_size - ccio_used_bytes, ccio_used_bytes,
-		(ccio_used_bytes * 100) / ioa->res_size);
-
-	sprintf(buf, "%spages   %8ld %8ld %8ld %8ld%%\n", buf, total_pages,
-		total_pages - ccio_used_pages, ccio_used_pages,
-		(ccio_used_pages * 100 / total_pages));
+	ioc->name = dev->id.hversion == U2_IOA_RUNWAY ? "U2" : "UTurn";
 
-	sprintf(buf, "%sconsistent       %8ld %8ld\n", buf,
-		ccio_alloc_size, ccio_free_size);
- 
-	strcat(buf, "\nResource bitmap:\n");
+	printk(KERN_INFO "Found %s at 0x%lx\n", ioc->name, dev->hpa);
 
-	for(; i < (ioa->res_size / sizeof(unsigned long)); ++i, ++res_ptr)
-		len += sprintf(buf, "%s%08lx ", buf, *res_ptr);
+	for (i = 0; i < ioc_count; i++) {
+		ioc_p = &(*ioc_p)->next;
+	}
+	*ioc_p = ioc;
 
-	strcat(buf, "\n");
-	return strlen(buf);
+	ioc->hw_path = dev->hw_path;
+	ioc->ioc_hpa = (struct ioa_registers *)dev->hpa;
+	ccio_ioc_init(ioc);
+	ccio_init_resources(ioc);
+	hppa_dma_ops = &ccio_ops;
+
+	if (ioc_count == 0) {
+		/* XXX: Create separate entries for each ioc */
+		create_proc_read_entry(MODULE_NAME, S_IRWXU, proc_runway_root,
+				       ccio_proc_info, NULL);
+		create_proc_read_entry(MODULE_NAME"-bitmap", S_IRWXU,
+				       proc_runway_root, ccio_resource_map, NULL);
+	}
+
+	ioc_count++;
+	return 0;
 }
-#endif
 
-/*
-** Determine if ccio should claim this chip (return 0) or not (return 1).
-** If so, initialize the chip and tell other partners in crime they
-** have work to do.
-*/
-static int
-ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+struct pci_dev * ccio_get_fake(const struct parisc_device *dev)
 {
-	struct ccio_device *ioa;
+	struct ioc *ioc;
 
-	printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+	dev = find_pa_parent_type(dev, HPHW_IOA);
+	if(!dev)
+		return NULL;
 
-	if (ccio_list) {
-		printk(MODULE_NAME ": already initialized one device\n");
-		return(0);
-	}
+	ioc = ccio_find_ioc(dev->hw_path);
+	if(!ioc)
+		return NULL;
 
-	ioa = kmalloc(sizeof(struct ccio_device), GFP_KERNEL);
-	if (NULL == ioa)
-	{
-		printk(MODULE_NAME " - couldn't alloc ccio_device\n");
-		return(1);
-	}
-	memset(ioa, 0, sizeof(struct ccio_device));
+	if(ioc->fake_pci_dev)
+		return ioc->fake_pci_dev;
 
-	/*
-	** ccio list is used mainly as a kluge to support a single instance. 
-	** Eventually, with core dumps, it'll be useful for debugging.
-	*/
-	ccio_list = ioa;
-	ioa->iodc = d;
+	ioc->fake_pci_dev = kmalloc(sizeof(struct pci_dev), GFP_KERNEL);
+	if(ioc->fake_pci_dev == NULL) {
+		printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
+		return NULL;
+	}
+	memset(ioc->fake_pci_dev, 0, sizeof(struct pci_dev));
 
-#if 1
-/* KLUGE: determine IOA hpa based on GSC port value.
-** Needed until we have a PA bus walk. Can only discover IOA via
-** walking the architected PA MMIO space as described by the I/O ACD.
-** "Legacy" PA Firmware only tells us about unarchitected devices
-** that can't be detected by PA/EISA/PCI bus walks.
-*/
-	switch((long) d->hpa) {
-	case 0xf3fbf000L:       /* C110 IOA0 LBC (aka GSC port) */
-		/* ccio_hpa same as C200 IOA0 */
-	case 0xf203f000L:       /* C180/C200/240/C360 IOA0 LBC (aka GSC port) */
-		ioa->ccio_hpa = (struct ioa_registers *) 0xfff88000L;
-		break;
-	case 0xf103f000L:       /* C180/C200/240/C360 IOA1 LBC (aka GSC port) */
-		ioa->ccio_hpa = (struct ioa_registers *) 0xfff8A000L;
-		break;
-	default:
-		panic("ccio-dma.c doesn't know this GSC port Address!\n");
-		break;
-	};
-#else
-	ioa->ccio_hpa = d->hpa;
-#endif
+	ioc->fake_pci_dev->sysdata = kmalloc(sizeof(struct pci_hba_data), GFP_KERNEL);
+	if(ioc->fake_pci_dev->sysdata == NULL) {
+		printk(KERN_ERR MODULE_NAME ": memory allocation failure\n");
+		return NULL;
+	}
 
-	ccio_alloc_pdir(ioa);
-	ccio_hw_init(ioa);
-	ccio_resmap_init(ioa);
+	HBA_DATA(ioc->fake_pci_dev->sysdata)->iommu = ioc;
+	return ioc->fake_pci_dev;
+}
 
-	/* CUJO20 KLUDGE start */
-	ccio_cujo20_hack(ioa);
-	/* CUJO20 KLUDGE end */
+/* We *can't* support JAVA (T600). Venture there at your own risk. */
+static struct parisc_device_id ccio_tbl[] = {
+	{ HPHW_IOA, HVERSION_REV_ANY_ID, U2_IOA_RUNWAY, 0xb }, /* U2 */
+	{ HPHW_IOA, HVERSION_REV_ANY_ID, UTURN_IOA_RUNWAY, 0xb }, /* UTurn */
+	{ 0, }
+};
 
-	hppa_dma_ops = &ccio_ops;
+static struct parisc_driver ccio_driver = {
+	name:		"U2/Uturn",
+	id_table:	ccio_tbl,
+	probe:		ccio_probe,
+};
 
-	create_proc_info_entry(MODULE_NAME, 0, proc_runway_root, ccio_proc_info);
-	return(0);
+/**
+ * ccio_init - ccio initalization procedure.
+ *
+ * Register this driver.
+ */
+void __init ccio_init(void)
+{
+	register_parisc_driver(&ccio_driver);
 }
 
-
-
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/ccio-rm-dma.c linux/arch/parisc/kernel/ccio-rm-dma.c
--- linux.orig/arch/parisc/kernel/ccio-rm-dma.c	2001-10-12 22:35:53.000000000 +0000
+++ linux/arch/parisc/kernel/ccio-rm-dma.c	2002-08-12 22:14:09.000000000 +0000
@@ -56,26 +56,6 @@
 #define UTURN_IOA_RUNWAY 0x581
 #define UTURN_BC_GSC     0x502
 
-static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
-
-static struct pa_iodc_driver ccio_drivers_for[] = {
-
-   {HPHW_BCPORT, U2_BC_GSC, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
-
-   {HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
-
-   {0,0,0,0,0,0,
-   0,
-   (char *) NULL, (char *) NULL, (void *) NULL }
-};
-
-
 #define IS_U2(id) ( \
     (((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
     (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC))  \
@@ -86,17 +66,10 @@
     (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC))  \
 )
 
-
-void __init ccio_init(void)
-{
-	register_driver(ccio_drivers_for);
-}
-
-
 static int ccio_dma_supported( struct pci_dev *dev, u64 mask)
 {
 	if (dev == NULL) {
-		printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
 		BUG();
 		return(0);
 	}
@@ -182,8 +155,6 @@
 	ccio_unmap_sg,
 	NULL,                   /* dma_sync_single : NOP for U2 */
 	NULL,                   /* dma_sync_sg     : ditto */
-
-
 };
 
 
@@ -193,9 +164,11 @@
 ** have work to do.
 */
 static int
-ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+ccio_probe(struct parisc_device *dev)
 {
-	printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+	printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME,
+			dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn",
+			dev->hpa);
 
 /*
 ** FIXME - should check U2 registers to verify it's really running
@@ -210,3 +183,20 @@
 	hppa_dma_ops = &ccio_ops;
 	return 0;
 }
+
+static struct parisc_device_id ccio_tbl[] = {
+	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, U2_BC_GSC, 0xc },
+	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, UTURN_BC_GSC, 0xc },
+	{ 0, }
+};
+
+static struct parisc_driver ccio_driver = {
+        name:           "U2/Uturn",
+        id_table:       ccio_tbl,
+        probe:          ccio_probe,
+};
+
+void __init ccio_init(void)
+{
+	register_parisc_driver(&ccio_driver);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/drivers.c linux/arch/parisc/kernel/drivers.c
--- linux.orig/arch/parisc/kernel/drivers.c	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/kernel/drivers.c	2002-08-12 22:14:14.000000000 +0000
@@ -1,134 +1,591 @@
 /*
-
-drivers.c
-
-Copyright (c) 1999 The Puffin Group 
-
-This is a collection of routines intended to register all the devices
-in a system, and register device drivers.
-
-*/
+ * drivers.c
+ *
+ * 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.
+ *
+ * Copyright (c) 1999 The Puffin Group
+ * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
+ * Copyright (c) 2001 Helge Deller <deller@gmx.de>
+ * 
+ * The file handles registering devices and drivers, then matching them.
+ * It's the closest we get to a dating agency.
+ */
 
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pdc.h>
+#include <asm/gsc.h>
 
+/* See comments in include/asm-parisc/pci.h */
+struct pci_dma_ops *hppa_dma_ops;
 
-extern struct hp_hardware *parisc_get_reference(
-	unsigned short hw_type, unsigned long hversion, 
-	unsigned long sversion );
+static struct parisc_driver *pa_drivers;
+static struct parisc_device root;
 
+/* This lock protects the pa_drivers list _only_ since all parisc_devices
+ * are registered before smp_init() is called.  If you wish to add devices
+ * after that, this muct be serialised somehow.  I recommend a semaphore
+ * rather than a spinlock since driver ->probe functions are allowed to
+ * sleep (for example when allocating memory).
+ */
+static spinlock_t pa_lock = SPIN_LOCK_UNLOCKED;
 
-/* I'm assuming there'll never be 64 devices.  We should probably make 
-   this more flexible.  */
+#define for_each_padev(dev) \
+	for (dev = root.child; dev != NULL; dev = next_dev(dev))
 
-#define MAX_DEVICES 64
+#define check_dev(dev) \
+	(dev->id.hw_type != HPHW_FAULTY) ? dev : next_dev(dev)
 
-unsigned int num_devices = 0;
+/**
+ * next_dev - enumerates registered devices
+ * @dev: the previous device returned from next_dev
+ *
+ * next_dev does a depth-first search of the tree, returning parents
+ * before children.  Returns NULL when there are no more devices.
+ */
+struct parisc_device *next_dev(struct parisc_device *dev)
+{
+	if (dev->child) {
+		return check_dev(dev->child);
+	} else if (dev->sibling) {
+		return dev->sibling;
+	}
 
-struct hp_device devices[MAX_DEVICES];
+	/* Exhausted tree at this level, time to go up. */
+	do {
+		dev = dev->parent;
+		if (dev && dev->sibling)
+			return dev->sibling;
+	} while (dev != &root);
 
-static unsigned long pdc_result[32] __attribute__ ((aligned (16))) = {0,0,0,0};
-static  u8 iodc_data[32] __attribute__ ((aligned (64)));
+	return NULL;
+}
 
-/*
- *	XXX should we be using a locked array ?
+/**
+ * match_device - Report whether this driver can handle this device
+ * @driver: the PA-RISC driver to try
+ * @dev: the PA-RISC device to try
  */
- 
-int register_driver(struct pa_iodc_driver *driver)
+static int match_device(struct parisc_driver *driver, struct parisc_device *dev)
 {
-	unsigned int i;
-	struct hp_device * device;
+	const struct parisc_device_id *ids;
 
-	for (;driver->check;driver++)  {
+	for (ids = driver->id_table; ids->sversion; ids++) {
+		if ((ids->sversion != SVERSION_ANY_ID) &&
+		    (ids->sversion != dev->id.sversion))
+			continue;
+
+		if ((ids->hw_type != HWTYPE_ANY_ID) &&
+		    (ids->hw_type != dev->id.hw_type))
+			continue;
+
+		if ((ids->hversion != HVERSION_ANY_ID) &&
+		    (ids->hversion != dev->id.hversion))
+			continue;
 
-		for (i=0;i<num_devices;i++) {
-			device = &devices[i];
+		return 1;
+	}
+	return 0;
+}
 
-			if (device->managed) continue;
+static void claim_device(struct parisc_driver *driver, struct parisc_device *dev)
+{
+	dev->driver = driver;
+	request_mem_region(dev->hpa, 0x1000, driver->name);
+}
 
-			if ((driver->check & DRIVER_CHECK_HWTYPE) &&
-			    (driver->hw_type != device->hw_type))
-				continue;
-			if ((driver->check & DRIVER_CHECK_HVERSION) &&
-			    (driver->hversion != device->hversion))
-				continue;
-			if ((driver->check & DRIVER_CHECK_HVERSION_REV) &&
-			    (driver->hversion_rev != device->hversion_rev))
-				continue;
-			if ((driver->check & DRIVER_CHECK_SVERSION) &&
-			    (driver->sversion != device->sversion))
-				continue;
-			if ((driver->check & DRIVER_CHECK_SVERSION_REV) &&
-			    (driver->sversion_rev != device->sversion_rev))
-				continue;
-			if ((driver->check & DRIVER_CHECK_OPT) &&
-			    (driver->opt != device->opt))
-				continue;
-			if ( (*driver->callback)(device,driver) ==0) {
-				device->managed=1;
-			} else {
-				printk("Warning : device (%d, 0x%x, 0x%x, 0x%x, 0x%x) NOT claimed by %s %s\n",
-					device->hw_type,
-					device->hversion, device->hversion_rev,
-					device->sversion, device->sversion_rev,
-					driver->name, driver->version);
-			}
+/**
+ * register_parisc_driver - Register this driver if it can handle a device
+ * @driver: the PA-RISC driver to try
+ */
+int register_parisc_driver(struct parisc_driver *driver)
+{
+	struct parisc_device *device;
+
+	if (driver->next) {
+		printk(KERN_WARNING 
+		       "BUG: Skipping previously registered driver: %s\n",
+		       driver->name);
+		return 1;
+	}
+
+	for_each_padev(device) {
+		if (device->driver)
+			continue;
+		if (!match_device(driver, device))
+			continue;
+
+		if (driver->probe(device) < 0)
+			continue;
+		claim_device(driver, device);
+	}
+
+	/* Note that the list is in reverse order of registration.  This
+	 * may be significant if we ever actually support hotplug and have
+	 * multiple drivers capable of claiming the same chip.
+	 */
+
+	spin_lock(&pa_lock);
+	driver->next = pa_drivers;
+	pa_drivers = driver;
+	spin_unlock(&pa_lock);
+
+	return 0;
+}
+
+/**
+ * count_parisc_driver - count # of devices this driver would match
+ * @driver: the PA-RISC driver to try
+ *
+ * Use by IOMMU support to "guess" the right size IOPdir.
+ * Formula is something like memsize/(num_iommu * entry_size).
+ */
+int count_parisc_driver(struct parisc_driver *driver)
+{
+	struct parisc_device *device;
+	int cnt = 0;
+
+	for_each_padev(device) {
+		if (match_device(driver, device))
+			cnt++;
+	}
+
+	return cnt;
+}
+
+
+
+/**
+ * unregister_parisc_driver - Unregister this driver from the list of drivers
+ * @driver: the PA-RISC driver to unregister
+ */
+int unregister_parisc_driver(struct parisc_driver *driver)
+{
+	struct parisc_device *dev;
+
+	spin_lock(&pa_lock);
+
+	if (pa_drivers == driver) {
+		/* was head of list - update head */
+		pa_drivers = driver->next;
+	} else {
+		struct parisc_driver *prev = pa_drivers;
+
+		while (prev && driver != prev->next) {
+			prev = prev->next;
+		}
+
+		if (!prev) {
+			printk(KERN_WARNING "unregister_parisc_driver: %s wasn't registered\n", driver->name);
+		} else {
+			/* Drop driver from list */
+			prev->next = driver->next;
+			driver->next = NULL;
 		}
+
 	}
+
+	spin_unlock(&pa_lock);
+
+	for_each_padev(dev) {
+		if (dev->driver != driver)
+			continue;
+		dev->driver = NULL;
+		release_mem_region(dev->hpa, 0x1000);
+	}
+
 	return 0;
 }
 
+static struct parisc_device *find_device_by_addr(unsigned long hpa)
+{
+	struct parisc_device *dev;
+	for_each_padev(dev) {
+		if (dev->hpa == hpa)
+			return dev;
+	}
+	return NULL;
+}
 
-struct hp_device * register_module(void *hpa)
+/**
+ * find_pa_parent_type - Find a parent of a specific type
+ * @dev: The device to start searching from
+ * @type: The device type to search for.
+ *
+ * Walks up the device tree looking for a device of the specified type.
+ * If it finds it, it returns it.  If not, it returns NULL.
+ */
+const struct parisc_device *find_pa_parent_type(const struct parisc_device *dev, int type)
 {
+	while (dev != &root) {
+		if (dev->id.hw_type == type)
+			return dev;
+		dev = dev->parent;
+	}
 
-	struct hp_device * d;
+	return NULL;
+}
+
+static void
+get_node_path(struct parisc_device *dev, struct hardware_path *path)
+{
+	int i = 5;
+	memset(&path->bc, -1, 6);
+	while (dev != &root) {
+		path->bc[i--] = dev->hw_path;
+		dev = dev->parent;
+	}
+}
+
+static char *print_hwpath(struct hardware_path *path, char *output)
+{
+	int i;
+	for (i = 0; i < 6; i++) {
+		if (path->bc[i] == -1)
+			continue;
+		output += sprintf(output, "%u/", (unsigned char) path->bc[i]);
+	}
+	output += sprintf(output, "%u", (unsigned char) path->mod);
+	return output;
+}
+
+/**
+ * print_pa_hwpath - Returns hardware path for PA devices
+ * dev: The device to return the path for
+ * output: Pointer to a previously-allocated array to place the path in.
+ *
+ * This function fills in the output array with a human-readable path
+ * to a PA device.  This string is compatible with that used by PDC, and
+ * may be printed on the outside of the box.
+ */
+char *print_pa_hwpath(struct parisc_device *dev, char *output)
+{
+	struct hardware_path path;
+
+	get_node_path(dev->parent, &path);
+	path.mod = dev->hw_path;
+	return print_hwpath(&path, output);
+}
+
+
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+/**
+ * get_pci_node_path - Returns hardware path for PCI devices
+ * dev: The device to return the path for
+ * output: Pointer to a previously-allocated array to place the path in.
+ *
+ * This function fills in the hardware_path structure with the route to
+ * the specified PCI device.  This structure is suitable for passing to
+ * PDC calls.
+ */
+void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path)
+{
+	struct pci_bus *bus;
+	const struct parisc_device *padev;
+	int i = 5;
+
+	memset(&path->bc, -1, 6);
+	path->mod = PCI_FUNC(dev->devfn);
+	path->bc[i--] = PCI_SLOT(dev->devfn);
+	for (bus = dev->bus; bus->parent; bus = bus->parent) {
+		unsigned int devfn = bus->self->devfn;
+		path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn) << 5);
+	}
+
+	padev = HBA_DATA(bus->sysdata)->dev;
+	while (padev != &root) {
+		path->bc[i--] = padev->hw_path;
+		padev = padev->parent;
+	}
+}
+
+/**
+ * print_pci_hwpath - Returns hardware path for PCI devices
+ * dev: The device to return the path for
+ * output: Pointer to a previously-allocated array to place the path in.
+ *
+ * This function fills in the output array with a human-readable path
+ * to a PCI device.  This string is compatible with that used by PDC, and
+ * may be printed on the outside of the box.
+ */
+char *print_pci_hwpath(struct pci_dev *dev, char *output)
+{
+	struct hardware_path path;
+
+	get_pci_node_path(dev, &path);
+	return print_hwpath(&path, output);
+}
+#endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */
+
+
+struct parisc_device * create_tree_node(char id, struct parisc_device *parent,
+		struct parisc_device **insert)
+{
+	struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return NULL;
+	memset(dev, 0, sizeof(*dev));
+	dev->hw_path = id;
+	dev->id.hw_type = HPHW_FAULTY;
+	dev->parent = parent;
+	dev->sibling = *insert;
+	*insert = dev;
+	return dev;
+}
+
+/**
+ * alloc_tree_node - returns a device entry in the iotree
+ * @parent: the parent node in the tree
+ * @id: the element of the module path for this entry
+ *
+ * Checks all the children of @parent for a matching @id.  If none
+ * found, it allocates a new device and returns it.
+ */
+struct parisc_device *
+alloc_tree_node(struct parisc_device *parent, char id)
+{
+	struct parisc_device *prev;
+	if ((!parent->child) || (parent->child->hw_path > id)) {
+		return create_tree_node(id, parent, &parent->child);
+	}
+
+	prev = parent->child;
+	if (prev->hw_path == id)
+		return prev;
+
+	while (prev->sibling && prev->sibling->hw_path < id) {
+		prev = prev->sibling;
+	}
+
+	if ((prev->sibling) && (prev->sibling->hw_path == id))
+		return prev->sibling;
+
+	return create_tree_node(id, parent, &prev->sibling);
+}
+
+static struct parisc_device *find_parisc_device(struct hardware_path *modpath)
+{
+	int i;
+	struct parisc_device *parent = &root;
+	for (i = 0; i < 6; i++) {
+		if (modpath->bc[i] == -1)
+			continue;
+		parent = alloc_tree_node(parent, modpath->bc[i]);
+	}
+	return alloc_tree_node(parent, modpath->mod);
+}
+
+struct parisc_device *
+alloc_pa_dev(unsigned long hpa, struct hardware_path *mod_path)
+{
 	int status;
+	unsigned long bytecnt;
+	u8 iodc_data[32];
+	struct parisc_device *dev;
+	const char *name;
+
+	/* Check to make sure this device has not already been added - Ryan */
+	if (find_device_by_addr(hpa) != NULL)
+		return NULL;
+
+	status = pdc_iodc_read(&bytecnt, hpa, 0, &iodc_data, 32);
+	if (status != PDC_OK)
+		return NULL;
+
+	dev = find_parisc_device(mod_path);
+	if (dev->id.hw_type != HPHW_FAULTY) {
+		char p[64];
+		print_pa_hwpath(dev, p);
+		printk("Two devices have hardware path %s.  Please file a bug with HP.\n"
+			"In the meantime, you could try rearranging your cards.\n", p);
+		return NULL;
+	}
+
+	dev->id.hw_type = iodc_data[3] & 0x1f;
+	dev->id.hversion = (iodc_data[0] << 4) | ((iodc_data[1] & 0xf0) >> 4);
+	dev->id.hversion_rev = iodc_data[1] & 0x0f;
+	dev->id.sversion = ((iodc_data[4] & 0x0f) << 16) |
+			(iodc_data[5] << 8) | iodc_data[6];
+	dev->hpa = hpa;
+	name = parisc_hardware_description(&dev->id);
+	if (name) {
+		strncpy(dev->name, name, sizeof(dev->name)-1);
+	}
+
+	return dev;
+}
 
-	d = &devices[num_devices];
-	status = pdc_iodc_read(&pdc_result,hpa,0,&iodc_data,32 );
-	if (status !=PDC_RET_OK) {
-		/* There is no device here, so we'll skip it */
+/**
+ * register_parisc_device - Locate a driver to manage this device.
+ * @dev: The parisc device.
+ *
+ * Search the driver list for a driver that is willing to manage
+ * this device.
+ */
+int register_parisc_device(struct parisc_device *dev)
+{
+	struct parisc_driver *driver;
+
+	if (!dev)
 		return 0;
+
+	if (dev->driver)
+		return 1;
+	
+	spin_lock(&pa_lock);
+
+	/* Locate a driver which agrees to manage this device.  */
+	for (driver = pa_drivers; driver; driver = driver->next) {
+		if (!match_device(driver,dev))
+			continue;
+		if (driver->probe(dev) == 0)
+			break;
 	}
 
-	d->hw_type = iodc_data[3]&0x1f;
-	d->hversion = (iodc_data[0]<<4)|((iodc_data[1]&0xf0)>>4);
-	d->sversion = 
-		((iodc_data[4]&0x0f)<<16)|(iodc_data[5]<<8)|(iodc_data[6]);
-	d->hversion_rev = iodc_data[1]&0x0f;
-	d->sversion_rev = iodc_data[4]>>4;
-	d->opt = iodc_data[7];
-	d->hpa = hpa;
-	d->managed=0;
-	d->reference = parisc_get_reference(d->hw_type, d->hversion, 
-								d->sversion);
-		
-	num_devices++;	
+	if (driver != NULL) {
+		claim_device(driver, dev);
+	}
+	spin_unlock(&pa_lock);
+	return driver != NULL;
+}
+
+#define BC_PORT_MASK 0x8
+#define BC_LOWER_PORT 0x8
+
+#define BUS_CONVERTER(dev) \
+        ((dev->id.hw_type == HPHW_IOA) || (dev->id.hw_type == HPHW_BCPORT))
+
+#define IS_LOWER_PORT(dev) \
+        ((gsc_readl(&((struct bc_module *)dev->hpa)->io_status) \
+                & BC_PORT_MASK) == BC_LOWER_PORT)
+
+#define READ_IO_IO_LOW(dev) \
+	(dev->id.hw_type == HPHW_IOA ? \
+	        __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_low) << 16 : \
+	        __raw_readl((unsigned long)&((struct bc_module *)dev->hpa)->io_io_low))
 
-	return d;
-}	
+static void walk_native_bus(unsigned long addr, struct parisc_device *parent);
+void walk_lower_bus(struct parisc_device *dev)
+{
+
+	if(!BUS_CONVERTER(dev) || IS_LOWER_PORT(dev))
+		return;
 
-void print_devices(char * buf) {
+	walk_native_bus((unsigned long)(signed int)READ_IO_IO_LOW(dev), dev);
+}
 
+#define MAX_NATIVE_DEVICES 64
+#define NATIVE_DEVICE_OFFSET 0x1000
+
+/**
+ * walk_native_bus -- Probe a bus for devices
+ * @addr: Base address of this bus.
+ * 
+ * A native bus (eg Runway or GSC) may have up to 64 devices on it,
+ * spaced at intervals of 0x1000 bytes.  PDC may not inform us of these
+ * devices, so we have to probe for them.  Unfortunately, we may find
+ * devices which are not physically connected (such as extra serial &
+ * keyboard ports).  This problem is not yet solved.
+ */
+static void walk_native_bus(unsigned long addr, struct parisc_device *parent)
+{
 	int i;
-	struct hp_device *d;
-	printk("Found devices:\n");
-	for (i=0;i<num_devices;i++) {	
-		d = &devices[i];
-		printk(KERN_INFO 
-		"%d. %s (%d) at 0x%p, versions 0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", 
-		i+1,
-		(d->reference) ? d->reference->name : "Unknown device",
-		d->hw_type,d->hpa, d->hversion, d->hversion_rev,
-		d->sversion, d->sversion_rev, d->opt);
+	struct hardware_path path;
+
+	get_node_path(parent, &path);
+	for (i = 0; i < MAX_NATIVE_DEVICES; i++) {
+		unsigned long hpa = (addr + i * NATIVE_DEVICE_OFFSET);
+		struct parisc_device *dev;
+
+		/* Was the device already added by Firmware? */
+		dev = find_device_by_addr(hpa);
+		if (!dev) {
+			path.mod = i;
+			dev = alloc_pa_dev(hpa, &path);
+			if (!dev)
+				continue;
+
+			register_parisc_device(dev);
+		}
+		walk_lower_bus(dev);
+	}
+}
+
+#define CENTRAL_BUS_ADDR (unsigned long) 0xfffffffffff80000
+
+/**
+ * walk_central_bus - Find devices attached to the central bus
+ *
+ * PDC doesn't tell us about all devices in the system.  This routine
+ * finds devices connected to the central bus.
+ */
+void walk_central_bus(void)
+{
+	walk_native_bus(CENTRAL_BUS_ADDR, &root);
+}
+
+void fixup_child_irqs(struct parisc_device *parent, int base,
+			int (*choose_irq)(struct parisc_device *))
+{
+	struct parisc_device *dev;
 
+	if (!parent->child)
+		return;
+
+	for (dev = check_dev(parent->child); dev; dev = dev->sibling) {
+		int irq = choose_irq(dev);
+		if (irq > 0) {
+#ifdef __LP64__
+			irq += 32;
+#endif
+			dev->irq = base + irq;
+		}
 	}
-	printk("That's a total of %d devices.\n",num_devices);
 }
 
+static void print_parisc_device(struct parisc_device *dev)
+{
+	char hw_path[64];
+	static int count;
 
+	print_pa_hwpath(dev, hw_path);
+	printk(KERN_INFO "%d. %s (%d) at 0x%lx [%s], versions 0x%x, 0x%x, 0x%x",
+		++count, dev->name, dev->id.hw_type, dev->hpa, hw_path,
+		dev->id.hversion, dev->id.hversion_rev, dev->id.sversion);
+
+	if (dev->num_addrs) {
+		int k;
+		printk(",  additional addresses: ");
+		for (k = 0; k < dev->num_addrs; k++)
+			printk("0x%lx ", dev->addr[k]);
+	}
+	printk("\n");
+}
+
+void print_subdevices(struct parisc_device *parent)
+{
+	struct parisc_device *dev;
+	for (dev = parent->child; dev != parent->sibling; dev = next_dev(dev)) {
+		print_parisc_device(dev);
+	}
+}
+
+/**
+ * print_parisc_devices - Print out a list of devices found in this system
+ */
+void print_parisc_devices(void)
+{
+	struct parisc_device *dev;
+	for_each_padev(dev) {
+		print_parisc_device(dev);
+	}
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/entry.S linux/arch/parisc/kernel/entry.S
--- linux.orig/arch/parisc/kernel/entry.S	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/kernel/entry.S	2002-08-12 22:14:08.000000000 +0000
@@ -1,5 +1,5 @@
-/*------------------------------------------------------------------------------
- * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  *
  * kernel entry points (interruptions, system call wrappers)
  *  Copyright (C) 1999,2000 Philipp Rumpf 
@@ -25,39 +25,51 @@
 #include <linux/config.h>
 #include <asm/offset.h>
 
-/* the following is the setup i think we should follow:
- * whenever the CPU is interruptible, the following has to be true:
- *  CR30 is the kernel sp or 0 if we currently use the kernel stack
- *  CR31 is the kernel gp */ 
-
 /* we have the following possibilities to act on an interruption:
  *  - handle in assembly and use shadowed registers only
  *  - save registers to kernel stack and handle in assembly or C */
 
-	.text
-
-#ifdef __LP64__
-	.level 2.0w
-#endif
 
-#define __ASSEMBLY__
 #include <asm/assembly.h>	/* for LDREG/STREG defines */
 #include <asm/pgtable.h>
 #include <asm/psw.h>
 #include <asm/signal.h>
+#include <asm/unistd.h>
 
 #ifdef __LP64__
-#define FRAME_SIZE	64
+#define FRAME_SIZE	128
+#define CMPIB           cmpib,*
+#define CMPB            cmpb,*
+
+	.level 2.0w
 #else
 #define FRAME_SIZE	64
+#define CMPIB           cmpib,
+#define CMPB            cmpb,
+
+	.level 2.0
+#endif
+
+	.import         pa_dbit_lock,data
+
+	/* space_to_prot macro creates a prot id from a space id */
+
+#if (SPACEID_SHIFT) == 0
+	.macro  space_to_prot spc prot
+	depd,z  \spc,62,31,\prot
+	.endm
+#else
+	.macro  space_to_prot spc prot
+	extrd,u \spc,(64 - (SPACEID_SHIFT)),32,\prot
+	.endm
 #endif
 
 	/* Switch to virtual mapping, trashing only %r1 */
-	.macro	virt_map rfi_type
-	mtsm	%r0
-	tovirt	%r29
-	tovirt	%r30
+	.macro  virt_map
+	rsm     PSW_SM_Q,%r0
+	tovirt_r1 %r29
 	mfsp	%sr7, %r1
+	or,=    %r0,%r1,%r0 /* Only save sr7 in sr3 if sr7 != 0 */
 	mtsp	%r1, %sr3
 	mtsp	%r0, %sr4
 	mtsp	%r0, %sr5
@@ -65,95 +77,114 @@
 	mtsp	%r0, %sr7
 	ldil	L%KERNEL_PSW, %r1
 	ldo	R%KERNEL_PSW(%r1), %r1
-	LDIL_FIXUP(%r1)
 	mtctl	%r1, %cr22
 	mtctl	%r0, %cr17
 	mtctl	%r0, %cr17
-	ldil	L%.+28, %r1
-	ldo	R%.+24(%r1), %r1
-	LDIL_FIXUP(%r1)
+	ldil	L%4f, %r1
+	ldo	R%4f(%r1), %r1
 	mtctl	%r1, %cr18
 	ldo	4(%r1), %r1
 	mtctl	%r1, %cr18
-	\rfi_type
+	rfir
 	nop
+4:
 	.endm
 
-	.macro	get_stack
-	mfctl	%cr30, %r1 
-	comib,=,n 0, %r1, 0f   /* forward so predicted not taken */
+	/*
+	 * The "get_stack" macros are responsible for determining the
+	 * kernel stack value.
+	 *
+	 * For Faults:
+	 *      If sr7 == 0
+	 *          Already using a kernel stack, so call the
+	 *          get_stack_use_r30 macro to push a pt_regs structure
+	 *          on the stack, and store registers there.
+	 *      else
+	 *          Need to set up a kernel stack, so call the
+	 *          get_stack_use_cr30 macro to set up a pointer
+	 *          to the pt_regs structure contained within the
+	 *          task pointer pointed to by cr30. Set the stack
+	 *          pointer to point to the end of the task structure.
+	 *
+	 * For Interrupts:
+	 *      If sr7 == 0
+	 *          Already using a kernel stack, check to see if r30
+	 *          is already pointing to the per processor interrupt
+	 *          stack. If it is, call the get_stack_use_r30 macro
+	 *          to push a pt_regs structure on the stack, and store
+	 *          registers there. Otherwise, call get_stack_use_cr31
+	 *          to get a pointer to the base of the interrupt stack
+	 *          and push a pt_regs structure on that stack.
+	 *      else
+	 *          Need to set up a kernel stack, so call the
+	 *          get_stack_use_cr30 macro to set up a pointer
+	 *          to the pt_regs structure contained within the
+	 *          task pointer pointed to by cr30. Set the stack
+	 *          pointer to point to the end of the task structure.
+	 *          N.B: We don't use the interrupt stack for the
+	 *          first interrupt from userland, because signals/
+	 *          resched's are processed when returning to userland,
+	 *          and we can sleep in those cases.
+	 *
+	 * Note that we use shadowed registers for temps until
+	 * we can save %r26 and %r29. %r26 is used to preserve
+	 * %r8 (a shadowed register) which temporarily contained
+	 * either the fault type ("code") or the eirr. We need
+	 * to use a non-shadowed register to carry the value over
+	 * the rfir in virt_map. We use %r26 since this value winds
+	 * up being passed as the argument to either do_cpu_irq_mask
+	 * or handle_interruption. %r29 is used to hold a pointer
+	 * the register save area, and once again, it needs to
+	 * be a non-shadowed register so that it survives the rfir.
+	 *
+	 * N.B. TASK_SZ_ALGN and PT_SZ_ALGN include space for a stack frame.
+	 */
+
+	.macro  get_stack_use_cr30
 
 	/* we save the registers in the task struct */
-	ldo	TASK_REGS(%r1), %r29
-	tophys	%r29
-	STREG	%r30, PT_GR30(%r29)
-	STREG	%r1,  PT_CR30(%r29)
+
+	mfctl   %cr30, %r1
+	tophys  %r1,%r9
+	ldo     TASK_REGS(%r9),%r9
+	STREG   %r30, PT_GR30(%r9)
 	ldo	TASK_SZ_ALGN(%r1), %r30
-	b	1f		    /* unconditional so predicted taken */	
-	mtctl	%r0,%cr30
-0:
-	/* we put a struct pt_regs on the stack and save the registers there */
-	copy	%r30,%r29
-	ldo	PT_SZ_ALGN(%r30),%r30
-	tophys	%r29
-	STREG	%r30,PT_GR30(%r29)
-	STREG	%r0,PT_CR30(%r29)
-1:
+	STREG   %r29,PT_GR29(%r9)
+	STREG   %r26,PT_GR26(%r9)
+	copy    %r9,%r29
 	.endm
 
-	.macro	rest_stack regs
-	LDREG	PT_CR30(\regs), %r1
-	comib,=,n 0, %r1, 2f/* forward so predicted not taken */
-
-	/* we restore the registers out of the task struct */
-	mtctl	%r1, %cr30
-	LDREG	PT_GR1(\regs), %r1
-	LDREG	PT_GR30(\regs),%r30
-	b	3f
-	LDREG	PT_GR29(\regs),%r29
-2:
-	/* we take a struct pt_regs off the stack */
-	LDREG	PT_GR1(\regs),  %r1
-	LDREG	PT_GR29(\regs), %r29
-	ldo	-PT_SZ_ALGN(%r30), %r30
-3:
-	.endm
+	.macro  get_stack_use_r30
 
-#ifdef OLD
-	/* fixme interruption handler */
-	.macro	def code
-	/* WARNING!!! THIS IS DEBUG CODE ONLY!!! */
-	b	unimplemented_64bitirq
-	ldi	\code, %r1
-	.align	32
+	/* we put a struct pt_regs on the stack and save the registers there */
+
+	tophys  %r30,%r9
+	STREG   %r30,PT_GR30(%r9)
+	ldo	PT_SZ_ALGN(%r30),%r30
+	STREG   %r29,PT_GR29(%r9)
+	STREG   %r26,PT_GR26(%r9)
+	copy    %r9,%r29
 	.endm
 
-	/* Use def to enable break - KWDB wants em
-	 * (calls traps.c:handle_interruption) */
-	.macro	pass_break code
+	.macro  rest_stack
+	LDREG   PT_GR1(%r29), %r1
+	LDREG   PT_GR30(%r29),%r30
+	LDREG   PT_GR29(%r29),%r29
+	.endm
 
-#else
 	/* default interruption handler
 	 * (calls traps.c:handle_interruption) */
 	.macro	def code
-#endif
-	mtctl	%r29, %cr31
-	mtctl	%r1,  %cr28
-	ldi	\code, %r1
 	b	intr_save
-	mtctl   %r1, %cr29
+	ldi     \code, %r8
 	.align	32
 	.endm
 
 	/* Interrupt interruption handler
-	 * (calls irq.c:do_irq_mask) */
+	 * (calls irq.c:do_cpu_irq_mask) */
 	.macro	extint code
-	mtctl	%r29, %cr31
-	mtctl	%r1,  %cr28
-	mfctl	%cr23, %r1
-	mtctl	%r1, %cr23
 	b	intr_extint
-	mtctl	%r1, %cr29
+	mfsp    %sr7,%r16
 	.align	32
 	.endm	
 
@@ -203,7 +234,6 @@
 	 */
 
 	.macro	itlb_20 code
-
 	mfctl	%pcsq, spc
 #ifdef __LP64__
 	b       itlb_miss_20w
@@ -298,37 +328,27 @@
 	.endm
 	
 #ifndef __LP64__
-	/* nadtlb miss interruption handler (parisc 1.1 - 32 bit)
-	 *
-	 * Note: nadtlb misses will be treated
-	 * as an ordinary dtlb miss for now.
-	 *
-	 */
+	/* nadtlb miss interruption handler (parisc 1.1 - 32 bit) */
 
 	.macro	nadtlb_11 code
 
 	mfctl	%isr,spc
-	b	dtlb_miss_11
+	b       nadtlb_miss_11
 	mfctl	%ior,va
 
 	.align		32
 	.endm
 #endif
 	
-	/* nadtlb miss interruption handler (parisc 2.0)
-	 *
-	 * Note: nadtlb misses will be treated
-	 * as an ordinary dtlb miss for now.
-	 *
-	 */
+	/* nadtlb miss interruption handler (parisc 2.0) */
 
 	.macro	nadtlb_20 code
 
 	mfctl	%isr,spc
 #ifdef __LP64__
-	b       dtlb_miss_20w
+	b       nadtlb_miss_20w
 #else
-	b	dtlb_miss_20
+	b       nadtlb_miss_20
 #endif
 	mfctl	%ior,va
 
@@ -372,13 +392,14 @@
 	 * fault_vector_11 and fault_vector_20 are on the
 	 * same page. This is only necessary as long as we
 	 * write protect the kernel text, which we may stop
-	 * doing once we use large parge translations to cover
+	 * doing once we use large page translations to cover
 	 * the static part of the kernel address space.
 	 */
 
-
 	.export fault_vector_20
 
+	.text
+
 	.align 4096
 
 fault_vector_20:
@@ -402,7 +423,11 @@
 	def		13
 	def		14
 	dtlb_20		15
+#if 0
 	naitlb_20	16
+#else
+	def             16
+#endif
 	nadtlb_20	17
 	def		18
 	def		19
@@ -446,7 +471,11 @@
 	def		13
 	def		14
 	dtlb_11		15
+#if 0
 	naitlb_11	16
+#else
+	def             16
+#endif
 	nadtlb_11	17
 	def		18
 	def		19
@@ -467,7 +496,7 @@
 
 	.import		handle_interruption,code
 	.import		handle_real_interruption,code
-	.import		do_irq_mask,code
+	.import		do_cpu_irq_mask,code
 	.import		parisc_stopkernel,code
 	.import		cpu_irq_region,data
 
@@ -492,7 +521,8 @@
 	ldo	PT_SZ_ALGN(%r30),%r30
 #ifdef __LP64__
 	/* Yo, function pointers in wide mode are little structs... -PB */
-	/* XXX FIXME do we need to honor the fptr's %dp value too? */
+	ldd	24(%r26), %r2
+	STREG	%r2, PT_GR27(%r1)	/* Store childs %dp */
 	ldd	16(%r26), %r26
 #endif
 	STREG	%r26, PT_GR26(%r1)  /* Store function & argument for child */
@@ -500,15 +530,17 @@
 	ldo	CLONE_VM(%r0), %r26   /* Force CLONE_VM since only init_mm */
 	or	%r26, %r24, %r26      /* will have kernel mappings.	 */
 	copy	%r0, %r25
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
 	bl	do_fork, %r2
 	copy	%r1, %r24
 
 	/* Parent Returns here */
 
-	ldo	-PT_SZ_ALGN(%r30), %r30
-	LDREG	-RP_OFFSET(%r30), %r2
+	LDREG	-PT_SZ_ALGN-RP_OFFSET(%r30), %r2
 	bv	%r0(%r2)
-	nop
+	ldo	-PT_SZ_ALGN(%r30), %r30
 
 	/*
 	 * Child Returns here
@@ -520,11 +552,22 @@
 	.export	ret_from_kernel_thread
 ret_from_kernel_thread:
 
+	/* Call schedule_tail first though */
+	bl	schedule_tail, %r2
+	nop
+
 	LDREG	TASK_PT_GR26-TASK_SZ_ALGN(%r30), %r1
 	LDREG	TASK_PT_GR25-TASK_SZ_ALGN(%r30), %r26
+#ifdef __LP64__
+	LDREG	TASK_PT_GR27-TASK_SZ_ALGN(%r30), %r27
+#endif
 	ble	0(%sr7, %r1)
 	copy	%r31, %r2
 
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+	loadgp				/* Thread could have been in a module */
+#endif
 	b	sys_exit
 	ldi	0, %r26
 
@@ -532,23 +575,22 @@
 	.export	__execve, code
 __execve:
 	copy	%r2, %r15
-	copy	%r23, %r17
 	copy	%r30, %r16
 	ldo	PT_SZ_ALGN(%r30), %r30
 	STREG	%r26, PT_GR26(%r16)
 	STREG	%r25, PT_GR25(%r16)
 	STREG	%r24, PT_GR24(%r16)
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
 	bl	sys_execve, %r2
 	copy	%r16, %r26
 
-	comib,<>,n 0,%r28,__execve_failed
-
-	b	intr_return
-	STREG	%r17, PT_CR30(%r16)
+	cmpib,=,n 0,%r28,intr_return    /* forward */
 
-__execve_failed:
 	/* yes, this will trap and die. */
 	copy	%r15, %r2
+	copy	%r16, %r30
 	bv	%r0(%r2)
 	nop
 
@@ -567,16 +609,14 @@
 
 	ldil	L%_switch_to_ret, %r2
 	ldo	R%_switch_to_ret(%r2), %r2
-	LDIL_FIXUP(%r2)
 
 	STREG	%r2, TASK_PT_KPC(%r26)
 	LDREG	TASK_PT_KPC(%r25), %r2
 
 	STREG	%r30, TASK_PT_KSP(%r26)
 	LDREG	TASK_PT_KSP(%r25), %r30
-
 	bv	%r0(%r2)
-	nop
+	mtctl   %r25,%cr30
 
 _switch_to_ret:
 	mtctl	%r0, %cr0		/* Needed for single stepping */
@@ -587,27 +627,30 @@
 	copy	%r26, %r28
 
 	/*
-	 * Common rfi return path for interruptions, kernel execve, and some
-	 * syscalls.  The sys_rt_sigreturn syscall will return via this path
-	 * if the signal was received when the process was running; if the
-	 * process was blocked on a syscall then the normal syscall_exit
-	 * path is used.  All syscalls for traced proceses exit via
-	 * intr_restore.
-	 * Note that the following code uses a "relied upon translation". See
-	 * the parisc ACD for details. The ssm is necessary due to a PCXT bug.
+	 * Common rfi return path for interruptions, kernel execve, and
+	 * sys_rt_sigreturn (sometimes).  The sys_rt_sigreturn syscall will
+	 * return via this path if the signal was received when the process
+	 * was running; if the process was blocked on a syscall then the
+	 * normal syscall_exit path is used.  All syscalls for traced
+	 * proceses exit via intr_restore.
+	 *
+	 * XXX If any syscalls that change a processes space id ever exit
+	 * this way, then we will need to copy %sr3 in to PT_SR[3..7], and
+	 * adjust IASQ[0..1].
+	 *
+	 * Note that the following code uses a "relied upon translation".
+	 * See the parisc ACD for details. The ssm is necessary due to a
+	 * PCXT bug.
 	 */
 
 	.align 4096
 
 	.export	syscall_exit_rfi
 syscall_exit_rfi:
-	copy    %r30,%r16
-	/* FIXME! depi below has hardcoded dependency on kernel stack size */
-	depi    0,31,14,%r16 /* get task pointer */
+	mfctl   %cr30,%r16
 	ldo	TASK_REGS(%r16),%r16
 	/* Force iaoq to userspace, as the user has had access to our current
-	 * context via sigcontext.
-	 * XXX do we need any other protection here?
+	 * context via sigcontext. Also Filter the PSW for the same reason.
 	 */
 	LDREG	PT_IAOQ0(%r16),%r19
 	depi	3,31,2,%r19
@@ -615,57 +658,84 @@
 	LDREG	PT_IAOQ1(%r16),%r19
 	depi	3,31,2,%r19
 	STREG	%r19,PT_IAOQ1(%r16)
-	
+	LDREG   PT_PSW(%r16),%r19
+	ldil    L%USER_PSW_MASK,%r1
+	ldo     R%USER_PSW_MASK(%r1),%r1
+#ifdef __LP64__
+	ldil    L%USER_PSW_HI_MASK,%r20
+	ldo     R%USER_PSW_HI_MASK(%r20),%r20
+	depd    %r20,31,32,%r1
+#endif
+	and     %r19,%r1,%r19 /* Mask out bits that user shouldn't play with */
+	ldil    L%USER_PSW,%r1
+	ldo     R%USER_PSW(%r1),%r1
+	or      %r19,%r1,%r19 /* Make sure default USER_PSW bits are set */
+	STREG   %r19,PT_PSW(%r16)
+
+	/*
+	 * If we aren't being traced, we never saved space registers
+	 * (we don't store them in the sigcontext), so set them
+	 * to "proper" values now (otherwise we'll wind up restoring
+	 * whatever was last stored in the task structure, which might
+	 * be inconsistant if an interrupt occured while on the gateway
+	 * page) Note that we may be "trashing" values the user put in
+	 * them, but we don't support the the user changing them.
+	 */
+
+	STREG   %r0,PT_SR2(%r16)
+	mfsp    %sr3,%r19
+	STREG   %r19,PT_SR0(%r16)
+	STREG   %r19,PT_SR1(%r16)
+	STREG   %r19,PT_SR3(%r16)
+	STREG   %r19,PT_SR4(%r16)
+	STREG   %r19,PT_SR5(%r16)
+	STREG   %r19,PT_SR6(%r16)
+	STREG   %r19,PT_SR7(%r16)
+
 intr_return:
+	ssm     PSW_SM_I, %r0
 
 	/* Check for software interrupts */
 
 	.import irq_stat,data
 
-	ldil    L%irq_stat,%r19
-	ldo     R%irq_stat(%r19),%r19
-	LDIL_FIXUP(%r19)
-
+	ldil	L%irq_stat,%r19
+	ldo	R%irq_stat(%r19),%r19
 #ifdef CONFIG_SMP
-	copy    %r30,%r1
-	/* FIXME! depi below has hardcoded dependency on kernel stack size */
-	depi    0,31,14,%r1 /* get task pointer */
-	ldw     TASK_PROCESSOR(%r1),%r20 /* get cpu # - int */
-#if (IRQSTAT_SZ == 32)
-	dep     %r20,26,27,%r20 /* shift left 5 bits */
-#else
-#error IRQSTAT_SZ changed, fix dep
-#endif /* IRQSTAT_SZ */
-	add     %r19,%r20,%r19
+	mfctl   %cr30,%r1
+	ldw	TASK_PROCESSOR(%r1),%r1 /* get cpu # - int */
+	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) amount
+	** irq_stat[] is defined using ____cacheline_aligned.
+	*/
+#ifdef __LP64__
+	shld	%r1, 6, %r20
+#else
+	shlw	%r1, 5, %r20
+#endif
+	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
 #endif /* CONFIG_SMP */
 
-	ldw     IRQSTAT_SI_ACTIVE(%r19),%r20	/* hardirq.h: unsigned int */
-	ldw     IRQSTAT_SI_MASK(%r19),%r19	/* hardirq.h: unsigned int */
-	and     %r19,%r20,%r20
-	comib,<>,n 0,%r20,intr_do_softirq /* forward */
+	LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
+	cmpib,<>,n 0,%r20,intr_do_softirq /* forward */
 
 intr_check_resched:
 
 	/* check for reschedule */
-	copy    %r30,%r1
-	/* FIXME! depi below has hardcoded dependency on kernel stack size */
-	depi    0,31,14,%r1 /* get task pointer */
+	mfctl   %cr30,%r1
 	LDREG     TASK_NEED_RESCHED(%r1),%r19	/* sched.h: long need_resched */
-	comib,<>,n 0,%r19,intr_do_resched /* forward */
+	CMPIB<>,n 0,%r19,intr_do_resched /* forward */
 
 intr_check_sig:
 	/* As above */
-	copy    %r30,%r1
-	depi    0,31,14,%r1 /* get task pointer */
+	mfctl   %cr30,%r1
 	ldw	TASK_SIGPENDING(%r1),%r19	/* sched.h: int sigpending */
-	comib,<>,n 0,%r19,intr_do_signal /* forward */
+	cmpib,<>,n 0,%r19,intr_do_signal /* forward */
 
 intr_restore:
-	copy	    	%r16, %r29
-	ldo		PT_FR31(%r29), %r29
-	rest_fp		%r29
-	copy    	%r16, %r29
-	rest_general 	%r29
+	copy            %r16,%r29
+	ldo             PT_FR31(%r29),%r1
+	rest_fp         %r1
+	rest_general    %r29
 	ssm		0,%r0
 	nop
 	nop
@@ -674,10 +744,10 @@
 	nop
 	nop
 	nop
-	tophys		%r29
-	mtsm		%r0
+	tophys_r1       %r29
+	rsm             (PSW_SM_Q|PSW_SM_P|PSW_SM_D|PSW_SM_I),%r0
 	rest_specials	%r29
-	rest_stack	%r29
+	rest_stack
 	rfi
 	nop
 	nop
@@ -691,88 +761,175 @@
 	.import do_softirq,code
 intr_do_softirq:
 	bl      do_softirq,%r2
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#else
 	nop
+#endif
 	b       intr_check_resched
 	nop
 
 	.import schedule,code
 intr_do_resched:
 	/* Only do reschedule if we are returning to user space */
-	LDREG     PT_SR7(%r16), %r20
-	comib,= 0,%r20,intr_restore /* backward */
+	LDREG   PT_IASQ0(%r16), %r20
+	CMPIB= 0,%r20,intr_restore /* backward */
+	nop
+	LDREG   PT_IASQ1(%r16), %r20
+	CMPIB= 0,%r20,intr_restore /* backward */
 	nop
 
-	bl      schedule,%r2
-	ssm     PSW_SM_I, %r0
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
+
+	ldil	L%intr_return, %r2
+	b	schedule
+	ldo	R%intr_return(%r2), %r2	/* return to intr_return, not here */
 
-	/* It's OK to leave I bit on */
-	b       intr_return /* start over if we got a resched */
-	nop
 
 	.import do_signal,code
 intr_do_signal:
 	/* Only do signals if we are returning to user space */
-	LDREG   PT_SR7(%r16), %r20
-	comib,= 0,%r20,intr_restore /* backward */
+	LDREG   PT_IASQ0(%r16), %r20
+	CMPIB= 0,%r20,intr_restore /* backward */
+	nop
+	LDREG   PT_IASQ1(%r16), %r20
+	CMPIB= 0,%r20,intr_restore /* backward */
 	nop
 
 	copy	%r0, %r24			/* unsigned long in_syscall */
 	copy	%r16, %r25			/* struct pt_regs *regs */
 	ssm     PSW_SM_I, %r0
+#ifdef __LP64__
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#endif
 	bl	do_signal,%r2
 	copy	%r0, %r26			/* sigset_t *oldset = NULL */
 
 	b	intr_restore
 	nop
 
-	/* CR28 - saved GR1
-	 * CR29 - argument for do_irq_mask */
+	/*
+	 * External interrupts.
+	 */
 
-	/* External interrupts */
 intr_extint:
-	get_stack
+	CMPIB=,n 0,%r16,1f
+	get_stack_use_cr30
+	b,n 3f
+
+1:
+#if 0  /* Interrupt Stack support not working yet! */
+	mfctl	%cr31,%r1
+	copy	%r30,%r17
+	/* FIXME! depi below has hardcoded idea of interrupt stack size (32k)*/
+#ifdef __LP64__
+	depdi	0,63,15,%r17
+#else
+	depi	0,31,15,%r17
+#endif
+	CMPB=,n	%r1,%r17,2f
+	get_stack_use_cr31
+	b,n 3f
+#endif
+2:
+	get_stack_use_r30
+
+3:
 	save_specials	%r29
-	virt_map	rfi
+	virt_map
 	save_general	%r29
 
-	ldo		PT_FR0(%r29), %r24
-	save_fp		%r24
+	ldo	PT_FR0(%r29), %r24
+	save_fp	%r24
 	
 	loadgp
 
-	copy		%r29, %r24	/* arg2 is pt_regs */
-	copy		%r29, %r16	/* save pt_regs */
+	copy	%r29, %r25	/* arg1 is pt_regs */
+	copy	%r29, %r16	/* save pt_regs */
 #ifdef CONFIG_KWDB
-	copy		%r29, %r3	/* KWDB - update frame pointer (gr3) */
+	copy	%r29, %r3	/* KWDB - update frame pointer (gr3) */
 #endif
 
-	/* sorry to put this cruft in the interrupt path */
-	ldil		L%cpu_irq_region, %r25
-	ldo		R%cpu_irq_region(%r25), %r25
-	bl		do_irq_mask,%r2
 #ifdef __LP64__
-	LDIL_FIXUP(%r25)
+	ldo	-16(%r30),%r29	/* Reference param save area */
 #else
 	nop
 #endif
-
-	b		intr_return
-	nop
+	
+	/*
+	 * We need to either load the CPU's ID or IRQ region.
+	 * Until we have "per CPU" IRQ regions, this is easy.
+	 */
+	ldil	L%cpu_irq_region, %r26
+	ldil	L%intr_return, %r2
+	ldo	R%cpu_irq_region(%r26), %r26
+	
+	b	do_cpu_irq_mask
+	ldo	R%intr_return(%r2), %r2	/* return to intr_return, not here */
 
 	/* Generic interruptions (illegal insn, unaligned, page fault, etc) */
 
 	.export         intr_save, code /* for os_hpmc */
 
 intr_save:
-	get_stack
+	mfsp    %sr7,%r16
+	CMPIB=,n 0,%r16,1f
+	get_stack_use_cr30
+	b	2f
+	copy    %r8,%r26
+
+1:
+	get_stack_use_r30
+	copy    %r8,%r26
+
+2:
 	save_specials	%r29
 
-	mfctl		%cr20, %r1
-	STREG		%r1, PT_ISR(%r29)
-	mfctl		%cr21, %r1
-	STREG		%r1, PT_IOR(%r29)
+	/* If this trap is a itlb miss, skip saving/adjusting isr/ior */
+
+	/*
+	 * FIXME: 1) Use a #define for the hardwired "6" below (and in
+	 *           traps.c.
+	 *        2) Once we start executing code above 4 Gb, we need
+	 *           to adjust iasq/iaoq here in the same way we
+	 *           adjust isr/ior below.
+	 */
+
+	CMPIB=,n        6,%r26,skip_save_ior
+
+	/* save_specials left ipsw value in r8 for us to test */
+
+	mfctl           %cr20, %r16 /* isr */
+	mfctl           %cr21, %r17 /* ior */
+
+#ifdef __LP64__
+	/*
+	 * If the interrupted code was running with W bit off (32 bit),
+	 * clear the b bits (bits 0 & 1) in the ior.
+	 */
+	extrd,u,*<>     %r8,PSW_W_BIT,1,%r0
+	depdi           0,1,2,%r17
+
+	/*
+	 * FIXME: This code has hardwired assumptions about the split
+	 *        between space bits and offset bits. This will change
+	 *        when we allow alternate page sizes.
+	 */
+
+	/* adjust isr/ior. */
+
+	extrd,u         %r16,63,7,%r1    /* get high bits from isr for ior */
+	depd            %r1,31,7,%r17    /* deposit them into ior */
+	depdi           0,63,7,%r16      /* clear them from isr */
+#endif
+	STREG           %r16, PT_ISR(%r29)
+	STREG           %r17, PT_IOR(%r29)
+
 
-	virt_map	rfi
+skip_save_ior:
+	virt_map
 	save_general	%r29
 
 	ldo		PT_FR0(%r29), %r25
@@ -785,11 +942,16 @@
 	copy		%r29, %r3	/* KWDB - update frame pointer (gr3) */
 #endif
 
-	bl		handle_interruption,%r2
-	copy		%r29, %r16	/* save pt_regs */
+#ifdef __LP64__
+	ldo		-16(%r30),%r29	/* Reference param save area */
+#endif
+
+	ldil		L%intr_return, %r2
+	copy		%r25, %r16	/* save pt_regs */
+
+	b		handle_interruption
+	ldo		R%intr_return(%r2), %r2	/* return to intr_return */
 
-	b		intr_return
-	nop
 
 	/*
 	 * Note for all tlb miss handlers:
@@ -821,10 +983,9 @@
 #ifdef __LP64__
 
 dtlb_miss_20w:
-
-	extrd,u         spc,31,7,t1     /* adjust va */
+	extrd,u         spc,63,7,t1     /* adjust va */
 	depd            t1,31,7,va      /* adjust va */
-	depdi           0,31,7,spc      /* adjust space */
+	depdi           0,63,7,spc      /* adjust space */
 	mfctl           %cr25,ptp	/* Assume user space miss */
 	or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
 	mfctl           %cr24,ptp	/* Load kernel pgd instead */
@@ -832,20 +993,20 @@
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
-	comb,<>,n       t0,spc,dtlb_fault /* forward */
+	cmpb,*<>,n       t0,spc,dtlb_fault /* forward */
 
 	/* First level page table lookup */
 
 	ldd,s           t1(ptp),ptp
 	extrd,u         va,42,9,t0     /* get second-level index */
-	bb,>=,n 	ptp,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
 	depdi           0,63,12,ptp     /* clear prot bits */
 
 	/* Second level page table lookup */
 
 	ldd,s           t0(ptp),ptp
 	extrd,u         va,51,9,t0     /* get third-level index */
-	bb,>=,n 	ptp,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
 	depdi           0,63,12,ptp     /* clear prot bits */
 
 	/* Third level page table lookup */
@@ -853,7 +1014,7 @@
 	shladd           t0,3,ptp,ptp
 	ldi		_PAGE_ACCESSED,t1
 	ldd              0(ptp),pte
-	bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20w
 
 	/* Check whether the "accessed" bit was set, otherwise do so */
 
@@ -861,11 +1022,9 @@
 	and,*<>         t1,pte,%r0      /* test and nullify if already set */
 	std             t0,0(ptp)       /* write back pte */
 
-	copy            spc,prot	/* init prot with faulting space */
-	
-	depd		pte,8,7,prot
-	extrd,u,*=	pte,_PAGE_NO_CACHE_BIT+32,1,r0
-	depdi		1,12,1,prot
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
+
 	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
 	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
 	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
@@ -874,11 +1033,106 @@
 	/* Get rid of prot bits and convert to page addr for idtlbt */
 
 	depdi		0,63,12,pte
-	extrd,u         pte,56,32,pte
-	idtlbt		%r16,%r17
+	extrd,u         pte,56,52,pte
+	idtlbt          pte,prot
 
 	rfir
 	nop
+
+dtlb_check_alias_20w:
+
+	/* Check to see if fault is in the temporary alias region */
+
+	cmpib,*<>,n     0,spc,dtlb_fault /* forward */
+	ldil            L%(TMPALIAS_MAP_START),t0
+	copy            va,t1
+	depdi           0,63,23,t1
+	cmpb,*<>,n      t0,t1,dtlb_fault /* forward */
+	ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
+	depd,z          prot,8,7,prot
+
+	/*
+	 * OK, it is in the temp alias region, check whether "from" or "to".
+	 * Check "subtle" note in pacache.S re: r23/r26.
+	 */
+
+	extrd,u,*=      va,41,1,r0
+	or,*tr          %r23,%r0,pte    /* If "from" use "from" page */
+	or,*            %r26,%r0,pte    /* else "to", use "to" page  */
+
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
+nadtlb_miss_20w:
+	extrd,u         spc,63,7,t1     /* adjust va */
+	depd            t1,31,7,va      /* adjust va */
+	depdi           0,63,7,spc      /* adjust space */
+	mfctl           %cr25,ptp	/* Assume user space miss */
+	or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
+	mfctl           %cr24,ptp	/* Load kernel pgd instead */
+	extrd,u         va,33,9,t1      /* Get pgd index */
+
+	mfsp            %sr7,t0		/* Get current space */
+	or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
+	cmpb,*<>,n       t0,spc,nadtlb_fault /* forward */
+
+	/* First level page table lookup */
+
+	ldd,s           t1(ptp),ptp
+	extrd,u         va,42,9,t0     /* get second-level index */
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
+	depdi           0,63,12,ptp     /* clear prot bits */
+
+	/* Second level page table lookup */
+
+	ldd,s           t0(ptp),ptp
+	extrd,u         va,51,9,t0     /* get third-level index */
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
+	depdi           0,63,12,ptp     /* clear prot bits */
+
+	/* Third level page table lookup */
+
+	shladd           t0,3,ptp,ptp
+	ldi		_PAGE_ACCESSED,t1
+	ldd              0(ptp),pte
+	bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20w
+
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
+
+	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
+	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
+	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
+	depdi		0,11,2,prot	/* If Gateway, Set PL2 to 0 */
+
+	/* Get rid of prot bits and convert to page addr for idtlbt */
+
+	depdi		0,63,12,pte
+	extrd,u         pte,56,52,pte
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
+nadtlb_check_flush_20w:
+	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
+
+	/* Insert a "flush only" translation */
+
+	depdi,z         7,7,3,prot
+	depdi           1,10,1,prot
+
+	/* Get rid of prot bits and convert to page addr for idtlbt */
+
+	depdi		0,63,12,pte
+	extrd,u         pte,56,52,pte
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
 #else
 
 dtlb_miss_11:
@@ -889,13 +1143,13 @@
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
-	comb,<>,n       t0,spc,dtlb_fault /* forward */
+	cmpb,<>,n       t0,spc,dtlb_fault /* forward */
 
 	/* First level page table lookup */
 
 	ldwx,s		t1(ptp),ptp
 	extru		va,19,10,t0	/* get second-level index */
-	bb,>=,n 	ptp,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_11
 	depi		0,31,12,ptp	/* clear prot bits */
 
 	/* Second level page table lookup */
@@ -903,7 +1157,7 @@
 	sh2addl 	 t0,ptp,ptp
 	ldi		_PAGE_ACCESSED,t1
 	ldw		 0(ptp),pte
-	bb,>=,n 	 pte,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_11
 
 	/* Check whether the "accessed" bit was set, otherwise do so */
 
@@ -911,8 +1165,8 @@
 	and,<>		t1,pte,%r0	/* test and nullify if already set */
 	stw		t0,0(ptp)	/* write back pte */
 
-	copy            spc,prot	/* init prot with faulting space */
-	dep		pte,8,7,prot
+	zdep            spc,30,15,prot  /* create prot id from space */
+	dep             pte,8,7,prot    /* add in prot bits from pte */
 
 	extru,=		pte,_PAGE_NO_CACHE_BIT,1,r0
 	depi		1,12,1,prot
@@ -937,9 +1191,108 @@
 	rfir
 	nop
 
-dtlb_miss_20:
-	.level 2.0
+dtlb_check_alias_11:
+
+	/* Check to see if fault is in the temporary alias region */
+
+	cmpib,<>,n      0,spc,dtlb_fault /* forward */
+	ldil            L%(TMPALIAS_MAP_START),t0
+	copy            va,t1
+	depwi           0,31,23,t1
+	cmpb,<>,n       t0,t1,dtlb_fault /* forward */
+	ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
+	depw,z          prot,8,7,prot
+
+	/*
+	 * OK, it is in the temp alias region, check whether "from" or "to".
+	 * Check "subtle" note in pacache.S re: r23/r26.
+	 */
+
+	extrw,u,=       va,9,1,r0
+	or,tr           %r23,%r0,pte    /* If "from" use "from" page */
+	or              %r26,%r0,pte    /* else "to", use "to" page  */
+
+	idtlba          pte,(va)
+	idtlbp          prot,(va)
+
+	rfir
+	nop
+
+nadtlb_miss_11:
+	mfctl           %cr25,ptp	/* Assume user space miss */
+	or,<>           %r0,spc,%r0	/* If it is user space, nullify */
+	mfctl           %cr24,ptp	/* Load kernel pgd instead */
+	extru		va,9,10,t1	/* Get pgd index */
+
+	mfsp            %sr7,t0		/* Get current space */
+	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
+	cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
+
+	/* First level page table lookup */
+
+	ldwx,s		t1(ptp),ptp
+	extru		va,19,10,t0	/* get second-level index */
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
+	depi		0,31,12,ptp	/* clear prot bits */
+
+	/* Second level page table lookup */
+
+	sh2addl 	 t0,ptp,ptp
+	ldi		_PAGE_ACCESSED,t1
+	ldw		 0(ptp),pte
+	bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_11
+
+	zdep            spc,30,15,prot  /* create prot id from space */
+	dep             pte,8,7,prot    /* add in prot bits from pte */
+
+	extru,=		pte,_PAGE_NO_CACHE_BIT,1,r0
+	depi		1,12,1,prot
+	extru,=         pte,_PAGE_USER_BIT,1,r0
+	depi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
+	extru,= 	pte,_PAGE_GATEWAY_BIT,1,r0
+	depi		0,11,2,prot	/* If Gateway, Set PL2 to 0 */
+
+	/* Get rid of prot bits and convert to page addr for idtlba */
+
+	depi		0,31,12,pte
+	extru		pte,24,25,pte
+
+	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+	mtsp		spc,%sr1
+
+	idtlba		pte,(%sr1,va)
+	idtlbp		prot,(%sr1,va)
+
+	mtsp		t0, %sr1	/* Restore sr1 */
+
+	rfir
+	nop
+
+nadtlb_check_flush_11:
+	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
+
+	/* Insert a "flush only" translation */
+
+	zdepi           7,7,3,prot
+	depi            1,10,1,prot
+
+	/* Get rid of prot bits and convert to page addr for idtlba */
+
+	depi		0,31,12,pte
+	extru		pte,24,25,pte
 
+	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+	mtsp		spc,%sr1
+
+	idtlba		pte,(%sr1,va)
+	idtlbp		prot,(%sr1,va)
+
+	mtsp		t0, %sr1	/* Restore sr1 */
+
+	rfir
+	nop
+
+dtlb_miss_20:
 	mfctl           %cr25,ptp	/* Assume user space miss */
 	or,<>           %r0,spc,%r0	/* If it is user space, nullify */
 	mfctl           %cr24,ptp	/* Load kernel pgd instead */
@@ -947,13 +1300,13 @@
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
-	comb,<>,n       t0,spc,dtlb_fault /* forward */
+	cmpb,<>,n       t0,spc,dtlb_fault /* forward */
 
 	/* First level page table lookup */
 
 	ldwx,s		t1(ptp),ptp
 	extru		va,19,10,t0	/* get second-level index */
-	bb,>=,n 	ptp,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,dtlb_check_alias_20
 	depi		0,31,12,ptp	/* clear prot bits */
 
 	/* Second level page table lookup */
@@ -961,7 +1314,7 @@
 	sh2addl 	 t0,ptp,ptp
 	ldi		_PAGE_ACCESSED,t1
 	ldw		 0(ptp),pte
-	bb,>=,n 	 pte,_PAGE_PRESENT_BIT,dtlb_fault
+	bb,>=,n          pte,_PAGE_PRESENT_BIT,dtlb_check_alias_20
 
 	/* Check whether the "accessed" bit was set, otherwise do so */
 
@@ -969,11 +1322,9 @@
 	and,<>		t1,pte,%r0	/* test and nullify if already set */
 	stw		t0,0(ptp)	/* write back pte */
 
-	copy            spc,prot	/* init prot with faulting space */
-	
-	depd		pte,8,7,prot
-	extrd,u,*=	pte,_PAGE_NO_CACHE_BIT+32,1,r0
-	depdi		1,12,1,prot
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
+
 	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
 	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
 	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
@@ -981,16 +1332,145 @@
 
 	/* Get rid of prot bits and convert to page addr for idtlbt */
 
-	depdi		0,63,12,pte
-	extrd,u		pte,56,25,pte
-	idtlbt		%r16,%r17
+	extrd,s         pte,35,4,t0
+	depdi		0,63,12,pte	/* clear lower 12 bits */
+        addi,=          1,t0,0 
+        extrd,u,*tr     pte,56,25,pte 
+	extrd,s		pte,56,25,pte	/* bit 31:8 >> 8  */ 
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
+dtlb_check_alias_20:
+
+	/* Check to see if fault is in the temporary alias region */
 
-	.level		1.1
+	cmpib,<>,n      0,spc,dtlb_fault /* forward */
+	ldil            L%(TMPALIAS_MAP_START),t0
+	copy            va,t1
+	depwi           0,31,23,t1
+	cmpb,<>,n       t0,t1,dtlb_fault /* forward */
+	ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
+	depd,z          prot,8,7,prot
+
+	/*
+	 * OK, it is in the temp alias region, check whether "from" or "to".
+	 * Check "subtle" note in pacache.S re: r23/r26.
+	 */
+
+	extrw,u,=       va,9,1,r0
+	or,tr           %r23,%r0,pte    /* If "from" use "from" page */
+	or              %r26,%r0,pte    /* else "to", use "to" page  */
+
+	idtlbt          pte,prot
+
+	rfir
+	nop
+
+nadtlb_miss_20:
+	mfctl           %cr25,ptp	/* Assume user space miss */
+	or,<>           %r0,spc,%r0	/* If it is user space, nullify */
+	mfctl           %cr24,ptp	/* Load kernel pgd instead */
+	extru		va,9,10,t1	/* Get pgd index */
+
+	mfsp            %sr7,t0		/* Get current space */
+	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
+	cmpb,<>,n       t0,spc,nadtlb_fault /* forward */
+
+	/* First level page table lookup */
+
+	ldwx,s		t1(ptp),ptp
+	extru		va,19,10,t0	/* get second-level index */
+	bb,>=,n         ptp,_PAGE_PRESENT_BIT,nadtlb_emulate
+	depi		0,31,12,ptp	/* clear prot bits */
+
+	/* Second level page table lookup */
+
+	sh2addl 	 t0,ptp,ptp
+	ldi		_PAGE_ACCESSED,t1
+	ldw		 0(ptp),pte
+	bb,>=,n          pte,_PAGE_PRESENT_BIT,nadtlb_check_flush_20
+
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
+
+	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
+	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
+	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
+	depdi		0,11,2,prot	/* If Gateway, Set PL2 to 0 */
+
+	/* Get rid of prot bits and convert to page addr for idtlbt */
+
+        extrd,s         pte,35,4,t0
+        depdi           0,63,12,pte     /* clear lower 12 bits */
+        addi,=          1,t0,0
+        extrd,u,*tr     pte,56,25,pte
+        extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
+        idtlbt          pte,prot
+
+	rfir
+	nop
+
+nadtlb_check_flush_20:
+	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
+
+	/* Insert a "flush only" translation */
+
+	depdi,z         7,7,3,prot
+	depdi           1,10,1,prot
+
+	/* Get rid of prot bits and convert to page addr for idtlbt */
+
+	depdi		0,63,12,pte
+	extrd,u         pte,56,32,pte
+	idtlbt          pte,prot
 
 	rfir
 	nop
 #endif
 
+nadtlb_emulate:
+
+	/*
+	 * Non access misses can be caused by fdc,fic,pdc,lpa,probe and
+	 * probei instructions. We don't want to fault for these
+	 * instructions (not only does it not make sense, it can cause
+	 * deadlocks, since some flushes are done with the mmap
+	 * semaphore held). If the translation doesn't exist, we can't
+	 * insert a translation, so have to emulate the side effects
+	 * of the instruction. Since we don't insert a translation
+	 * we can get a lot of faults during a flush loop, so it makes
+	 * sense to try to do it here with minimum overhead. We only
+	 * emulate fdc,fic & pdc instructions whose base and index
+	 * registers are not shadowed. We defer everything else to the
+	 * "slow" path.
+	 */
+
+	mfctl           %cr19,%r9 /* Get iir */
+	ldi             0x280,%r16
+	and             %r9,%r16,%r17
+	cmpb,<>,n       %r16,%r17,nadtlb_fault /* Not fdc,fic,pdc */
+	bb,>=,n         %r9,26,nadtlb_nullify  /* m bit not set, just nullify */
+	b,l             get_register,%r25
+	extrw,u         %r9,15,5,%r8           /* Get index register # */
+	CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
+	copy            %r1,%r24
+	b,l             get_register,%r25
+	extrw,u         %r9,10,5,%r8           /* Get base register # */
+	CMPIB=,n        -1,%r1,nadtlb_fault    /* have to use slow path */
+	b,l             set_register,%r25
+	add,l           %r1,%r24,%r1           /* doesn't affect c/b bits */
+
+nadtlb_nullify:
+	mfctl           %cr22,%r8              /* Get ipsw */
+	ldil            L%PSW_N,%r9
+	or              %r8,%r9,%r8            /* Set PSW_N */
+	mtctl           %r8,%cr22
+
+	rfir
+	nop
+
 #ifdef __LP64__
 itlb_miss_20w:
 
@@ -999,9 +1479,9 @@
 	 * on the gateway page which is in the kernel address space.
 	 */
 
-	extrd,u         spc,31,7,t1     /* adjust va */
+	extrd,u         spc,63,7,t1     /* adjust va */
 	depd            t1,31,7,va      /* adjust va */
-	depdi           0,31,7,spc      /* adjust space */
+	depdi           0,63,7,spc      /* adjust space */
 	cmpib,*=        0,spc,itlb_miss_kernel_20w
 	extrd,u         va,33,9,t1      /* Get pgd index */
 
@@ -1039,11 +1519,9 @@
 	and,*<>         t1,pte,%r0      /* test and nullify if already set */
 	std             t0,0(ptp)       /* write back pte */
 
-	copy            spc,prot        /* init prot with faulting space */
-	
-	depd		pte,8,7,prot
-	extrd,u,*=	pte,_PAGE_NO_CACHE_BIT+32,1,r0
-	depdi		1,12,1,prot
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
+
 	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
 	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
 	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
@@ -1053,7 +1531,7 @@
 
 	depdi		0,63,12,pte
 	extrd,u         pte,56,32,pte
-	iitlbt          %r16,%r17
+	iitlbt          pte,prot
 
 	rfir
 	nop
@@ -1070,14 +1548,14 @@
 	 * on the gateway page which is in the kernel address space.
 	 */
 
-	comib,=         0,spc,itlb_miss_kernel_11
+	cmpib,=         0,spc,itlb_miss_kernel_11
 	extru		va,9,10,t1	/* Get pgd index */
 
 	mfctl           %cr25,ptp	/* load user pgd */
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
-	comb,<>,n       t0,spc,itlb_fault /* forward */
+	cmpb,<>,n       t0,spc,itlb_fault /* forward */
 
 	/* First level page table lookup */
 
@@ -1100,8 +1578,8 @@
 	and,<>		t1,pte,%r0	/* test and nullify if already set */
 	stw		t0,0(ptp)	/* write back pte */
 
-	copy            spc,prot        /* init prot with faulting space */
-	dep		pte,8,7,prot
+	zdep            spc,30,15,prot  /* create prot id from space */
+	dep             pte,8,7,prot    /* add in prot bits from pte */
 
 	extru,=		pte,_PAGE_NO_CACHE_BIT,1,r0
 	depi		1,12,1,prot
@@ -1137,14 +1615,14 @@
 	 * on the gateway page which is in the kernel address space.
 	 */
 
-	comib,=         0,spc,itlb_miss_kernel_20
+	cmpib,=         0,spc,itlb_miss_kernel_20
 	extru		va,9,10,t1	/* Get pgd index */
 
 	mfctl           %cr25,ptp	/* load user pgd */
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
-	comb,<>,n       t0,spc,itlb_fault /* forward */
+	cmpb,<>,n       t0,spc,itlb_fault /* forward */
 
 	/* First level page table lookup */
 
@@ -1167,13 +1645,9 @@
 	and,<>		t1,pte,%r0	/* test and nullify if already set */
 	stw		t0,0(ptp)	/* write back pte */
 
-	copy            spc,prot        /* init prot with faulting space */
-	
-	.level 2.0
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
 
-	depd		pte,8,7,prot
-	extrd,u,*=	pte,_PAGE_NO_CACHE_BIT+32,1,r0
-	depdi		1,12,1,prot
 	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
 	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
 	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
@@ -1181,10 +1655,12 @@
 
 	/* Get rid of prot bits and convert to page addr for iitlbt */
 
-	depdi		0,63,12,pte
-	extrd,u		pte,56,25,pte
-	iitlbt          %r16,%r17
-	.level		1.1
+        extrd,s         pte,35,4,t0 
+        depdi           0,63,12,pte     /* clear lower 12 bits */
+        addi,=          1,t0,0
+        extrd,u,*tr     pte,56,25,pte 
+        extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
+	iitlbt          pte,prot
 
 	rfir
 	nop
@@ -1198,11 +1674,10 @@
 #ifdef __LP64__
 
 dbit_trap_20w:
-
-	extrd,u         spc,31,7,t1     /* adjust va */
+	extrd,u         spc,63,7,t1     /* adjust va */
 	depd            t1,31,7,va      /* adjust va */
 	depdi           0,1,2,va        /* adjust va */
-	depdi           0,31,7,spc      /* adjust space */
+	depdi           0,63,7,spc      /* adjust space */
 	mfctl           %cr25,ptp	/* Assume user space miss */
 	or,*<>          %r0,spc,%r0     /* If it is user space, nullify */
 	mfctl           %cr24,ptp	/* Load kernel pgd instead */
@@ -1210,7 +1685,7 @@
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,*=           %r0,t0,%r0      /* If kernel, nullify following test */
-	comb,<>,n       t0,spc,dbit_fault /* forward */
+	cmpb,*<>,n       t0,spc,dbit_fault /* forward */
 
 	/* First level page table lookup */
 
@@ -1229,6 +1704,18 @@
 	/* Third level page table lookup */
 
 	shladd           t0,3,ptp,ptp
+#ifdef CONFIG_SMP
+	CMPIB=,n        0,spc,dbit_nolock_20w
+	ldil            L%PA(pa_dbit_lock),t0
+	ldo             R%PA(pa_dbit_lock)(t0),t0
+
+dbit_spin_20w:
+	ldcw            0(t0),t1
+	cmpib,=         0,t1,dbit_spin_20w
+	nop
+
+dbit_nolock_20w:
+#endif
 	ldi		(_PAGE_ACCESSED|_PAGE_DIRTY),t1
 	ldd              0(ptp),pte
 	bb,>=,n          pte,_PAGE_PRESENT_BIT,dbit_fault
@@ -1238,11 +1725,9 @@
 	or		t1,pte,pte
 	std             pte,0(ptp)      /* write back pte */
 
-	copy            spc,prot	/* init prot with faulting space */
-	
-	depd		pte,8,7,prot
-	extrd,u,*=	pte,_PAGE_NO_CACHE_BIT+32,1,r0
-	depdi		1,12,1,prot
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
+
 	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
 	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
 	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
@@ -1251,8 +1736,15 @@
 	/* Get rid of prot bits and convert to page addr for idtlbt */
 
 	depdi		0,63,12,pte
-	extrd,u         pte,56,32,pte
-	idtlbt		%r16,%r17
+	extrd,u         pte,56,52,pte
+	idtlbt          pte,prot
+#ifdef CONFIG_SMP
+	CMPIB=,n        0,spc,dbit_nounlock_20w
+	ldi             1,t1
+	stw             t1,0(t0)
+
+dbit_nounlock_20w:
+#endif
 
 	rfir
 	nop
@@ -1266,7 +1758,7 @@
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
-	comb,<>,n       t0,spc,dbit_fault /* forward */
+	cmpb,<>,n       t0,spc,dbit_fault /* forward */
 
 	/* First level page table lookup */
 
@@ -1278,6 +1770,18 @@
 	/* Second level page table lookup */
 
 	sh2addl 	 t0,ptp,ptp
+#ifdef CONFIG_SMP
+	CMPIB=,n        0,spc,dbit_nolock_11
+	ldil            L%PA(pa_dbit_lock),t0
+	ldo             R%PA(pa_dbit_lock)(t0),t0
+
+dbit_spin_11:
+	ldcw            0(t0),t1
+	cmpib,=         0,t1,dbit_spin_11
+	nop
+
+dbit_nolock_11:
+#endif
 	ldi		(_PAGE_ACCESSED|_PAGE_DIRTY),t1
 	ldw		 0(ptp),pte
 	bb,>=,n 	 pte,_PAGE_PRESENT_BIT,dbit_fault
@@ -1287,8 +1791,8 @@
 	or		t1,pte,pte
 	stw		pte,0(ptp)	/* write back pte */
 
-	copy            spc,prot        /* init prot with faulting space */
-	dep		pte,8,7,prot
+	zdep            spc,30,15,prot  /* create prot id from space */
+	dep             pte,8,7,prot    /* add in prot bits from pte */
 
 	extru,=		pte,_PAGE_NO_CACHE_BIT,1,r0
 	depi		1,12,1,prot
@@ -1302,13 +1806,20 @@
 	depi		0,31,12,pte
 	extru		pte,24,25,pte
 
-	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+	mfsp            %sr1,t1  /* Save sr1 so we can use it in tlb inserts */
 	mtsp		spc,%sr1
 
 	idtlba		pte,(%sr1,va)
 	idtlbp		prot,(%sr1,va)
 
-	mtsp		t0, %sr1     /* Restore sr1 */
+	mtsp            t1, %sr1     /* Restore sr1 */
+#ifdef CONFIG_SMP
+	CMPIB=,n        0,spc,dbit_nounlock_11
+	ldi             1,t1
+	stw             t1,0(t0)
+
+dbit_nounlock_11:
+#endif
 
 	rfir
 	nop
@@ -1321,7 +1832,7 @@
 
 	mfsp            %sr7,t0		/* Get current space */
 	or,=            %r0,t0,%r0	/* If kernel, nullify following test */
-	comb,<>,n       t0,spc,dbit_fault /* forward */
+	cmpb,<>,n       t0,spc,dbit_fault /* forward */
 
 	/* First level page table lookup */
 
@@ -1333,6 +1844,18 @@
 	/* Second level page table lookup */
 
 	sh2addl 	 t0,ptp,ptp
+#ifdef CONFIG_SMP
+	CMPIB=,n        0,spc,dbit_nolock_20
+	ldil            L%PA(pa_dbit_lock),t0
+	ldo             R%PA(pa_dbit_lock)(t0),t0
+
+dbit_spin_20:
+	ldcw            0(t0),t1
+	cmpib,=         0,t1,dbit_spin_20
+	nop
+
+dbit_nolock_20:
+#endif
 	ldi		(_PAGE_ACCESSED|_PAGE_DIRTY),t1
 	ldw		 0(ptp),pte
 	bb,>=,n 	 pte,_PAGE_PRESENT_BIT,dbit_fault
@@ -1342,25 +1865,28 @@
 	or		t1,pte,pte
 	stw		pte,0(ptp)	/* write back pte */
 
-	copy            spc,prot        /* init prot with faulting space */
-	
-	.level 2.0
+	space_to_prot   spc prot        /* create prot id from space */
+	depd            pte,8,7,prot    /* add in prot bits from pte */
 
-	depd		pte,8,7,prot
-	extrd,u,*=	pte,_PAGE_NO_CACHE_BIT+32,1,r0
-	depdi		1,12,1,prot
 	extrd,u,*=      pte,_PAGE_USER_BIT+32,1,r0
 	depdi		7,11,3,prot   /* Set for user space (1 rsvd for read) */
 	extrd,u,*= 	pte,_PAGE_GATEWAY_BIT+32,1,r0
 	depdi		0,11,2,prot	/* If Gateway, Set PL2 to 0 */
 
-	/* Get rid of prot bits and convert to page addr for idtlbt */
+        extrd,s         pte,35,4,t0 
+        depdi           0,63,12,pte     /* clear lower 12 bits */
+        addi,=          1,t0,0
+        extrd,u,*tr     pte,56,25,pte 
+        extrd,s         pte,56,25,pte   /* bit 31:8 >> 8  */
+        idtlbt          pte,prot
 
-	depdi		0,63,12,pte
-	extrd,u		pte,56,25,pte
-	idtlbt		%r16,%r17
+#ifdef CONFIG_SMP
+	CMPIB=,n        0,spc,dbit_nounlock_20
+	ldi             1,t1
+	stw             t1,0(t0)
 
-	.level		1.1
+dbit_nounlock_20:
+#endif
 
 	rfir
 	nop
@@ -1369,50 +1895,24 @@
 	.import handle_interruption,code
 
 kernel_bad_space:
-	b		tlb_fault
-	ldi		31,%r1	/* Use an unused code */
+	b               intr_save
+	ldi             31,%r8  /* Use an unused code */
 
 dbit_fault:
-	b		tlb_fault
-	ldi		20,%r1
+	b               intr_save
+	ldi             20,%r8
 
 itlb_fault:
-	b		tlb_fault
-	ldi		6,%r1
-
-dtlb_fault:
-	ldi		15,%r1
+	b               intr_save
+	ldi             6,%r8
 
-	/* Fall Through */
+nadtlb_fault:
+	b               intr_save
+	ldi             17,%r8
 
-tlb_fault:
-	mtctl		%r1,%cr29
-	mtctl		%r29,%cr31
-
-	get_stack
-	save_specials	%r29		/* Note this saves a trashed r1 */
-
-	SAVE_CR		(%cr20, PT_ISR(%r29))
-	SAVE_CR		(%cr21, PT_IOR(%r29))
-
-	virt_map	rfir
-
-	STREG		%r1,PT_GR1(%r29)	/* save good value after rfir */
-
-	save_general	%r29
-
-	ldo	PT_FR0(%r29), %r25
-	save_fp		%r25
-	
-	loadgp
-
-	copy		%r29, %r25
-
-	bl		handle_interruption, %r2
-	copy		%r29, %r16
-
-	b		intr_return
-	nop
+dtlb_fault:
+	b               intr_save
+	ldi             15,%r8
 
 	/* Register saving semantics for system calls:
 
@@ -1475,21 +1975,23 @@
 	.endm
 
 	.export sys_fork_wrapper
+	.export child_return
 sys_fork_wrapper:
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1	/* get pt regs */
 	reg_save %r1
+	mfctl	%cr27, %r3
+	STREG	%r3, PT_CR27(%r1)
 
 	STREG	%r2,-RP_OFFSET(%r30)
 	ldo	FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
 
 	/* These are call-clobbered registers and therefore
 	   also syscall-clobbered (we hope). */
 	STREG	%r2,PT_GR19(%r1)	/* save for child */
-	STREG	%r30,PT_GR20(%r1)
-	ldil	L%child_return, %r3
-	ldo	R%child_return(%r3), %r3
-	LDIL_FIXUP(%r3)
-	STREG	%r3,PT_GR21(%r1)	/* save for child */
+	STREG	%r30,PT_GR21(%r1)
 
 	LDREG	PT_GR30(%r1),%r25
 	copy	%r1,%r24
@@ -1501,14 +2003,21 @@
 	ldo	-FRAME_SIZE(%r30),%r30		/* get the stackframe */
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1    /* get pt regs */
 
+	LDREG	PT_CR27(%r1), %r3
+	mtctl	%r3, %cr27
 	reg_restore %r1
 
+	/* strace expects syscall # to be preserved in r20 */
+	ldi	__NR_fork,%r20
 	bv %r0(%r2)
-	nop
+	STREG	%r20,PT_GR20(%r1)
 
 	/* Set the return value for the child */
 child_return:
-	LDREG	TASK_PT_GR19-TASK_SZ_ALGN-128(%r30),%r2
+	bl	schedule_tail, %r2
+	nop
+
+	LDREG	TASK_PT_GR19-TASK_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30),%r2
 	b	wrapper_exit
 	copy	%r0,%r28
 
@@ -1517,35 +2026,38 @@
 sys_clone_wrapper:
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1	/* get pt regs */
 	reg_save %r1
+	mfctl	%cr27, %r3
+	STREG	%r3, PT_CR27(%r1)
 
 	STREG	%r2,-RP_OFFSET(%r30)
 	ldo	FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
 
-	STREG	%r30,PT_GR20(%r1)
-	ldil	L%child_return,%r3
-	ldo	R%child_return(%r3),%r3
-	LDIL_FIXUP(%r3)
-
+	STREG	%r2,PT_GR19(%r1)	/* save for child */
+	STREG	%r30,PT_GR21(%r1)
 	bl	sys_clone,%r2
-	STREG	%r3,PT_GR21(%r1)	/* save for child */
+	copy	%r1,%r24
 
 	b	wrapper_exit
 	LDREG	-RP_OFFSET-FRAME_SIZE(%r30),%r2
 
-
 	.export sys_vfork_wrapper
 sys_vfork_wrapper:
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1	/* get pt regs */
 	reg_save %r1
+	mfctl	%cr27, %r3
+	STREG	%r3, PT_CR27(%r1)
 
 	STREG	%r2,-RP_OFFSET(%r30)
 	ldo	FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
 
-	STREG	%r30,PT_GR20(%r1)
-	ldil	L%child_return,%r3
-	ldo	R%child_return(%r3),%r3
-	LDIL_FIXUP(%r3)
-	STREG	%r3,PT_GR21(%r1)	/* save for child */
+	STREG	%r2,PT_GR19(%r1)	/* save for child */
+	STREG	%r30,PT_GR21(%r1)
 
 	bl	sys_vfork,%r2
 	copy	%r1,%r26
@@ -1567,6 +2079,9 @@
 
 	STREG %r2,-RP_OFFSET(%r30)
 	ldo FRAME_SIZE(%r30),%r30
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#endif
 	bl \execve,%r2
 	copy %r1,%arg0
 
@@ -1576,7 +2091,7 @@
 	/* If exec succeeded we need to load the args */
 
 	ldo -1024(%r0),%r1
-	comb,>>= %r28,%r1,error_\execve
+	cmpb,>>= %r28,%r1,error_\execve
 	copy %r2,%r19
 
 error_\execve:
@@ -1603,8 +2118,14 @@
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r26
 	/* Don't save regs, we are going to restore them from sigcontext. */
 	STREG	%r2, -RP_OFFSET(%r30)
+#ifdef __LP64__
+	ldo	FRAME_SIZE(%r30), %r30
+	bl	sys_rt_sigreturn,%r2
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#else
 	bl	sys_rt_sigreturn,%r2
 	ldo	FRAME_SIZE(%r30), %r30
+#endif
 
 	ldo	-FRAME_SIZE(%r30), %r30
 	LDREG	-RP_OFFSET(%r30), %r2
@@ -1625,22 +2146,50 @@
 	/* Get the user stack pointer */
 	LDREG	-TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24
 	STREG	%r2, -RP_OFFSET(%r30)
+#ifdef __LP64__
+	ldo	FRAME_SIZE(%r30), %r30
+	bl	do_sigaltstack,%r2
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#else
 	bl	do_sigaltstack,%r2
 	ldo	FRAME_SIZE(%r30), %r30
+#endif
 
 	ldo	-FRAME_SIZE(%r30), %r30
 	LDREG	-RP_OFFSET(%r30), %r2
 	bv	%r0(%r2)
 	nop
 
+#ifdef __LP64__
+	.export sys32_sigaltstack_wrapper
+sys32_sigaltstack_wrapper:
+	/* Get the user stack pointer */
+	LDREG	-TASK_SZ_ALGN-FRAME_SIZE+TASK_PT_GR30(%r30), %r24
+	STREG	%r2, -RP_OFFSET(%r30)
+	ldo	FRAME_SIZE(%r30), %r30
+	bl	do_sigaltstack32,%r2
+	ldo	-16(%r30),%r29		/* Reference param save area */
+
+	ldo	-FRAME_SIZE(%r30), %r30
+	LDREG	-RP_OFFSET(%r30), %r2
+	bv	%r0(%r2)
+	nop
+#endif
+
 	.export sys_rt_sigsuspend_wrapper
 sys_rt_sigsuspend_wrapper:
 	ldo	TASK_REGS-TASK_SZ_ALGN-FRAME_SIZE(%r30), %r24
 	reg_save %r24
 
 	STREG	%r2, -RP_OFFSET(%r30)
+#ifdef __LP64__
+	ldo	FRAME_SIZE(%r30), %r30
+	bl	sys_rt_sigsuspend,%r2
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#else
 	bl	sys_rt_sigsuspend,%r2
 	ldo	FRAME_SIZE(%r30), %r30
+#endif
 
 	ldo	-FRAME_SIZE(%r30), %r30
 	LDREG	-RP_OFFSET(%r30), %r2
@@ -1658,66 +2207,80 @@
 	   values. */
 	/* NOTE: Not all syscalls exit this way.  rt_sigreturn will exit
 	 * via syscall_exit_rfi if the signal was received while the process
-	 * was running.  All traced processes will probably exit via
-	 * syscall_exit_rfi in the future.
+	 * was running.
 	 */
 
 	/* save return value now */
 
 	STREG     %r28,TASK_PT_GR28-TASK_SZ_ALGN-FRAME_SIZE(%r30)
 
+	/* Save other hpux returns if personality is PER_HPUX */
+
+#define PER_HPUX 0xe /* <linux/personality.h> cannot be easily included */
+
+	LDREG     TASK_PERSONALITY-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19
+	CMPIB<>,n PER_HPUX,%r19,1f
+	STREG     %r22,TASK_PT_GR22-TASK_SZ_ALGN-FRAME_SIZE(%r30)
+	STREG     %r29,TASK_PT_GR29-TASK_SZ_ALGN-FRAME_SIZE(%r30)
+1:
+
+	/* Seems to me that dp could be wrong here, if the syscall involved
+	 * calling a module, and nothing got round to restoring dp on return.
+	 */
+	loadgp
+
 syscall_check_bh:
 
-/* #ifdef NOTNOW */
 	/* Check for software interrupts */
 
 	.import irq_stat,data
 
 	ldil    L%irq_stat,%r19
 	ldo     R%irq_stat(%r19),%r19
-	LDIL_FIXUP(%r19)
 
 #ifdef CONFIG_SMP
 	/* sched.h: int processor */
-	ldw     TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r20 /* get cpu # */
-#if (IRQSTAT_SZ == 32)
-	dep     %r20,26,27,%r20 /* shift left 5 bits */
-#else
-#error IRQSTAT_SZ changed, fix dep
-#endif /* IRQSTAT_SZ */
-	add     %r19,%r20,%r19
-#endif /* CONFIG_SMP */
+	/* %r26 is used as scratch register to index into irq_stat[] */
+	ldw     TASK_PROCESSOR-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r26 /* cpu # */
 
-	ldw     IRQSTAT_SI_ACTIVE(%r19),%r20	/* hardirq.h: unsigned int */
-	ldw     IRQSTAT_SI_MASK(%r19),%r19	/* hardirq.h: unsigned int */
-	and     %r19,%r20,%r20
-	comib,<>,n 0,%r20,syscall_do_softirq /* forward */
-/* #endif */
+	/* shift left ____cacheline_aligned (aka L1_CACHE_BYTES) bits */
+#ifdef __LP64__
+	shld	%r26, 6, %r20
+#else
+	shlw	%r26, 5, %r20
+#endif
+	add     %r19,%r20,%r19	/* now have &irq_stat[smp_processor_id()] */
+#endif /* CONFIG_SMP */
 
+	LDREG   IRQSTAT_SIRQ_PEND(%r19),%r20    /* hardirq.h: unsigned long */
+	cmpib,<>,n 0,%r20,syscall_do_softirq /* forward */
 
 syscall_check_resched:
 
 	/* check for reschedule */
 
 	LDREG  TASK_NEED_RESCHED-TASK_SZ_ALGN-FRAME_SIZE(%r30),%r19	/* long */
-	comib,<>,n 0,%r19,syscall_do_resched /* forward */
+	CMPIB<>,n 0,%r19,syscall_do_resched /* forward */
 
 syscall_check_sig:
 	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1         /* get task ptr */
 	/* check for pending signals */
 	ldw     TASK_SIGPENDING(%r1),%r19
-	comib,<>,n 0,%r19,syscall_do_signal  /* forward */
+	cmpib,<>,n 0,%r19,syscall_do_signal  /* forward */
 
 syscall_restore:
-	/* disable interrupts while dicking with the kernel stack, */
-	/* or life can become unpleasant */
-	rsm	PSW_SM_I, %r20
 	LDREG	TASK_PTRACE(%r1), %r19		/* Are we being ptraced? */
 	bb,<,n	%r19,31,syscall_restore_rfi
-	LDREG	TASK_PT_GR20(%r1),%r19
-	mtctl	%r19, %cr27
+
+	ldo	TASK_PT_FR31(%r1),%r19		   /* reload fpregs */
+	rest_fp	%r19
+
+	LDREG	TASK_PT_SAR(%r1),%r19		   /* restore SAR */
+	mtsar	%r19
 
 	LDREG	TASK_PT_GR2(%r1),%r2		   /* restore user rp */
+	LDREG	TASK_PT_GR19(%r1),%r19
+	LDREG   TASK_PT_GR20(%r1),%r20
 	LDREG	TASK_PT_GR21(%r1),%r21
 	LDREG	TASK_PT_GR22(%r1),%r22
 	LDREG	TASK_PT_GR23(%r1),%r23
@@ -1727,43 +2290,31 @@
 	LDREG	TASK_PT_GR27(%r1),%r27	   /* restore user dp */
 	LDREG	TASK_PT_GR28(%r1),%r28	   /* syscall return value */
 	LDREG	TASK_PT_GR29(%r1),%r29
-	LDREG	TASK_PT_GR30(%r1),%r30	   /* restore user sp */
 	LDREG	TASK_PT_GR31(%r1),%r31	   /* restore syscall rp */
-	ldo	TASK_PT_FR31(%r1),%r19		   /* reload fpregs */
-	rest_fp	%r19
-	LDREG	TASK_PT_SAR(%r1),%r19		   /* restore SAR */
-	mtsar	%r19
-	LDREG	TASK_PT_GR19(%r1),%r19
 
-	mtctl	%r1,%cr30			   /* intrhandler okay. */
+	rsm     PSW_SM_I, %r0
+	LDREG   TASK_PT_GR30(%r1),%r30             /* restore user sp */
 	mfsp	%sr3,%r1			   /* Get users space id */
+	mtsp    %r1,%sr7                           /* Restore sr7 */
+	ssm     PSW_SM_I, %r0
 	mtsp	%r1,%sr4			   /* Restore sr4 */
 	mtsp	%r1,%sr5			   /* Restore sr5 */
 	mtsp	%r1,%sr6			   /* Restore sr6 */
 
 	depi	3,31,2,%r31			   /* ensure return to user mode. */
 
-	mtsm	%r20				   /* restore irq state  */
-	mfctl	%cr27,%r20
-	
-	/*
-	 * Due to a dependency in the tlb miss handlers on sr7, it
-	 * is essential that sr7 get set in the delay slot.
-	 */
-
 #ifdef __LP64__
-
-	/* Note the be (and mtsp) is executed in narrow mode. This is OK
-	 * for 32 bit processes, but won't work once we support 64 bit
-	 * processes.
+	/* Since we are returning to a 32 bit user process, we always
+	 * clear the W bit. This means that the be (and mtsp) gets
+	 * executed in narrow mode, but that is OK, since we are
+	 * returning to a 32 bit process. When we support 64 bit processes
+	 * we won't clear the W bit, so the be will run in wide mode.
 	 */
 
-	rsm	PSW_SM_W, %r0
 	be	0(%sr3,%r31)			   /* return to user space */
-	mtsp	%r1,%sr7			   /* Restore sr7 */
+	rsm	PSW_SM_W, %r0
 #else
-	be	0(%sr3,%r31)			   /* return to user space */
-	mtsp	%r1,%sr7			   /* Restore sr7 */
+	be,n    0(%sr3,%r31)                       /* return to user space */
 #endif
 
 	/* We have to return via an RFI, so that PSW T and R bits can be set
@@ -1774,43 +2325,52 @@
 syscall_restore_rfi:
 	ldo	-1(%r0),%r2			   /* Set recovery cntr to -1 */
 	mtctl	%r2,%cr0			   /*   for immediate trap */
-	copy	%r0,%r2				   /* Create a reasonable PSW */
+	LDREG	TASK_PT_PSW(%r1),%r2		   /* Get old PSW */
+	ldi	0x0b,%r20			   /* Create new PSW */
+	depi	-1,13,1,%r20			   /* C, Q, D, and I bits */
+	bb,>=,n	%r19,15,try_tbit		   /* PT_SINGLESTEP */
+	depi	-1,27,1,%r20			   /* R bit */
+try_tbit:
+	bb,>=,n	%r19,14,psw_setup		   /* PT_BLOCKSTEP, see ptrace.c */
+	depi	-1,7,1,%r20			   /* T bit */
+psw_setup:
+	STREG	%r20,TASK_PT_PSW(%r1)
+
+	/* Always store space registers, since sr3 can be changed (e.g. fork) */
+
+	mfsp    %sr3,%r25
+	STREG   %r25,TASK_PT_SR3(%r1)
+	STREG   %r25,TASK_PT_SR4(%r1)
+	STREG   %r25,TASK_PT_SR5(%r1)
+	STREG   %r25,TASK_PT_SR6(%r1)
+	STREG   %r25,TASK_PT_SR7(%r1)
+	STREG   %r25,TASK_PT_IASQ0(%r1)
+	STREG   %r25,TASK_PT_IASQ1(%r1)
+
 	/* XXX W bit??? */
-	depi	-1,13,1,%r2
-	depi	-1,28,1,%r2
-	depi	-1,30,1,%r2
-	depi	-1,31,1,%r2
-	bb,<,n	%r19,15,set_rbit		   /* PT_SINGLESTEP */
-	bb,>=,n	%r19,14,set_nobit		   /* PT_BLOCKSTEP, see ptrace.c */
-set_tbit:
-	depi	-1,7,1,%r2
-	b,n	set_nobit
-set_rbit:
-	depi	-1,27,1,%r2
-set_nobit:
-	STREG	%r2,TASK_PT_PSW(%r1)
-	STREG	%r1,TASK_PT_CR30(%r1)
+	/* Now if old D bit is clear, it means we didn't save all registers
+	 * on syscall entry, so do that now.  This only happens on TRACEME
+	 * calls, or if someone attached to us while we were on a syscall.
+	 * We could make this more efficient by not saving r3-r18, but
+	 * then we wouldn't be able to use the common intr_restore path.
+	 * It is only for traced processes anyway, so performance is not
+	 * an issue.
+	 */
+	bb,<	%r2,30,pt_regs_ok		   /* Branch if D set */
+	ldo	TASK_REGS(%r1),%r25
+	reg_save %r25				   /* Save r3 to r18 */
 	mfsp	%sr0,%r2
 	STREG	%r2,TASK_PT_SR0(%r1)
 	mfsp	%sr1,%r2
 	STREG	%r2,TASK_PT_SR1(%r1)
 	mfsp	%sr2,%r2
 	STREG	%r2,TASK_PT_SR2(%r1)
-	mfsp	%sr3,%r2
-	STREG	%r2,TASK_PT_SR3(%r1)
-	STREG	%r2,TASK_PT_SR4(%r1)
-	STREG	%r2,TASK_PT_SR5(%r1)
-	STREG	%r2,TASK_PT_SR6(%r1)
-	STREG	%r2,TASK_PT_SR7(%r1)
-	STREG	%r2,TASK_PT_IASQ0(%r1)
-	STREG	%r2,TASK_PT_IASQ1(%r1)
+pt_regs_ok:
 	LDREG	TASK_PT_GR31(%r1),%r2
 	depi	3,31,2,%r2			   /* ensure return to user mode. */
 	STREG	%r2,TASK_PT_IAOQ0(%r1)
 	ldo	4(%r2),%r2
 	STREG	%r2,TASK_PT_IAOQ1(%r1)
-	ldo	TASK_REGS(%r1),%r25
-	reg_save %r25				   /* Save r3 to r18 */
 	copy	%r25,%r16
 	b	intr_restore
 	nop
@@ -1825,7 +2385,11 @@
 	.import schedule,code
 syscall_do_resched:
 	bl	schedule,%r2
+#ifdef __LP64__
+	ldo	-16(%r30),%r29		/* Reference param save area */
+#else
 	nop
+#endif
 	b       syscall_check_bh  /* if resched, we start over again */
 	nop
 
@@ -1840,6 +2404,9 @@
 
 	ldi	1, %r24				/* unsigned long in_syscall */
 
+#ifdef __LP64__
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#endif
 	bl	do_signal,%r2
 	copy	%r0, %r26			/* sigset_t *oldset = NULL */
 
@@ -1849,19 +2416,155 @@
 
 	b,n     syscall_restore
 
-#ifdef __LP64__
-unimplemented_64bitirq:
-	ssm PSW_SM_Q+PSW_SM_I, %r0
-	/* indicate that we had an interrupt */
-	ldi	0x77, %r28
-	ldi	0x77, %r29
-	/* save interrupt registers in GRs for diagnosis */
-	mfctl %cr17, %r17
-	mfctl %cr18, %r18
-	mfctl %cr19, %r19
-	mfctl %cr20, %r20
-	mfctl %cr21, %r21
-	mfctl %cr22, %r22
-	b,n .
-	nop
-#endif
+	/*
+	 * get_register is used by the non access tlb miss handlers to
+	 * copy the value of the general register specified in r8 into
+	 * r1. This routine can't be used for shadowed registers, since
+	 * the rfir will restore the original value. So, for the shadowed
+	 * registers we put a -1 into r1 to indicate that the register
+	 * should not be used (the register being copied could also have
+	 * a -1 in it, but that is OK, it just means that we will have
+	 * to use the slow path instead).
+	 */
+
+get_register:
+	blr     %r8,%r0
+	nop
+	bv      %r0(%r25)    /* r0 */
+	copy    %r0,%r1
+	bv      %r0(%r25)    /* r1 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r2 */
+	copy    %r2,%r1
+	bv      %r0(%r25)    /* r3 */
+	copy    %r3,%r1
+	bv      %r0(%r25)    /* r4 */
+	copy    %r4,%r1
+	bv      %r0(%r25)    /* r5 */
+	copy    %r5,%r1
+	bv      %r0(%r25)    /* r6 */
+	copy    %r6,%r1
+	bv      %r0(%r25)    /* r7 */
+	copy    %r7,%r1
+	bv      %r0(%r25)    /* r8 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r9 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r10 */
+	copy    %r10,%r1
+	bv      %r0(%r25)    /* r11 */
+	copy    %r11,%r1
+	bv      %r0(%r25)    /* r12 */
+	copy    %r12,%r1
+	bv      %r0(%r25)    /* r13 */
+	copy    %r13,%r1
+	bv      %r0(%r25)    /* r14 */
+	copy    %r14,%r1
+	bv      %r0(%r25)    /* r15 */
+	copy    %r15,%r1
+	bv      %r0(%r25)    /* r16 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r17 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r18 */
+	copy    %r18,%r1
+	bv      %r0(%r25)    /* r19 */
+	copy    %r19,%r1
+	bv      %r0(%r25)    /* r20 */
+	copy    %r20,%r1
+	bv      %r0(%r25)    /* r21 */
+	copy    %r21,%r1
+	bv      %r0(%r25)    /* r22 */
+	copy    %r22,%r1
+	bv      %r0(%r25)    /* r23 */
+	copy    %r23,%r1
+	bv      %r0(%r25)    /* r24 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r25 - shadowed */
+	ldi     -1,%r1
+	bv      %r0(%r25)    /* r26 */
+	copy    %r26,%r1
+	bv      %r0(%r25)    /* r27 */
+	copy    %r27,%r1
+	bv      %r0(%r25)    /* r28 */
+	copy    %r28,%r1
+	bv      %r0(%r25)    /* r29 */
+	copy    %r29,%r1
+	bv      %r0(%r25)    /* r30 */
+	copy    %r30,%r1
+	bv      %r0(%r25)    /* r31 */
+	copy    %r31,%r1
+
+	/*
+	 * set_register is used by the non access tlb miss handlers to
+	 * copy the value of r1 into the general register specified in
+	 * r8.
+	 */
+
+set_register:
+	blr     %r8,%r0
+	nop
+	bv      %r0(%r25)    /* r0 (silly, but it is a place holder) */
+	copy    %r1,%r0
+	bv      %r0(%r25)    /* r1 */
+	copy    %r1,%r1
+	bv      %r0(%r25)    /* r2 */
+	copy    %r1,%r2
+	bv      %r0(%r25)    /* r3 */
+	copy    %r1,%r3
+	bv      %r0(%r25)    /* r4 */
+	copy    %r1,%r4
+	bv      %r0(%r25)    /* r5 */
+	copy    %r1,%r5
+	bv      %r0(%r25)    /* r6 */
+	copy    %r1,%r6
+	bv      %r0(%r25)    /* r7 */
+	copy    %r1,%r7
+	bv      %r0(%r25)    /* r8 */
+	copy    %r1,%r8
+	bv      %r0(%r25)    /* r9 */
+	copy    %r1,%r9
+	bv      %r0(%r25)    /* r10 */
+	copy    %r1,%r10
+	bv      %r0(%r25)    /* r11 */
+	copy    %r1,%r11
+	bv      %r0(%r25)    /* r12 */
+	copy    %r1,%r12
+	bv      %r0(%r25)    /* r13 */
+	copy    %r1,%r13
+	bv      %r0(%r25)    /* r14 */
+	copy    %r1,%r14
+	bv      %r0(%r25)    /* r15 */
+	copy    %r1,%r15
+	bv      %r0(%r25)    /* r16 */
+	copy    %r1,%r16
+	bv      %r0(%r25)    /* r17 */
+	copy    %r1,%r17
+	bv      %r0(%r25)    /* r18 */
+	copy    %r1,%r18
+	bv      %r0(%r25)    /* r19 */
+	copy    %r1,%r19
+	bv      %r0(%r25)    /* r20 */
+	copy    %r1,%r20
+	bv      %r0(%r25)    /* r21 */
+	copy    %r1,%r21
+	bv      %r0(%r25)    /* r22 */
+	copy    %r1,%r22
+	bv      %r0(%r25)    /* r23 */
+	copy    %r1,%r23
+	bv      %r0(%r25)    /* r24 */
+	copy    %r1,%r24
+	bv      %r0(%r25)    /* r25 */
+	copy    %r1,%r25
+	bv      %r0(%r25)    /* r26 */
+	copy    %r1,%r26
+	bv      %r0(%r25)    /* r27 */
+	copy    %r1,%r27
+	bv      %r0(%r25)    /* r28 */
+	copy    %r1,%r28
+	bv      %r0(%r25)    /* r29 */
+	copy    %r1,%r29
+	bv      %r0(%r25)    /* r30 */
+	copy    %r1,%r30
+	bv      %r0(%r25)    /* r31 */
+	copy    %r1,%r31
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/firmware.c linux/arch/parisc/kernel/firmware.c
--- linux.orig/arch/parisc/kernel/firmware.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/firmware.c	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,1111 @@
+/* arch/parisc/kernel/pdc.c  - safe pdc access routines
+ *
+ * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
+ * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
+ *
+ * only these routines should be used out of the real kernel (i.e. everything
+ * using virtual addresses) for obvious reasons */
+
+/*	I think it would be in everyone's best interest to follow this
+ *	guidelines when writing PDC wrappers:
+ *
+ *	 - the name of the pdc wrapper should match one of the macros
+ *	   used for the first two arguments
+ *	 - don't use caps for random parts of the name
+ *	 - use the static PDC result buffers and "copyout" to structs
+ *	   supplied by the caller to encapsulate alignment restrictions
+ *	 - hold pdc_lock while in PDC or using static result buffers
+ *	 - use __pa() to convert virtual (kernel) pointers to physical
+ *	   ones.
+ *	 - the name of the struct used for pdc return values should equal
+ *	   one of the macros used for the first two arguments to the
+ *	   corresponding PDC call
+ *	 - keep the order of arguments
+ *	 - don't be smart (setting trailing NUL bytes for strings, return
+ *	   something useful even if the call failed) unless you are sure
+ *	   it's not going to affect functionality or performance
+ *
+ *	Example:
+ *	int pdc_cache_info(struct pdc_cache_info *cache_info )
+ *	{
+ *		int retval;
+ *
+ *		spin_lock_irq(&pdc_lock);
+ *		retval = mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
+ *		convert_to_wide(pdc_result);
+ *		memcpy(cache_info, pdc_result, sizeof(*cache_info));
+ *		spin_unlock_irq(&pdc_lock);
+ *
+ *		return retval;
+ *	}
+ *					prumpf	991016	
+ */
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/system.h>
+#include <asm/processor.h>	/* for boot_cpu_data */
+
+#include <stdarg.h>
+
+static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long pdc_result[32] __attribute__ ((aligned (8)));
+static unsigned long pdc_result2[32] __attribute__ ((aligned (8)));
+
+/* on all currently-supported platforms, IODC I/O calls are always
+ * 32-bit calls, and MEM_PDC calls are always the same width as the OS.
+ * This means Cxxx boxes can't run wide kernels right now. -PB
+ *
+ * CONFIG_PDC_NARROW has been added to allow 64-bit kernels to run on
+ * systems with 32-bit MEM_PDC calls. This will allow wide kernels to
+ * run on Cxxx boxes now. -RB
+ *
+ * Note that some PAT boxes may have 64-bit IODC I/O...
+ */
+
+#ifdef __LP64__
+static long real64_call(unsigned long function, ...);
+#endif
+static long real32_call(unsigned long function, ...);
+
+#if defined(__LP64__) && ! defined(CONFIG_PDC_NARROW)
+#define MEM_PDC (unsigned long)(PAGE0->mem_pdc_hi) << 32 | PAGE0->mem_pdc
+#   define mem_pdc_call(args...) real64_call(MEM_PDC, args)
+#else
+#define MEM_PDC (unsigned long)PAGE0->mem_pdc
+#   define mem_pdc_call(args...) real32_call(MEM_PDC, args)
+#endif
+
+
+/**
+ * f_extend - Convert PDC addresses to kernel addresses.
+ * @address: Address returned from PDC.
+ *
+ * This function is used to convert PDC addresses into kernel addresses
+ * when the PDC address size and kernel address size are different.
+ */
+static unsigned long f_extend(unsigned long address)
+{
+#ifdef CONFIG_PDC_NARROW
+	if((address & 0xff000000) == 0xf0000000)
+		return 0xf0f0f0f000000000 | (u32)address;
+
+	if((address & 0xf0000000) == 0xf0000000)
+		return 0xffffffff00000000 | (u32)address;
+#endif
+	return address;
+}
+
+/**
+ * convert_to_wide - Convert the return buffer addresses into kernel addresses.
+ * @address: The return buffer from PDC.
+ *
+ * This function is used to convert the return buffer addresses retrieved from PDC
+ * into kernel addresses when the PDC address size and kernel address size are
+ * different.
+ */
+static void convert_to_wide(unsigned long *addr)
+{
+#ifdef CONFIG_PDC_NARROW
+	int i;
+	unsigned *p = (unsigned int *)addr;
+	for(i = 31; i >= 0; --i)
+		addr[i] = p[i];
+#endif
+}
+
+/**
+ * pdc_emergency_unlock - Unlock the linux pdc lock
+ *
+ * This call unlocks the linux pdc lock in case we need some PDC functions
+ * (like pdc_add_valid) during kernel stack dump.
+ */
+void pdc_emergency_unlock(void)
+{
+        spin_unlock(&pdc_lock);
+}
+
+
+/**
+ * pdc_add_valid - Verify address can be accessed without causing a HPMC.
+ * @address: Address to be verified.
+ *
+ * This PDC call attempts to read from the specified address and verifies
+ * if the address is valid.
+ * 
+ * The return value is PDC_OK (0) in case accessing this address is valid.
+ */
+int pdc_add_valid(unsigned long address)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, address);
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_chassis_info - Return chassis information.
+ * @result: The return buffer.
+ * @chassis_info: The memory buffer address.
+ * @len: The size of the memory buffer address.
+ *
+ * An HVERSION dependent call for returning the chassis information.
+ */
+int __init pdc_chassis_info(struct pdc_chassis_info *chassis_info, void *led_info, unsigned long len)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        memcpy(&pdc_result, chassis_info, sizeof(*chassis_info));
+        memcpy(&pdc_result2, led_info, len);
+        retval = mem_pdc_call(PDC_CHASSIS, PDC_RETURN_CHASSIS_INFO,
+                              __pa(pdc_result), __pa(pdc_result2), len);
+        memcpy(chassis_info, pdc_result, sizeof(*chassis_info));
+        memcpy(led_info, pdc_result2, len);
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_coproc_cfg - To identify coprocessors attached to the processor.
+ * @pdc_coproc_info: Return buffer address.
+ *
+ * This PDC call returns the presence and status of all the coprocessors
+ * attached to the processor.
+ */
+int __init pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_COPROC, PDC_COPROC_CFG, __pa(pdc_result));
+        convert_to_wide(pdc_result);
+        pdc_coproc_info->ccr_functional = pdc_result[0];
+        pdc_coproc_info->ccr_present = pdc_result[1];
+        pdc_coproc_info->revision = pdc_result[17];
+        pdc_coproc_info->model = pdc_result[18];
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_iodc_read - Read data from the modules IODC.
+ * @actcnt: The actual number of bytes.
+ * @hpa: The HPA of the module for the iodc read.
+ * @index: The iodc entry point.
+ * @iodc_data: A buffer memory for the iodc options.
+ * @iodc_data_size: Size of the memory buffer.
+ *
+ * This PDC call reads from the IODC of the module specified by the hpa
+ * argument.
+ */
+int pdc_iodc_read(unsigned long *actcnt, unsigned long hpa, unsigned int index,
+		  void *iodc_data, unsigned int iodc_data_size)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_IODC, PDC_IODC_READ, __pa(pdc_result), hpa, 
+			      index, __pa(pdc_result2), iodc_data_size);
+	convert_to_wide(pdc_result);
+	*actcnt = pdc_result[0];
+	memcpy(iodc_data, pdc_result2, iodc_data_size);
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_system_map_find_mods - Locate unarchitected modules.
+ * @pdc_mod_info: Return buffer address.
+ * @mod_path: pointer to dev path structure.
+ * @mod_index: fixed address module index.
+ *
+ * To locate and identify modules which reside at fixed I/O addresses, which
+ * do not self-identify via architected bus walks.
+ */
+int pdc_system_map_find_mods(struct pdc_system_map_mod_info *pdc_mod_info,
+			     struct pdc_module_path *mod_path, long mod_index)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE, __pa(pdc_result), 
+			      __pa(pdc_result2), mod_index);
+	convert_to_wide(pdc_result);
+	memcpy(pdc_mod_info, pdc_result, sizeof(*pdc_mod_info));
+	memcpy(mod_path, pdc_result2, sizeof(*mod_path));
+	spin_unlock_irq(&pdc_lock);
+
+	pdc_mod_info->mod_addr = f_extend(pdc_mod_info->mod_addr);
+	return retval;
+}
+
+/**
+ * pdc_system_map_find_addrs - Retrieve additional address ranges.
+ * @pdc_addr_info: Return buffer address.
+ * @mod_index: Fixed address module index.
+ * @addr_index: Address range index.
+ * 
+ * Retrieve additional information about subsequent address ranges for modules
+ * with multiple address ranges.  
+ */
+int pdc_system_map_find_addrs(struct pdc_system_map_addr_info *pdc_addr_info, 
+			      long mod_index, long addr_index)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_ADDRESS, __pa(pdc_result),
+			      mod_index, addr_index);
+	convert_to_wide(pdc_result);
+	memcpy(pdc_addr_info, pdc_result, sizeof(*pdc_addr_info));
+	spin_unlock_irq(&pdc_lock);
+
+	pdc_addr_info->mod_addr = f_extend(pdc_addr_info->mod_addr);
+	return retval;
+}
+
+/**
+ * pdc_model_info - Return model information about the processor.
+ * @model: The return buffer.
+ *
+ * Returns the version numbers, identifiers, and capabilities from the processor module.
+ */
+int pdc_model_info(struct pdc_model *model) 
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_INFO, __pa(pdc_result), 0);
+	convert_to_wide(pdc_result);
+	memcpy(model, pdc_result, sizeof(*model));
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_model_sysmodel - Get the system model name.
+ * @name: A char array of at least 81 characters.
+ *
+ * Get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L)
+ */
+int pdc_model_sysmodel(char *name)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_SYSMODEL, __pa(pdc_result),
+                              OS_ID_HPUX, __pa(name));
+        convert_to_wide(pdc_result);
+
+        if (retval == PDC_OK) {
+                name[pdc_result[0]] = '\0'; /* add trailing '\0' */
+        } else {
+                name[0] = 0;
+        }
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_model_versions - Identify the version number of each processor.
+ * @cpu_id: The return buffer.
+ * @id: The id of the processor to check.
+ *
+ * Returns the version number for each processor component.
+ *
+ * This comment was here before, but I do not know what it means :( -RB
+ * id: 0 = cpu revision, 1 = boot-rom-version
+ */
+int pdc_model_versions(unsigned long *versions, int id)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_VERSIONS, __pa(pdc_result), id);
+        convert_to_wide(pdc_result);
+        *versions = pdc_result[0];
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_model_cpuid - Returns the CPU_ID.
+ * @cpu_id: The return buffer.
+ *
+ * Returns the CPU_ID value which uniquely identifies the cpu portion of
+ * the processor module.
+ */
+int pdc_model_cpuid(unsigned long *cpu_id)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
+        retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CPU_ID, __pa(pdc_result), 0);
+        convert_to_wide(pdc_result);
+        *cpu_id = pdc_result[0];
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_model_capabilities - Returns the platform capabilities.
+ * @capabilities: The return buffer.
+ *
+ * Returns information about platform support for 32- and/or 64-bit
+ * OSes, IO-PDIR coherency, and virtual aliasing.
+ */
+int pdc_model_capabilities(unsigned long *capabilities)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        pdc_result[0] = 0; /* preset zero (call may not be implemented!) */
+        retval = mem_pdc_call(PDC_MODEL, PDC_MODEL_CAPABILITIES, __pa(pdc_result), 0);
+        convert_to_wide(pdc_result);
+        *capabilities = pdc_result[0];
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_cache_info - Return cache and TLB information.
+ * @cache_info: The return buffer.
+ *
+ * Returns information about the processor's cache and TLB.
+ */
+int pdc_cache_info(struct pdc_cache_info *cache_info)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_CACHE, PDC_CACHE_INFO, __pa(pdc_result), 0);
+        convert_to_wide(pdc_result);
+        memcpy(cache_info, pdc_result, sizeof(*cache_info));
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+#ifndef CONFIG_PA20
+/**
+ * pdc_btlb_info - Return block TLB information.
+ * @btlb: The return buffer.
+ *
+ * Returns information about the hardware Block TLB.
+ */
+int pdc_btlb_info(struct pdc_btlb_info *btlb) 
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_BLOCK_TLB, PDC_BTLB_INFO, __pa(pdc_result), 0);
+        memcpy(btlb, pdc_result, sizeof(*btlb));
+        spin_unlock_irq(&pdc_lock);
+
+        if(retval < 0) {
+                btlb->max_size = 0;
+        }
+        return retval;
+}
+
+/**
+ * pdc_mem_map_hpa - Find fixed module information.  
+ * @address: The return buffer
+ * @mod_path: pointer to dev path structure.
+ *
+ * This call was developed for S700 workstations to allow the kernel to find
+ * the I/O devices (Core I/O). In the future (Kittyhawk and beyond) this
+ * call will be replaced (on workstations) by the architected PDC_SYSTEM_MAP
+ * call.
+ *
+ * This call is supported by all existing S700 workstations (up to  Gecko).
+ */
+int pdc_mem_map_hpa(struct pdc_memory_map *address,
+		struct pdc_module_path *mod_path)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        memcpy(pdc_result2, mod_path, sizeof(*mod_path));
+        retval = mem_pdc_call(PDC_MEM_MAP, PDC_MEM_MAP_HPA, __pa(pdc_result),
+				__pa(pdc_result2));
+        memcpy(address, pdc_result, sizeof(*address));
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+#endif	/* !CONFIG_PA20 */
+
+/**
+ * pdc_lan_station_id - Get the LAN address.
+ * @lan_addr: The return buffer.
+ * @hpa: The network device HPA.
+ *
+ * Get the LAN station address when it is not directly available from the LAN hardware.
+ */
+int pdc_lan_station_id(char *lan_addr, unsigned long hpa)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
+			__pa(pdc_result), hpa);
+	if (retval < 0) {
+		/* FIXME: else read MAC from NVRAM */
+		memset(lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
+	} else {
+		memcpy(lan_addr, pdc_result, PDC_LAN_STATION_ID_SIZE);
+	}
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+
+/**
+ * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
+ * @hwpath: fully bc.mod style path to the device.
+ * @scsi_id: what someone told firmware the ID should be.
+ * @period: time in cycles 
+ * @width: 8 or 16-bit wide bus
+ * @mode: 0,1,2 -> SE,HVD,LVD signalling mode
+ *
+ * Get the SCSI operational parameters from PDC.
+ * Needed since HPUX never used BIOS or symbios card NVRAM.
+ * Most ncr/sym cards won't have an entry and just use whatever
+ * capabilities of the card are (eg Ultra, LVD). But there are
+ * several cases where it's useful:
+ *    o set SCSI id for Multi-initiator clusters,
+ *    o cable too long (ie SE scsi 10Mhz won't support 6m length),
+ *    o bus width exported is less than what the interface chip supports.
+ */
+int pdc_get_initiator( struct hardware_path *hwpath, unsigned char *scsi_id,
+	unsigned long *period, char *width, char *mode)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+
+/* BCJ-XXXX series boxes. E.G. "9000/785/C3000" */
+#define IS_SPROCKETS() (strlen(boot_cpu_data.pdc.sys_model_name) == 14 && \
+	strncmp(boot_cpu_data.pdc.sys_model_name, "9000/785", 9) == 0)
+
+	retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, 
+			      __pa(pdc_result), __pa(hwpath));
+
+
+	if (retval >= PDC_OK) {
+		*scsi_id = (unsigned char) pdc_result[0];
+
+		/* convert Bus speed in Mhz to period (in 1/10 ns) */
+		switch(pdc_result[1]) {
+		/*
+		** case  0:   driver determines rate
+		** case -1:   Settings are uninitialized.
+		*/
+		case  5:  *period = 2000; break;
+		case 10:  *period = 1000; break;
+		case 20:  *period = 500; break;
+		case 40:  *period = 250; break;
+		default: /* Do nothing */ break;
+		}
+
+		/* 
+		** pdc_result[2]	PDC suggested SCSI id
+		** pdc_result[3]	PDC suggested SCSI rate
+		*/
+
+		if (IS_SPROCKETS()) {
+			/*
+			** Revisit: PAT PDC do the same thing?
+			** A500 also exports 50-pin SE SCSI.
+			**	0 == 8-bit
+			**	1 == 16-bit
+			*/
+			*width = (char) pdc_result[4];
+
+			/* ...in case someone needs it in the future.
+			** sym53c8xx.c comments say it can't autodetect
+			** for 825/825A/875 chips.
+			**	0 == SE, 1 == HVD, 2 == LVD
+			*/
+			*mode = (char) pdc_result[5]; 
+		}
+	}
+
+	spin_unlock_irq(&pdc_lock);
+	return retval >= PDC_OK;
+}
+
+
+/**
+ * pdc_pci_irt_size - Get the number of entries in the interrupt routing table.
+ * @num_entries: The return value.
+ * @hpa: The HPA for the device.
+ *
+ * This PDC function returns the number of entries in the specified cell's
+ * interrupt table.
+ * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
+ */ 
+int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE, 
+			      __pa(pdc_result), hpa);
+	convert_to_wide(pdc_result);
+	*num_entries = pdc_result[0];
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/** 
+ * pdc_pci_irt - Get the PCI interrupt routing table.
+ * @num_entries: The number of entries in the table.
+ * @hpa: The Hard Physical Address of the device.
+ * @tbl: 
+ *
+ * Get the PCI interrupt routing table for the device at the given HPA.
+ * Similar to PDC_PAT stuff - but added for Forte/Allegro boxes
+ */
+int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	pdc_result[0] = num_entries;
+	retval = mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, 
+			      __pa(pdc_result), hpa, __pa(tbl));
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+
+/**
+ * pdc_tod_read - Read the Time-Of-Day clock.
+ * @tod: The return buffer:
+ *
+ * Read the Time-Of-Day clock
+ */
+int pdc_tod_read(struct pdc_tod *tod)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(pdc_result), 0);
+        convert_to_wide(pdc_result);
+        memcpy(tod, pdc_result, sizeof(*tod));
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/**
+ * pdc_tod_set - Set the Time-Of-Day clock.
+ * @sec: The number of seconds since epoch.
+ * @usec: The number of micro seconds.
+ *
+ * Set the Time-Of-Day clock.
+ */ 
+int pdc_tod_set(unsigned long sec, unsigned long usec)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+#ifdef __LP64__
+int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
+		struct pdc_memory_table *tbl, unsigned long entries)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_MEM, PDC_MEM_TABLE, __pa(pdc_result), __pa(pdc_result2), entries);
+	convert_to_wide(pdc_result);
+	memcpy(r_addr, pdc_result, sizeof(*r_addr));
+	memcpy(tbl, pdc_result2, entries * sizeof(*tbl));
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+#endif /* __LP64__ */
+
+/* FIXME: Is this pdc used?  I could not find type reference to ftc_bitmap
+ * so I guessed at unsigned long.  Someone who knows what this does, can fix
+ * it later. :)
+ */
+int pdc_do_firm_test_reset(unsigned long ftc_bitmap)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_FIRM_TEST_RESET,
+                              PDC_FIRM_TEST_MAGIC, ftc_bitmap);
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/*
+ * pdc_do_reset - Reset the system.
+ *
+ * Reset the system.
+ */
+int pdc_do_reset()
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);
+        retval = mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET);
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+/*
+ * pdc_soft_power_info - Enable soft power switch.
+ * @power_reg: address of soft power register
+ *
+ * Return the absolute address of the soft power switch register
+ */
+int __init pdc_soft_power_info(unsigned long *power_reg)
+{
+	int retval;
+
+	*power_reg = (unsigned long) (-1);
+	
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_INFO, __pa(pdc_result), 0);
+	if (retval == PDC_OK) {
+                convert_to_wide(pdc_result);
+                *power_reg = f_extend(pdc_result[0]);
+	}
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/*
+ * pdc_soft_power_button - Control the soft power button behaviour
+ * @sw_control: 0 for hardware control, 1 for software control 
+ *
+ *
+ * This PDC function places the soft power button under software or
+ * hardware control.
+ * Under software control the OS may control to when to allow to shut 
+ * down the system. Under hardware control pressing the power button 
+ * powers off the system immediately.
+ */
+int pdc_soft_power_button(int sw_control)
+{
+	int retval;
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_SOFT_POWER, PDC_SOFT_POWER_ENABLE, __pa(pdc_result), sw_control);
+	spin_unlock_irq(&pdc_lock);
+	return retval;
+}
+
+/*
+ * pdc_suspend_usb - Stop USB controller
+ *
+ * If PDC used the usb controller, the usb controller
+ * is still running and will crash the machines during iommu 
+ * setup, because of still running DMA. This PDC call
+ * stops the USB controller
+ */
+void pdc_suspend_usb(void)
+{
+	spin_lock_irq(&pdc_lock);  
+	mem_pdc_call(PDC_IO, PDC_IO_SUSPEND_USB, 0);
+	spin_unlock_irq(&pdc_lock);
+}
+
+/**
+ * pdc_iodc_putc - Console character print using IODC.
+ * @c: the character to output.
+ *
+ * Note that only these special chars are architected for console IODC io:
+ * BEL, BS, CR, and LF. Others are passed through.
+ * Since the HP console requires CR+LF to perform a 'newline', we translate
+ * "\n" to "\r\n".
+ */
+void pdc_iodc_putc(unsigned char c)
+{
+        /* XXX Should we spinlock posx usage */
+        static int posx;        /* for simple TAB-Simulation... */
+        static int __attribute__((aligned(8)))   iodc_retbuf[32];
+        static char __attribute__((aligned(64))) iodc_dbuf[4096];
+        unsigned int n;
+	unsigned int flags;
+
+        switch (c) {
+        case '\n':
+                iodc_dbuf[0] = '\r';
+                iodc_dbuf[1] = '\n';
+                n = 2;
+                posx = 0;
+                break;
+        case '\t':
+                pdc_iodc_putc(' ');
+                while (posx & 7)        /* expand TAB */
+                        pdc_iodc_putc(' ');
+                return;         /* return since IODC can't handle this */
+        case '\b':
+                posx-=2;                /* BS */
+        default:
+                iodc_dbuf[0] = c;
+                n = 1;
+                posx++;
+                break;
+        }
+
+        spin_lock_irqsave(&pdc_lock, flags);
+        real32_call(PAGE0->mem_cons.iodc_io,
+                    (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+                    PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+                    __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+        spin_unlock_irqrestore(&pdc_lock, flags);
+}
+
+/**
+ * pdc_iodc_outc - Console character print using IODC (without conversions).
+ * @c: the character to output.
+ *
+ * Write the character directly to the IODC console.
+ */
+void pdc_iodc_outc(unsigned char c)
+{
+	unsigned int n, flags;
+
+	/* fill buffer with one caracter and print it */
+        static int __attribute__((aligned(8)))   iodc_retbuf[32];
+        static char __attribute__((aligned(64))) iodc_dbuf[4096];
+
+	n = 1;
+	iodc_dbuf[0] = c;
+
+	spin_lock_irqsave(&pdc_lock, flags);
+	real32_call(PAGE0->mem_cons.iodc_io,
+		    (unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
+		    PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
+		    __pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
+	spin_unlock_irqrestore(&pdc_lock, flags);
+}
+
+/**
+ * pdc_iodc_getc - Read a character (non-blocking) from the PDC console.
+ *
+ * Read a character (non-blocking) from the PDC console, returns -1 if
+ * key is not present.
+ */
+int pdc_iodc_getc(void)
+{
+	unsigned int flags;
+        static int __attribute__((aligned(8)))   iodc_retbuf[32];
+        static char __attribute__((aligned(64))) iodc_dbuf[4096];
+	int ch;
+	int status;
+
+	/* Bail if no console input device. */
+	if (!PAGE0->mem_kbd.iodc_io)
+		return 0;
+	
+	/* wait for a keyboard (rs232)-input */
+	spin_lock_irqsave(&pdc_lock, flags);
+	real32_call(PAGE0->mem_kbd.iodc_io,
+		    (unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
+		    PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers), 
+		    __pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
+
+	ch = *iodc_dbuf;
+	status = *iodc_retbuf;
+	spin_unlock_irqrestore(&pdc_lock, flags);
+
+	if (status == 0)
+	    return -1;
+	
+	return ch;
+}
+
+int pdc_sti_call(unsigned long func, unsigned long flags,
+                 unsigned long inptr, unsigned long outputr,
+                 unsigned long glob_cfg)
+{
+        int retval;
+
+        spin_lock_irq(&pdc_lock);  
+        retval = real32_call(func, flags, inptr, outputr, glob_cfg);
+        spin_unlock_irq(&pdc_lock);
+
+        return retval;
+}
+
+#ifdef __LP64__
+/**
+ * pdc_pat_cell_get_number - Returns the cell number.
+ * @cell_info: The return buffer.
+ *
+ * This PDC call returns the cell number of the cell from which the call
+ * is made.
+ */
+int pdc_pat_cell_get_number(struct pdc_pat_cell_num *cell_info)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_GET_NUMBER, __pa(pdc_result));
+	memcpy(cell_info, pdc_result, sizeof(*cell_info));
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_cell_module - Retrieve the cell's module information.
+ * @actcnt: The number of bytes written to mem_addr.
+ * @ploc: The physical location.
+ * @mod: The module index.
+ * @view_type: The view of the address type.
+ * @mem_addr: The return buffer.
+ *
+ * This PDC call returns information about each module attached to the cell
+ * at the specified location.
+ */
+int pdc_pat_cell_module(unsigned long *actcnt, unsigned long ploc, unsigned long mod,
+			unsigned long view_type, void *mem_addr)
+{
+	int retval;
+	static struct pdc_pat_cell_mod_maddr_block result __attribute__ ((aligned (8)));
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_CELL, PDC_PAT_CELL_MODULE, __pa(pdc_result), 
+			      ploc, mod, view_type, __pa(&result));
+	if(!retval) {
+		*actcnt = pdc_result[0];
+		memcpy(mem_addr, &result, *actcnt);
+	}
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_cpu_get_number - Retrieve the cpu number.
+ * @cpu_info: The return buffer.
+ * @hpa: The Hard Physical Address of the CPU.
+ *
+ * Retrieve the cpu number for the cpu at the specified HPA.
+ */
+int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, void *hpa)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
+			      __pa(&pdc_result), hpa);
+	memcpy(cpu_info, pdc_result, sizeof(*cpu_info));
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_get_irt_size - Retrieve the number of entries in the cell's interrupt table.
+ * @num_entries: The return value.
+ * @cell_num: The target cell.
+ *
+ * This PDC function returns the number of entries in the specified cell's
+ * interrupt table.
+ */
+int pdc_pat_get_irt_size(unsigned long *num_entries, unsigned long cell_num)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE_SIZE,
+			      __pa(pdc_result), cell_num);
+	*num_entries = pdc_result[0];
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_get_irt - Retrieve the cell's interrupt table.
+ * @r_addr: The return buffer.
+ * @cell_num: The target cell.
+ *
+ * This PDC function returns the actual interrupt table for the specified cell.
+ */
+int pdc_pat_get_irt(void *r_addr, unsigned long cell_num)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_IO, PDC_PAT_IO_GET_PCI_ROUTING_TABLE,
+			      __pa(r_addr), cell_num);
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+
+/**
+ * pdc_pat_pd_get_addr_map - Retrieve information about memory address ranges.
+ * @actlen: The return buffer.
+ * @mem_addr: Pointer to the memory buffer.
+ * @count: The number of bytes to read from the buffer.
+ * @offset: The offset with respect to the beginning of the buffer.
+ *
+ */
+int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, 
+			    unsigned long count, unsigned long offset)
+{
+	int retval;
+
+	spin_lock_irq(&pdc_lock);
+	retval = mem_pdc_call(PDC_PAT_PD, PDC_PAT_PD_GET_ADDR_MAP, __pa(pdc_result), 
+			      __pa(pdc_result2), count, offset);
+	*actual_len = pdc_result[0];
+	memcpy(mem_addr, pdc_result2, *actual_len);
+	spin_unlock_irq(&pdc_lock);
+
+	return retval;
+}
+#endif /* __LP64__ */
+
+
+/***************** 32-bit real-mode calls ***********/
+/* The struct below is used
+ * to overlay real_stack (real2.S), preparing a 32-bit call frame.
+ * real32_call_asm() then uses this stack in narrow real mode
+ */
+
+struct narrow_stack {
+	/* use int, not long which is 64 bits */
+	unsigned int arg13;
+	unsigned int arg12;
+	unsigned int arg11;
+	unsigned int arg10;
+	unsigned int arg9;
+	unsigned int arg8;
+	unsigned int arg7;
+	unsigned int arg6;
+	unsigned int arg5;
+	unsigned int arg4;
+	unsigned int arg3;
+	unsigned int arg2;
+	unsigned int arg1;
+	unsigned int arg0;
+	unsigned int frame_marker[8];
+	unsigned int sp;
+	/* in reality, there's nearly 8k of stack after this */
+};
+
+static long real32_call(unsigned long fn, ...)
+{
+	va_list args;
+	extern struct narrow_stack real_stack;
+	extern unsigned long real32_call_asm(unsigned int *,
+					     unsigned int *, 
+					     unsigned int);
+	
+	va_start(args, fn);
+	real_stack.arg0 = va_arg(args, unsigned int);
+	real_stack.arg1 = va_arg(args, unsigned int);
+	real_stack.arg2 = va_arg(args, unsigned int);
+	real_stack.arg3 = va_arg(args, unsigned int);
+	real_stack.arg4 = va_arg(args, unsigned int);
+	real_stack.arg5 = va_arg(args, unsigned int);
+	real_stack.arg6 = va_arg(args, unsigned int);
+	real_stack.arg7 = va_arg(args, unsigned int);
+	real_stack.arg8 = va_arg(args, unsigned int);
+	real_stack.arg9 = va_arg(args, unsigned int);
+	real_stack.arg10 = va_arg(args, unsigned int);
+	real_stack.arg11 = va_arg(args, unsigned int);
+	real_stack.arg12 = va_arg(args, unsigned int);
+	real_stack.arg13 = va_arg(args, unsigned int);
+	va_end(args);
+	
+	return real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+}
+
+#ifdef __LP64__
+/***************** 64-bit real-mode calls ***********/
+
+struct wide_stack {
+	unsigned long arg0;
+	unsigned long arg1;
+	unsigned long arg2;
+	unsigned long arg3;
+	unsigned long arg4;
+	unsigned long arg5;
+	unsigned long arg6;
+	unsigned long arg7;
+	unsigned long arg8;
+	unsigned long arg9;
+	unsigned long arg10;
+	unsigned long arg11;
+	unsigned long arg12;
+	unsigned long arg13;
+	unsigned long frame_marker[2];	/* rp, previous sp */
+	unsigned long sp;
+	/* in reality, there's nearly 8k of stack after this */
+};
+
+static long real64_call(unsigned long fn, ...)
+{
+	va_list args;
+	extern struct wide_stack real_stack;
+	extern unsigned long real64_call_asm(unsigned long *,
+					     unsigned long *, 
+					     unsigned long);
+    
+	va_start(args, fn);
+	real_stack.arg0 = va_arg(args, unsigned long);
+	real_stack.arg1 = va_arg(args, unsigned long);
+	real_stack.arg2 = va_arg(args, unsigned long);
+	real_stack.arg3 = va_arg(args, unsigned long);
+	real_stack.arg4 = va_arg(args, unsigned long);
+	real_stack.arg5 = va_arg(args, unsigned long);
+	real_stack.arg6 = va_arg(args, unsigned long);
+	real_stack.arg7 = va_arg(args, unsigned long);
+	real_stack.arg8 = va_arg(args, unsigned long);
+	real_stack.arg9 = va_arg(args, unsigned long);
+	real_stack.arg10 = va_arg(args, unsigned long);
+	real_stack.arg11 = va_arg(args, unsigned long);
+	real_stack.arg12 = va_arg(args, unsigned long);
+	real_stack.arg13 = va_arg(args, unsigned long);
+	va_end(args);
+	
+	return real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
+}
+
+#endif /* __LP64__ */
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/hardware.c linux/arch/parisc/kernel/hardware.c
--- linux.orig/arch/parisc/kernel/hardware.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/hardware.c	2002-08-12 22:14:17.000000000 +0000
@@ -5,7 +5,7 @@
  * 
  *    Based on the document "PA-RISC 1.1 I/O Firmware Architecture 
  *    Reference Specification", March 7, 1999, version 0.96.  This
- *    is available at ?.
+ *    is available at http://parisc-linux.org/documentation/
  *
  *    Copyright 1999 by Alex deVries <adevries@thepuffingroup.com>
  *    and copyright 1999 The Puffin Group Inc.
@@ -30,32 +30,15 @@
 #include <asm/hardware.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
-
-#define HPHW_NUM_TYPES 3431
-
-static char * hw_type_name[16] = {
-	"Processor",
-	"Memory",
-	"B DMA",
-	"Obsolete",
-	"A DMA",
-	"A Direct",
-	"Obsolete",
-	"Bus Converter Port",
-	"HP CIO Adapter",
-	"Console",
-	"Foreign I/O Module",
-	"Bus Adapter",
-	"IOA (?)",
-	"Bus Bridge to Foreign Bus",
-	"HP Clothing: Fabric Component"
-};
+#include <linux/init.h>
 
 /*
- *	XXX	Could this be __init ??
+ *	HP PARISC Hardware Database
+ *	Access to this database is only possible during bootup
+ *	so don't reference this table after starting the init process
  */
  
-static struct hp_hardware hp_hardware_list[] = {
+static struct hp_hardware hp_hardware_list[] __initdata = {
 	{HPHW_NPROC,0x01,0x4,0x0,"Indigo (840, 930)"},
 	{HPHW_NPROC,0x8,0x4,0x01,"Firefox(825,925)"},
 	{HPHW_NPROC,0xA,0x4,0x01,"Top Gun (835,834,935,635)"},
@@ -169,9 +152,10 @@
 	{HPHW_NPROC,0x59A,0x4,0x91,"Unlisted but reserved"},
 	{HPHW_NPROC,0x59A,0x4,0x81,"Unlisted but reserved"},
 	{HPHW_NPROC,0x59B,0x4,0x81,"Raven U 160 (9000/780/C160)"},
+	{HPHW_NPROC,0x59C,0x4,0x81,"Raven U 180 (9000/780/C180)"},
 	{HPHW_NPROC,0x59D,0x4,0x81,"Raven U 200 (9000/780/C200)"},
 	{HPHW_NPROC,0x59E,0x4,0x91,"ThunderHawk T' 120"},
-	{HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780/\?\?\?\?)"},
+	{HPHW_NPROC,0x59F,0x4,0x91,"Raven U 180+ (9000/780)"},
 	{HPHW_NPROC,0x5A0,0x4,0x81,"UL 1w T120 1MB/1MB (841/D260,D360)"},
 	{HPHW_NPROC,0x5A1,0x4,0x91,"UL 2w T120 1MB/1MB (851/D260,D360)"},
 	{HPHW_NPROC,0x5A2,0x4,0x81,"UL 1w U160 512K/512K (861/D270,D370)"},
@@ -201,7 +185,7 @@
 	{HPHW_NPROC,0x5B8,0x4,0x91,"SPP2250 240 MHz"},
 	{HPHW_NPROC,0x5B9,0x4,0x81,"UL 1w U+/240 (350/550)"},
 	{HPHW_NPROC,0x5BA,0x4,0x91,"UL 2w U+/240 (350/550)"},
-	{HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W "},
+	{HPHW_NPROC,0x5BB,0x4,0x81,"AllegroHigh W"},
 	{HPHW_NPROC,0x5BC,0x4,0x91,"AllegroLow W"},
 	{HPHW_NPROC,0x5BD,0x4,0x91,"Forte W 2-way"},
 	{HPHW_NPROC,0x5BE,0x4,0x91,"Prelude W"},
@@ -212,12 +196,41 @@
 	{HPHW_NPROC,0x5C3,0x4,0x91,"Sonata 360"},
 	{HPHW_NPROC,0x5C4,0x4,0x91,"Rhapsody 440"},
 	{HPHW_NPROC,0x5C5,0x4,0x91,"Rhapsody 360"},
-	{HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780/\?\?\?\?)"},
+	{HPHW_NPROC,0x5C6,0x4,0x91,"Raven W 360 (9000/780)"},
 	{HPHW_NPROC,0x5C7,0x4,0x91,"Halfdome W 440"},
 	{HPHW_NPROC,0x5C8,0x4,0x81,"Lego 360 processor"},
 	{HPHW_NPROC,0x5C9,0x4,0x91,"Rhapsody DC- 440"},
 	{HPHW_NPROC,0x5CA,0x4,0x91,"Rhapsody DC- 360"},
 	{HPHW_NPROC,0x5CB,0x4,0x91,"Crescendo 440"},
+	{HPHW_NPROC,0x5CC,0x4,0x91,"Prelude W 440"},
+	{HPHW_NPROC,0x5CD,0x4,0x91,"SPP2600"},
+	{HPHW_NPROC,0x5CE,0x4,0x91,"M2600"},
+	{HPHW_NPROC,0x5CF,0x4,0x81,"Allegro W+"},
+	{HPHW_NPROC,0x5D0,0x4,0x81,"Kazoo W+"},
+	{HPHW_NPROC,0x5D1,0x4,0x91,"Forte W+ 2w"},
+	{HPHW_NPROC,0x5D2,0x4,0x91,"Forte W+ 4w"},
+	{HPHW_NPROC,0x5D3,0x4,0x91,"Prelude W+ 540"},
+	{HPHW_NPROC,0x5D4,0x4,0x91,"Duet W+"},
+	{HPHW_NPROC,0x5D5,0x4,0x91,"Crescendo 550"},
+	{HPHW_NPROC,0x5D6,0x4,0x81,"Crescendo DC- 440"},
+	{HPHW_NPROC,0x5D7,0x4,0x91,"Keystone W+"},
+	{HPHW_NPROC,0x5D8,0x4,0x91,"Rhapsody wave 2 W+ DC-"},
+	{HPHW_NPROC,0x5D9,0x4,0x91,"Rhapsody wave 2 W+"},
+	{HPHW_NPROC,0x5DA,0x4,0x91,"Marcato W+ DC-"},
+	{HPHW_NPROC,0x5DB,0x4,0x91,"Marcato W+"},
+	{HPHW_NPROC,0x5DC,0x4,0x91,"Allegro W2"},
+	{HPHW_NPROC,0x5DD,0x4,0x81,"Duet W2"},
+	{HPHW_NPROC,0x5DE,0x4,0x81,"Piccolo W+"},
+	{HPHW_NPROC,0x5DF,0x4,0x81,"Cantata W2"},
+	{HPHW_NPROC,0x5E0,0x4,0x91,"Cantata DC- W2"},
+	{HPHW_NPROC,0x5E1,0x4,0x91,"Crescendo DC- W2"},
+	{HPHW_NPROC,0x5E2,0x4,0x91,"Crescendo 650 W2"},
+	{HPHW_NPROC,0x5E3,0x4,0x91,"Crescendo 750 W2"},
+	{HPHW_NPROC,0x5E4,0x4,0x91,"Keystone/Matterhorn W2 750"},
+	{HPHW_NPROC,0x5E5,0x4,0x91,"PowerBar W+"},
+	{HPHW_NPROC,0x5E6,0x4,0x91,"Keystone/Matterhorn W2 650"},
+	{HPHW_NPROC,0x5E7,0x4,0x91,"Caribe W2 800"},
+	{HPHW_NPROC,0x5E8,0x4,0x91,"Pikes Peak W2"},
 	{HPHW_NPROC,0x5FF,0x4,0x91,"Hitachi W"},
 	{HPHW_NPROC,0x600,0x4,0x81,"Gecko (712/60)"},
 	{HPHW_NPROC,0x601,0x4,0x81,"Gecko 80 (712/80)"},
@@ -243,7 +256,7 @@
 	{HPHW_NPROC,0x616,0x4,0x81,"Piranha 120"},
 	{HPHW_NPROC,0x617,0x4,0x81,"Jason 50"},
 	{HPHW_NPROC,0x618,0x4,0x81,"Jason 100"},
-	{HPHW_NPROC,0x619,0x4,0x81,"Mirage 80 "},
+	{HPHW_NPROC,0x619,0x4,0x81,"Mirage 80"},
 	{HPHW_NPROC,0x61A,0x4,0x81,"SAIC L-80"},
 	{HPHW_NPROC,0x61B,0x4,0x81,"Rocky1 L-60"},
 	{HPHW_NPROC,0x61C,0x4,0x81,"Anole T (743/T)"},
@@ -311,6 +324,7 @@
 	{HPHW_A_DMA, 0x004, 0x00050, 0x80, "Lanbrusca 802.3 (36967A)"}, 
 	{HPHW_A_DMA, 0x004, 0x00056, 0x80, "HP-PB LoQuix FDDI"}, 
 	{HPHW_A_DMA, 0x004, 0x00057, 0x80, "HP-PB LoQuix FDDI (28670A)"}, 
+	{HPHW_A_DMA, 0x004, 0x0005E, 0x00, "Gecko Add-on Token Ring"}, 
 	{HPHW_A_DMA, 0x012, 0x00089, 0x80, "Barracuda Add-on FW-SCSI"}, 
 	{HPHW_A_DMA, 0x013, 0x00089, 0x80, "Bluefish Add-on FW-SCSI"}, 
 	{HPHW_A_DMA, 0x014, 0x00089, 0x80, "Shrike Add-on FW-SCSI"}, 
@@ -319,6 +333,7 @@
 	{HPHW_A_DMA, 0x01F, 0x00089, 0x80, "SkyHawk 100/120 FW-SCSI"}, 
 	{HPHW_A_DMA, 0x027, 0x00089, 0x80, "Piranha 100 FW-SCSI"}, 
 	{HPHW_A_DMA, 0x032, 0x00089, 0x80, "Raven T' Core FW-SCSI"}, 
+	{HPHW_A_DMA, 0x03b, 0x00089, 0x80, "Raven U/L2 Core FW-SCSI"}, 
 	{HPHW_A_DMA, 0x03d, 0x00089, 0x80, "Merlin 160 Core FW-SCSI"},
 	{HPHW_A_DMA, 0x044, 0x00089, 0x80, "Mohawk Core FW-SCSI"}, 
 	{HPHW_A_DMA, 0x051, 0x00089, 0x80, "Firehawk FW-SCSI"}, 
@@ -440,6 +455,8 @@
 	{HPHW_BA, 0x801, 0x00081, 0x0, "Hitachi Tiny 80 Core BA"}, 
 	{HPHW_BA, 0x004, 0x0008B, 0x0, "Anole Optional PCMCIA BA"}, 
 	{HPHW_BA, 0x004, 0x0008E, 0x0, "GSC ITR Wax BA"}, 
+	{HPHW_BA, 0x00C, 0x0008E, 0x0, "Gecko Optional Wax BA"}, 
+	{HPHW_BA, 0x010, 0x0008E, 0x0, "Pace Wax BA"}, 
 	{HPHW_BA, 0x011, 0x0008E, 0x0, "SuperPace Wax BA"}, 
 	{HPHW_BA, 0x012, 0x0008E, 0x0, "Mirage Jr Wax BA"}, 
 	{HPHW_BA, 0x013, 0x0008E, 0x0, "Mirage Wax BA"}, 
@@ -489,7 +506,7 @@
 	{HPHW_BA, 0x800, 0x00090, 0x0, "Hitachi Tiny 64 Wax EISA BA"}, 
 	{HPHW_BA, 0x801, 0x00090, 0x0, "Hitachi Tiny 80 Wax EISA BA"}, 
 	{HPHW_BA, 0x01A, 0x00093, 0x0, "Anole 64 TIMI BA"}, 
-	{HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 64 TIMI BA"}, 
+	{HPHW_BA, 0x01B, 0x00093, 0x0, "Anole 100 TIMI BA"}, 
 	{HPHW_BA, 0x034, 0x00093, 0x0, "Anole T TIMI BA"}, 
 	{HPHW_BA, 0x04A, 0x00093, 0x0, "Anole L2 132 TIMI BA"}, 
 	{HPHW_BA, 0x04C, 0x00093, 0x0, "Anole L2 165 TIMI BA"}, 
@@ -551,6 +568,7 @@
 	{HPHW_CONSOLE, 0x01A, 0x0001F, 0x00, "Jason/Anole 64 Null Console"}, 
 	{HPHW_CONSOLE, 0x01B, 0x0001F, 0x00, "Jason/Anole 100 Null Console"}, 
 	{HPHW_FABRIC, 0x004, 0x000AA, 0x80, "Halfdome DNA Central Agent"}, 
+	{HPHW_FABRIC, 0x007, 0x000AA, 0x80, "Caribe DNA Central Agent"}, 
 	{HPHW_FABRIC, 0x004, 0x000AB, 0x00, "Halfdome TOGO Fabric Crossbar"}, 
 	{HPHW_FABRIC, 0x004, 0x000AC, 0x00, "Halfdome Sakura Fabric Router"}, 
 	{HPHW_FIO, 0x025, 0x0002E, 0x80, "Armyknife Optional X.25"}, 
@@ -588,14 +606,14 @@
 	{HPHW_FIO, 0x00D, 0x00072, 0x0, "Strider-33 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x00E, 0x00072, 0x0, "Trailways-50 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x00F, 0x00072, 0x0, "Trailways-33 Core LAN (802.3)"}, 
-	{HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core Lan (802.3)"}, 
+	{HPHW_FIO, 0x010, 0x00072, 0x0, "Pace Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x011, 0x00072, 0x0, "Sidewinder Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x019, 0x00072, 0x0, "Scorpio Sr. Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x020, 0x00072, 0x0, "Scorpio 100 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x021, 0x00072, 0x0, "Spectra 50 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x022, 0x00072, 0x0, "Spectra 75 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x023, 0x00072, 0x0, "Spectra 100 Core LAN (802.3)"}, 
-	{HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core Lan (802.3)"}, 
+	{HPHW_FIO, 0x024, 0x00072, 0x0, "Fast Pace Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x026, 0x00072, 0x0, "CoralII Jaguar Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x004, 0x00073, 0x0, "Cobra Core HIL"}, 
 	{HPHW_FIO, 0x005, 0x00073, 0x0, "Coral Core HIL"}, 
@@ -694,8 +712,8 @@
 	{HPHW_FIO, 0x04D, 0x00074, 0x0, "Anole L2 165 Core Centronics"}, 
 	{HPHW_FIO, 0x050, 0x00074, 0x0, "Merlin Jr 132 Core Centronics"}, 
 	{HPHW_FIO, 0x051, 0x00074, 0x0, "Firehawk Core Centronics"}, 
-	{HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ wSE FWSCSI Core Centronics"}, 
-	{HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ wDiff FWSCSI Core Centronics"}, 
+	{HPHW_FIO, 0x056, 0x00074, 0x0, "Raven+ w SE FWSCSI Core Centronics"}, 
+	{HPHW_FIO, 0x057, 0x00074, 0x0, "Raven+ w Diff FWSCSI Core Centronics"}, 
 	{HPHW_FIO, 0x058, 0x00074, 0x0, "FireHawk 200 Core Centronics"}, 
 	{HPHW_FIO, 0x05C, 0x00074, 0x0, "SummitHawk 230 Core Centronics"}, 
 	{HPHW_FIO, 0x800, 0x00074, 0x0, "Hitachi Tiny 64 Core Centronics"}, 
@@ -861,66 +879,66 @@
 	{HPHW_FIO, 0x02E, 0x00083, 0x0, "UL 350 Core PC Floppy"}, 
 	{HPHW_FIO, 0x02F, 0x00083, 0x0, "UL 550 Core PC Floppy"}, 
 	{HPHW_FIO, 0x032, 0x00083, 0x0, "Raven T' Core PC Floppy"}, 
-	{HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floopy"}, 
-	{HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floopy"}, 
-	{HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floopy"}, 
-	{HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floopy"}, 
-	{HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floopy"}, 
-	{HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floopy"}, 
-	{HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floopy"}, 
-	{HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floopy"}, 
-	{HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floopy"}, 
-	{HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floopy"}, 
-	{HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floopy"}, 
-	{HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floopy"}, 
-	{HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floopy"}, 
-	{HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floopy"}, 
-	{HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floopy"}, 
-	{HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floopy"}, 
-	{HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floopy"}, 
-	{HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PC Keyboard"}, 
-	{HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PC Keyboard"}, 
-	{HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PC Keyboard"}, 
-	{HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PC Keyboard"}, 
-	{HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PC Keyboard"}, 
-	{HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PC Keyboard"}, 
-	{HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PC Keyboard"}, 
-	{HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PC Keyboard"}, 
-	{HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PC Keyboard"}, 
-	{HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core Keyboard"}, 
-	{HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core Keyboard"}, 
-	{HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PC Keyboard"}, 
-	{HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PC Keyboard"}, 
-	{HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PC Keyboard"}, 
-	{HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PC Keyboard"}, 
-	{HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PC Keyboard"}, 
-	{HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PC Keyboard"}, 
-	{HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PC Keyboard"}, 
-	{HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PC Keyboard"}, 
+	{HPHW_FIO, 0x034, 0x00083, 0x0, "SAIC L-80 Core PC Floppy"}, 
+	{HPHW_FIO, 0x035, 0x00083, 0x0, "PCX-L2 712/132 Core Floppy"}, 
+	{HPHW_FIO, 0x036, 0x00083, 0x0, "PCX-L2 712/160 Core Floppy"}, 
+	{HPHW_FIO, 0x03B, 0x00083, 0x0, "Raven U/L2 Core PC Floppy"}, 
+	{HPHW_FIO, 0x03C, 0x00083, 0x0, "Merlin 132 Core PC Floppy"}, 
+	{HPHW_FIO, 0x03D, 0x00083, 0x0, "Merlin 160 Core PC Floppy"}, 
+	{HPHW_FIO, 0x03E, 0x00083, 0x0, "Merlin+ 132 Core PC Floppy"}, 
+	{HPHW_FIO, 0x03F, 0x00083, 0x0, "Merlin+ 180 Core PC Floppy"}, 
+	{HPHW_FIO, 0x045, 0x00083, 0x0, "Rocky1 Core PC Floppy"}, 
+	{HPHW_FIO, 0x046, 0x00083, 0x0, "Rocky2 120 Core PC Floppy"}, 
+	{HPHW_FIO, 0x047, 0x00083, 0x0, "Rocky2 150 Core PC Floppy"}, 
+	{HPHW_FIO, 0x04E, 0x00083, 0x0, "Kiji L2 132 Core PC Floppy"}, 
+	{HPHW_FIO, 0x050, 0x00083, 0x0, "Merlin Jr 132 Core PC Floppy"}, 
+	{HPHW_FIO, 0x056, 0x00083, 0x0, "Raven+ w SE FWSCSI Core PC Floppy"}, 
+	{HPHW_FIO, 0x057, 0x00083, 0x0, "Raven+ w Diff FWSCSI Core PC Floppy"}, 
+	{HPHW_FIO, 0x800, 0x00083, 0x0, "Hitachi Tiny 64 Core PC Floppy"}, 
+	{HPHW_FIO, 0x801, 0x00083, 0x0, "Hitachi Tiny 80 Core PC Floppy"},
+	{HPHW_FIO, 0x015, 0x00084, 0x0, "KittyHawk GSY Core PS/2 Port"}, 
+	{HPHW_FIO, 0x016, 0x00084, 0x0, "Gecko Core PS/2 Port"}, 
+	{HPHW_FIO, 0x018, 0x00084, 0x0, "Gecko Optional PS/2 Port"}, 
+	{HPHW_FIO, 0x01A, 0x00084, 0x0, "Anole 64 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x01B, 0x00084, 0x0, "Anole 100 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x01C, 0x00084, 0x0, "Gecko 80 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x01D, 0x00084, 0x0, "Gecko 100 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x01F, 0x00084, 0x0, "SkyHawk 100/120 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x027, 0x00084, 0x0, "Piranha 100 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x028, 0x00084, 0x0, "Mirage Jr Core PS/2 Port"}, 
+	{HPHW_FIO, 0x029, 0x00084, 0x0, "Mirage Core PS/2 Port"}, 
+	{HPHW_FIO, 0x02A, 0x00084, 0x0, "Electra Core PS/2 Port"}, 
+	{HPHW_FIO, 0x02B, 0x00084, 0x0, "Mirage 80 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x02C, 0x00084, 0x0, "Mirage 100+ Core PS/2 Port"}, 
+	{HPHW_FIO, 0x02E, 0x00084, 0x0, "UL 350 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x02F, 0x00084, 0x0, "UL 550 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x032, 0x00084, 0x0, "Raven T' Core PS/2 Port"}, 
+	{HPHW_FIO, 0x033, 0x00084, 0x0, "Anole T Core PS/2 Port"}, 
+	{HPHW_FIO, 0x034, 0x00084, 0x0, "SAIC L-80 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x035, 0x00084, 0x0, "PCX-L2 712/132 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x036, 0x00084, 0x0, "PCX-L2 712/160 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x03B, 0x00084, 0x0, "Raven U/L2 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x03C, 0x00084, 0x0, "Merlin 132 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x03D, 0x00084, 0x0, "Merlin 160 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x03E, 0x00084, 0x0, "Merlin+ 132 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x03F, 0x00084, 0x0, "Merlin+ 180 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x044, 0x00084, 0x0, "Mohawk Core PS/2 Port"}, 
+	{HPHW_FIO, 0x045, 0x00084, 0x0, "Rocky1 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x046, 0x00084, 0x0, "Rocky2 120 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x047, 0x00084, 0x0, "Rocky2 150 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x048, 0x00084, 0x0, "Rocky2 120 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x049, 0x00084, 0x0, "Rocky2 150 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x04B, 0x00084, 0x0, "Anole L2 132 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x04D, 0x00084, 0x0, "Anole L2 165 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x04E, 0x00084, 0x0, "Kiji L2 132 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x050, 0x00084, 0x0, "Merlin Jr 132 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x051, 0x00084, 0x0, "Firehawk Core PS/2 Port"}, 
+	{HPHW_FIO, 0x056, 0x00084, 0x0, "Raven+ w SE FWSCSI Core PS/2 Port"}, 
+	{HPHW_FIO, 0x057, 0x00084, 0x0, "Raven+ w Diff FWSCSI Core PS/2 Port"}, 
+	{HPHW_FIO, 0x058, 0x00084, 0x0, "FireHawk 200 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x05C, 0x00084, 0x0, "SummitHawk 230 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x800, 0x00084, 0x0, "Hitachi Tiny 64 Core PS/2 Port"}, 
+	{HPHW_FIO, 0x801, 0x00084, 0x0, "Hitachi Tiny 80 Core PS/2 Port"}, 
 	{HPHW_FIO, 0x004, 0x00085, 0x0, "Solo GSC Optional Graphics"}, 
 	{HPHW_FIO, 0x005, 0x00085, 0x0, "Duet GSC Optional Graphics"}, 
 	{HPHW_FIO, 0x008, 0x00085, 0x0, "Anole Artist Optional Graphics"}, 
@@ -969,18 +987,17 @@
 	{HPHW_FIO, 0x034, 0x00088, 0x0, "Anole T VME Networking"}, 
 	{HPHW_FIO, 0x04A, 0x00088, 0x0, "Anole L2 132 VME Networking"}, 
 	{HPHW_FIO, 0x04C, 0x00088, 0x0, "Anole L2 165 VME Networking"}, 
-	{HPHW_FIO, 0x03B, 0x00089, 0x0, "Raven U/L2 Core FW-SCSI"}, 
-	{HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional Lan (802.3)"}, 
-	{HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core Lan (802.3)"}, 
+	{HPHW_FIO, 0x011, 0x0008A, 0x0, "WB-96 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x012, 0x0008A, 0x0, "Orville Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x013, 0x0008A, 0x0, "Wilbur Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x014, 0x0008A, 0x0, "WB-80 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x015, 0x0008A, 0x0, "KittyHawk GSY Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x016, 0x0008A, 0x0, "Gecko Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x018, 0x0008A, 0x0, "Gecko Optional LAN (802.3)"}, 
+	{HPHW_FIO, 0x01A, 0x0008A, 0x0, "Anole 64 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x01B, 0x0008A, 0x0, "Anole 100 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x01C, 0x0008A, 0x0, "Gecko 80 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x01D, 0x0008A, 0x0, "Gecko 100 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x01F, 0x0008A, 0x0, "SkyHawk 100/120 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x027, 0x0008A, 0x0, "Piranha 100 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x028, 0x0008A, 0x0, "Mirage Jr Core LAN (802.3)"}, 
@@ -991,24 +1008,24 @@
 	{HPHW_FIO, 0x02E, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x02F, 0x0008A, 0x0, "UL 350 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x032, 0x0008A, 0x0, "Raven T' Core LAN (802.3)"}, 
-	{HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core Lan (802.3)"}, 
+	{HPHW_FIO, 0x033, 0x0008A, 0x0, "Anole T Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x034, 0x0008A, 0x0, "SAIC L-80 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x035, 0x0008A, 0x0, "PCX-L2 712/132 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x036, 0x0008A, 0x0, "PCX-L2 712/160 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x03B, 0x0008A, 0x0, "Raven U/L2 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x03C, 0x0008A, 0x0, "Merlin 132 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x03D, 0x0008A, 0x0, "Merlin 160 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x044, 0x0008A, 0x0, "Mohawk Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x045, 0x0008A, 0x0, "Rocky1 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x046, 0x0008A, 0x0, "Rocky2 120 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x047, 0x0008A, 0x0, "Rocky2 150 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x04B, 0x0008A, 0x0, "Anole L2 132 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x04D, 0x0008A, 0x0, "Anole L2 165 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x04E, 0x0008A, 0x0, "Kiji L2 132 Core LAN (802.3)"}, 
-	{HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core Lan (802.3)"}, 
+	{HPHW_FIO, 0x050, 0x0008A, 0x0, "Merlin Jr 132 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x058, 0x0008A, 0x0, "FireHawk 200 Core LAN (802.3)"}, 
-	{HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core Lan (802.3)"}, 
-	{HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core Lan (802.3)"}, 
+	{HPHW_FIO, 0x800, 0x0008A, 0x0, "Hitachi Tiny 64 Core LAN (802.3)"}, 
+	{HPHW_FIO, 0x801, 0x0008A, 0x0, "Hitachi Tiny 80 Core LAN (802.3)"}, 
 	{HPHW_FIO, 0x004, 0x0008C, 0x0, "SkyHawk 100/120 Wax RS-232"}, 
 	{HPHW_FIO, 0x005, 0x0008C, 0x0, "SAIC L-80 Wax RS-232"}, 
 	{HPHW_FIO, 0x006, 0x0008C, 0x0, "Raven U/L2 Dino RS-232"}, 
@@ -1099,14 +1116,15 @@
 	{HPHW_FIO, 0x005, 0x0008F, 0x0, "Rocky1 Boot Rom"}, 
 	{HPHW_FIO, 0x006, 0x0008F, 0x0, "Rocky2 120 Boot Rom"}, 
 	{HPHW_FIO, 0x007, 0x0008F, 0x0, "Rocky2 150 Boot Rom"}, 
-	{HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS2 Keyboard"}, 
-	{HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG lan"}, 
+	{HPHW_FIO, 0x01B, 0x0008F, 0x0, "Anole 100 Boot Rom"}, 
+	{HPHW_FIO, 0x006, 0x00096, 0x0, "Raven U/L2 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x007, 0x00096, 0x0, "Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x008, 0x00096, 0x0, "Merlin 132 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x009, 0x00096, 0x0, "Merlin 160 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x00A, 0x00096, 0x0, "Merlin Jr 132 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x019, 0x00096, 0x0, "Merlin+ 180 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x022, 0x00096, 0x0, "Merlin+ 132 Dino PS/2 Port"}, 
+	{HPHW_FIO, 0x004, 0x00097, 0x0, "Cascade EISA 100VG LAN"}, 
 	{HPHW_FIO, 0x023, 0x00099, 0x0, "Rocky1 Wax HPIB"}, 
 	{HPHW_FIO, 0x048, 0x00099, 0x0, "Rocky2 120 Clark/Dino HPIB"}, 
 	{HPHW_FIO, 0x049, 0x00099, 0x0, "Rocky2 150 Clark/Dino HPIB"}, 
@@ -1114,14 +1132,14 @@
 	{HPHW_FIO, 0x004, 0x000A2, 0x0, "Forte Core PCI 10/100BT LAN"}, 
 	{HPHW_FIO, 0x005, 0x000A2, 0x0, "AllegroLow PCI 10/100BT LAN"}, 
 	{HPHW_FIO, 0x006, 0x000A2, 0x0, "AllegroHIgh Core PCI 10/100BT LAN"}, 
-	{HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in Lan"}, 
-	{HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT Lan"}, 
-	{HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI Lan"}, 
-	{HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI Lan"}, 
-	{HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI Lan"}, 
-	{HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI Lan"}, 
-	{HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI Lan"}, 
-	{HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI Lan"}, 
+	{HPHW_FIO, 0x007, 0x000A2, 0x0, "PCI Plug-in LAN"}, 
+	{HPHW_FIO, 0x00A, 0x000A2, 0x0, "Lego 360 Core PCI 10/100BT LAN"}, 
+	{HPHW_FIO, 0x03E, 0x000A2, 0x0, "Merlin+ 132 Core PCI LAN"}, 
+	{HPHW_FIO, 0x03F, 0x000A2, 0x0, "Merlin+ 180 Core PCI LAN"}, 
+	{HPHW_FIO, 0x056, 0x000A2, 0x0, "Raven+ w SE FWSCSI Core PCI LAN"}, 
+	{HPHW_FIO, 0x057, 0x000A2, 0x0, "Raven+ w Diff FWSCSI Core PCI LAN"}, 
+	{HPHW_FIO, 0x05E, 0x000A2, 0x0, "Staccato 132 PCI LAN"}, 
+	{HPHW_FIO, 0x05F, 0x000A2, 0x0, "Staccato 180 PCI LAN"}, 
 	{HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI LVD Ultra2 SCSI"}, 
 	{HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI SE UltraSCSI"}, 
 	{HPHW_FIO, 0x004, 0x000A3, 0x0, "Forte Core PCI IDE/ATAPI CD-ROM"}, 
@@ -1157,160 +1175,19 @@
 	{HPHW_IOA, 0x185, 0x0000B, 0x00, "Java BC Summit Port"}, 
 	{HPHW_IOA, 0x1FF, 0x0000B, 0x00, "Hitachi Ghostview Summit Port"}, 
 	{HPHW_IOA, 0x580, 0x0000B, 0x10, "U2-IOA BC Runway Port"}, 
-	{HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"}, 
-	{HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"}, 
-	{HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"}, 
+	{HPHW_IOA, 0x581, 0x0000B, 0x10, "Uturn-IOA BC Runway Port"},
+	{HPHW_IOA, 0x582, 0x0000B, 0x10, "Astro BC Runway Port"},
+	{HPHW_IOA, 0x700, 0x0000B, 0x00, "NEC-IOS BC System Bus Port"},
 	{HPHW_MEMORY, 0x002, 0x00008, 0x00, "MID_BUS"}, 
-	{HPHW_MEMORY, 0x00C, 0x00008, 0x08, "Kahlua 8MB"}, 
-	{HPHW_MEMORY, 0x00D, 0x00008, 0x08, "Kahlua 4MB"}, 
-	{HPHW_MEMORY, 0x00E, 0x00008, 0x08, "Tequila 16MB"}, 
-	{HPHW_MEMORY, 0x00F, 0x00008, 0x08, "Tequila 32MB"}, 
-	{HPHW_MEMORY, 0x040, 0x00008, 0x00, "Hitachi"}, 
-	{HPHW_MEMORY, 0x004, 0x00009, 0x00, "Cheetah"}, 
-	{HPHW_MEMORY, 0x005, 0x00009, 0x00, "Emerald"}, 
-	{HPHW_MEMORY, 0x008, 0x00009, 0x00, "Indigo 3MB/5MB"}, 
-	{HPHW_MEMORY, 0x00C, 0x00009, 0x00, "Indigo 8MB"}, 
-	{HPHW_MEMORY, 0x00D, 0x00009, 0x00, "Paradise 4MB"}, 
-	{HPHW_MEMORY, 0x00E, 0x00009, 0x00, "Burgundy Onboard"}, 
-	{HPHW_MEMORY, 0x012, 0x00009, 0x00, "Indigo 12MB/20MB"}, 
-	{HPHW_MEMORY, 0x013, 0x00009, 0x00, "Cobra"}, 
-	{HPHW_MEMORY, 0x014, 0x00009, 0x00, "Nova"}, 
-	{HPHW_MEMORY, 0x015, 0x00009, 0x00, "Coral"}, 
-	{HPHW_MEMORY, 0x016, 0x00009, 0x00, "Bushmaster"}, 
-	{HPHW_MEMORY, 0x017, 0x00009, 0x00, "Scorpio"}, 
-	{HPHW_MEMORY, 0x018, 0x00009, 0x00, "Flounder"}, 
-	{HPHW_MEMORY, 0x019, 0x00009, 0x00, "Hardball"}, 
-	{HPHW_MEMORY, 0x01A, 0x00009, 0x00, "CoralII 99"}, 
-	{HPHW_MEMORY, 0x01B, 0x00009, 0x00, "Scorpio Jr."}, 
-	{HPHW_MEMORY, 0x01C, 0x00009, 0x00, "Strider-50 (715T)"}, 
-	{HPHW_MEMORY, 0x01D, 0x00009, 0x00, "Strider-33 (707T)"}, 
-	{HPHW_MEMORY, 0x01E, 0x00009, 0x00, "Trailways-50 (715S)"}, 
-	{HPHW_MEMORY, 0x01F, 0x00009, 0x00, "Trailways-33 (707S)"}, 
-	{HPHW_MEMORY, 0x020, 0x00009, 0x00, "Pace"}, 
-	{HPHW_MEMORY, 0x021, 0x00009, 0x00, "Sidewinder"}, 
-	{HPHW_MEMORY, 0x022, 0x00009, 0x00, "Orville"}, 
-	{HPHW_MEMORY, 0x023, 0x00009, 0x00, "Wilbur"}, 
-	{HPHW_MEMORY, 0x026, 0x00009, 0x00, "Gecko"}, 
-	{HPHW_MEMORY, 0x027, 0x00009, 0x00, "Scorpio Sr."}, 
-	{HPHW_MEMORY, 0x028, 0x00009, 0x00, "Scorpio 100"}, 
-	{HPHW_MEMORY, 0x029, 0x00009, 0x00, "Spectra 50"}, 
-	{HPHW_MEMORY, 0x02A, 0x00009, 0x00, "CoralII 132"}, 
-	{HPHW_MEMORY, 0x02F, 0x00009, 0x00, "KittyHawk DC2-"}, 
-	{HPHW_MEMORY, 0x030, 0x00009, 0x00, "Spectra 75"}, 
-	{HPHW_MEMORY, 0x031, 0x00009, 0x00, "Spectra 100"}, 
-	{HPHW_MEMORY, 0x032, 0x00009, 0x00, "KittyHawk DC3"}, 
-	{HPHW_MEMORY, 0x033, 0x00009, 0x00, "Fast Pace"}, 
-	{HPHW_MEMORY, 0x034, 0x00009, 0x00, "Snake Eagle"}, 
-	{HPHW_MEMORY, 0x035, 0x00009, 0x00, "Anole 64"}, 
-	{HPHW_MEMORY, 0x036, 0x00009, 0x00, "Anole 100"}, 
-	{HPHW_MEMORY, 0x037, 0x00009, 0x00, "Snake Cheetah"}, 
-	{HPHW_MEMORY, 0x038, 0x00009, 0x00, "Gecko 80"}, 
-	{HPHW_MEMORY, 0x039, 0x00009, 0x00, "Gecko 100"}, 
-	{HPHW_MEMORY, 0x03A, 0x00009, 0x00, "Gecko 120"}, 
-	{HPHW_MEMORY, 0x03B, 0x00009, 0x00, "Gila 80"}, 
-	{HPHW_MEMORY, 0x03C, 0x00009, 0x00, "Gila 100"}, 
-	{HPHW_MEMORY, 0x03D, 0x00009, 0x00, "Gila 120"}, 
-	{HPHW_MEMORY, 0x03E, 0x00009, 0x00, "Scorpio-L 80"}, 
-	{HPHW_MEMORY, 0x03F, 0x00009, 0x00, "Scorpio-L 100"}, 
-	{HPHW_MEMORY, 0x040, 0x00009, 0x00, "Scorpio-L 120"}, 
-	{HPHW_MEMORY, 0x041, 0x00009, 0x00, "Spectra-L 80"}, 
-	{HPHW_MEMORY, 0x042, 0x00009, 0x00, "Spectra-L 100"}, 
-	{HPHW_MEMORY, 0x043, 0x00009, 0x00, "Spectra-L 120"}, 
-	{HPHW_MEMORY, 0x044, 0x00009, 0x00, "Piranha 100"}, 
-	{HPHW_MEMORY, 0x045, 0x00009, 0x00, "Piranha 120"}, 
-	{HPHW_MEMORY, 0x046, 0x00009, 0x00, "Jason 50"}, 
-	{HPHW_MEMORY, 0x047, 0x00009, 0x00, "Jason 100"}, 
-	{HPHW_MEMORY, 0x049, 0x00009, 0x00, "SkyHawk 100/120"}, 
-	{HPHW_MEMORY, 0x04A, 0x00009, 0x00, "Mirage Jr"}, 
-	{HPHW_MEMORY, 0x04B, 0x00009, 0x00, "Mirage 100"}, 
-	{HPHW_MEMORY, 0x04C, 0x00009, 0x00, "Mirage 100+"}, 
-	{HPHW_MEMORY, 0x04D, 0x00009, 0x00, "Electra 100"}, 
-	{HPHW_MEMORY, 0x04E, 0x00009, 0x00, "Electra 120"}, 
-	{HPHW_MEMORY, 0x04F, 0x00009, 0x00, "Mirage 80"}, 
-	{HPHW_MEMORY, 0x050, 0x00009, 0x00, "UL Proc 1 way T'100"}, 
-	{HPHW_MEMORY, 0x051, 0x00009, 0x00, "UL Proc 1 way T'120"}, 
-	{HPHW_MEMORY, 0x052, 0x00009, 0x00, "UL Proc 2 way T'100"}, 
-	{HPHW_MEMORY, 0x053, 0x00009, 0x00, "KittyHawk DC3-"}, 
-	{HPHW_MEMORY, 0x054, 0x00009, 0x00, "UL Proc 2 way T'120"}, 
-	{HPHW_MEMORY, 0x055, 0x00009, 0x00, "Raven 120 mem"}, 
-	{HPHW_MEMORY, 0x056, 0x00009, 0x00, "UL Proc L 75"}, 
-	{HPHW_MEMORY, 0x057, 0x00009, 0x00, "UL Proc L 100"}, 
-	{HPHW_MEMORY, 0x058, 0x00009, 0x00, "Anole T"}, 
-	{HPHW_MEMORY, 0x059, 0x00009, 0x00, "SAIC L-80"}, 
-	{HPHW_MEMORY, 0x05A, 0x00009, 0x00, "Merlin+ L2 180"}, 
-	{HPHW_MEMORY, 0x05B, 0x00009, 0x00, "Raven U 200 2-way"}, 
-	{HPHW_MEMORY, 0x05C, 0x00009, 0x00, "Raven U 180+"}, 
-	{HPHW_MEMORY, 0x05D, 0x00009, 0x00, "Raven U 200"}, 
-	{HPHW_MEMORY, 0x05E, 0x00009, 0x00, "Rocky2 150 Memory"}, 
-	{HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"}, 
-	{HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"}, 
-	{HPHW_MEMORY, 0x05F, 0x00009, 0x00, "SPP2000 Memory"}, 
-	{HPHW_MEMORY, 0x060, 0x00009, 0x00, "Merlin L2 132"}, 
-	{HPHW_MEMORY, 0x061, 0x00009, 0x00, "Merlin+ L2 132"}, 
 	{HPHW_MEMORY, 0x063, 0x00009, 0x00, "712/132 L2 Upgrade"}, 
 	{HPHW_MEMORY, 0x064, 0x00009, 0x00, "712/160 L2 Upgrade"}, 
 	{HPHW_MEMORY, 0x065, 0x00009, 0x00, "715/132 L2 Upgrade"}, 
-	{HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"}, 
-	{HPHW_MEMORY, 0x067, 0x00009, 0x00, "Merlin 160/ThunderHawk Memory"}, 
-	{HPHW_MEMORY, 0x068, 0x00009, 0x00, "LightningHawk Memory"}, 
-	{HPHW_MEMORY, 0x069, 0x00009, 0x00, "Rocky1 Memory"}, 
-	{HPHW_MEMORY, 0x06A, 0x00009, 0x00, "Raven L2 132"}, 
-	{HPHW_MEMORY, 0x06B, 0x00009, 0x00, "Raven L2 160"}, 
-	{HPHW_MEMORY, 0x06C, 0x00009, 0x00, "Raven L2 187"}, 
-	{HPHW_MEMORY, 0x06D, 0x00009, 0x00, "Raven L2 200"}, 
-	{HPHW_MEMORY, 0x06E, 0x00009, 0x00, "Raven U 230"}, 
-	{HPHW_MEMORY, 0x06F, 0x00009, 0x00, "Raven U 240"}, 
-	{HPHW_MEMORY, 0x070, 0x00009, 0x00, "Rocky2 120 Memory"}, 
-	{HPHW_MEMORY, 0x071, 0x00009, 0x00, "Raven U 160"}, 
-	{HPHW_MEMORY, 0x072, 0x00009, 0x00, "Raven U 180"}, 
-	{HPHW_MEMORY, 0x072, 0x00009, 0x00, "UL Proc 1 way T'120 1MB/1MB"}, 
-	{HPHW_MEMORY, 0x073, 0x00009, 0x00, "UL Proc 2 way T'120 1MB/1MB"}, 
-	{HPHW_MEMORY, 0x074, 0x00009, 0x00, "Anole L2 132 memory"}, 
-	{HPHW_MEMORY, 0x075, 0x00009, 0x00, "Anole L2 165 memory"}, 
-	{HPHW_MEMORY, 0x076, 0x00009, 0x00, "UL 1 way U160 512K/512K memory"}, 
-	{HPHW_MEMORY, 0x077, 0x00009, 0x00, "UL 2 way U160 512K/512K memory"}, 
-	{HPHW_MEMORY, 0x078, 0x00009, 0x00, "Kiji L2 132 memory"}, 
-	{HPHW_MEMORY, 0x079, 0x00009, 0x00, "UL 1 way U160 1M/1M memory"}, 
-	{HPHW_MEMORY, 0x07A, 0x00009, 0x00, "UL 2 way U160 1M/1M memory"}, 
-	{HPHW_MEMORY, 0x07B, 0x00009, 0x00, "UL 1 way U180 1M/1M memory"}, 
-	{HPHW_MEMORY, 0x07C, 0x00009, 0x00, "UL 2 way U180 1M/1M memory"}, 
-	{HPHW_MEMORY, 0x07D, 0x00009, 0x00, "UL 1 way U240 U+ 2M/2M memory"}, 
-	{HPHW_MEMORY, 0x07E, 0x00009, 0x00, "UL 2 way U240 U+ 2M/2M memory"}, 
-	{HPHW_MEMORY, 0x07F, 0x00009, 0x00, "UL L2 132 memory"}, 
-	{HPHW_MEMORY, 0x080, 0x00009, 0x00, "UL L2 160 memory"}, 
-	{HPHW_MEMORY, 0x081, 0x00009, 0x00, "Merlin Jr 132 memory"}, 
-	{HPHW_MEMORY, 0x082, 0x00009, 0x00, "FireHawk 200 Memory"}, 
-	{HPHW_MEMORY, 0x083, 0x00009, 0x00, "SummitHawk Memory"}, 
-	{HPHW_MEMORY, 0x084, 0x00009, 0x00, "Jade Upgrade Memory"}, 
-	{HPHW_MEMORY, 0x085, 0x00009, 0x00, "SPP2500 Memory"}, 
-	{HPHW_MEMORY, 0x086, 0x00009, 0x00, "AllegroHigh Memory"}, 
-	{HPHW_MEMORY, 0x087, 0x00009, 0x00, "AllegroLow Memory"}, 
-	{HPHW_MEMORY, 0x088, 0x00009, 0x00, "Forte 2w Memory"}, 
-	{HPHW_MEMORY, 0x089, 0x00009, 0x00, "Forte 4w Memory"}, 
-	{HPHW_MEMORY, 0x08A, 0x00009, 0x00, "Staccato L2 132 Memory"}, 
-	{HPHW_MEMORY, 0x08B, 0x00009, 0x00, "Staccato L2 180 Memory"}, 
-	{HPHW_MEMORY, 0x090, 0x00009, 0x00, "Prelude SMC Memory"}, 
-	{HPHW_MEMORY, 0x091, 0x00009, 0x00, "Lego 360 Memory"}, 
-	{HPHW_MEMORY, 0x7FF, 0x00009, 0x00, "NEC Aska memory"}, 
-	{HPHW_MEMORY, 0x800, 0x00009, 0x00, "Hitachi Tiny 64"}, 
-	{HPHW_MEMORY, 0x801, 0x00009, 0x00, "Hitachi Tiny 80"}, 
-	{HPHW_MEMORY, 0x8FF, 0x00009, 0x00, "Hitachi X memory"}, 
-	{HPHW_MEMORY, 0x091, 0x00009, 0x00, "M2250 Memory"}, 
-	{HPHW_MEMORY, 0x092, 0x00009, 0x00, "M2500 Memory"}, 
-	{HPHW_MEMORY, 0x093, 0x00009, 0x00, "Sonata 440 Memory"}, 
-	{HPHW_MEMORY, 0x094, 0x00009, 0x00, "Sonata 360 Memory"}, 
-	{HPHW_MEMORY, 0x095, 0x00009, 0x00, "Rhapsody 440 Memory"}, 
-	{HPHW_MEMORY, 0x096, 0x00009, 0x00, "Rhapsody 360 Memory"}, 
-	{HPHW_MEMORY, 0x097, 0x00009, 0x00, "Raven W 360 Memory"}, 
-	{HPHW_MEMORY, 0x098, 0x00009, 0x00, "Halfdome W 440 Memory"}, 
-	{HPHW_MEMORY, 0x099, 0x00009, 0x00, "Rhapsody DC- 440 Memory"}, 
-	{HPHW_MEMORY, 0x09A, 0x00009, 0x00, "Rhapsody DC- 360 Memory"}, 
-	{HPHW_MEMORY, 0x09B, 0x00009, 0x00, "Crescendo Memory"}, 
+	{HPHW_MEMORY, 0x066, 0x00009, 0x00, "715/160 L2 Upgrade"},
 	{HPHW_OTHER, 0x004, 0x00030, 0x00, "Master"}, 
 	{HPHW_OTHER, 0x004, 0x00034, 0x00, "Slave"}, 
 	{HPHW_OTHER, 0x004, 0x00038, 0x00, "EDU"}, 
 	{HPHW_OTHER, 0x004, 0x00049, 0x00, "LGB Control"}, 
-        {0, }			/* leave the last entry empty ! */
+	{HPHW_FAULTY, 0, }  /* Special Marker for last entry */
 };
 
 
@@ -1318,7 +1195,7 @@
 	unsigned short model;
 	unsigned short mask;
 	enum cpu_type cpu;
-} hp_cpu_type_mask_list[] = {
+} hp_cpu_type_mask_list[] __initdata = {
 
 	{ 0x0000, 0x0ff0, pcx    },  /* 0x0000 - 0x000f */
 	{ 0x0048, 0x0ff0, pcxl   },  /* 0x0040 - 0x004f */
@@ -1350,8 +1227,10 @@
 	{ 0x0592, 0x0fff, pcxt_  },  /* 0x0592 - 0x0592 */
 	{ 0x0593, 0x0fff, pcxu   },  /* 0x0593 - 0x0593 */
 	{ 0x0594, 0x0ffc, pcxu   },  /* 0x0594 - 0x0597 */
-	{ 0x0598, 0x0ffc, pcxu   },  /* 0x0598 - 0x059b */
-	{ 0x059c, 0x0ffe, pcxu_  },  /* 0x059c - 0x059d */
+	{ 0x0598, 0x0ffe, pcxu_  },  /* 0x0598 - 0x0599 */
+	{ 0x059a, 0x0ffe, pcxu   },  /* 0x059a - 0x059b */
+	{ 0x059c, 0x0fff, pcxu   },  /* 0x059c - 0x059c */
+	{ 0x059d, 0x0fff, pcxu_  },  /* 0x059d - 0x059d */
 	{ 0x059e, 0x0fff, pcxt_  },  /* 0x059e - 0x059e */
 	{ 0x059f, 0x0fff, pcxu   },  /* 0x059f - 0x059f */
 	{ 0x05a0, 0x0ffe, pcxt_  },  /* 0x05a0 - 0x05a1 */
@@ -1370,7 +1249,27 @@
 	{ 0x05ba, 0x0fff, pcxu_  },  /* 0x05ba - 0x05ba */
 	{ 0x05bb, 0x0fff, pcxw   },  /* 0x05bb - 0x05bb */
 	{ 0x05bc, 0x0ffc, pcxw   },  /* 0x05bc - 0x05bf */
-	{ 0x05c0, 0x0fc0, pcxw   },  /* 0x05c0 - 0x05ff */
+	{ 0x05c0, 0x0ffc, pcxw 	 },  /* 0x05c0 - 0x05c3 */
+	{ 0x05c4, 0x0ffe, pcxw 	 },  /* 0x05c4 - 0x05c5 */
+	{ 0x05c6, 0x0fff, pcxw 	 },  /* 0x05c6 - 0x05c6 */
+	{ 0x05c7, 0x0fff, pcxw_  },  /* 0x05c7 - 0x05c7 */
+	{ 0x05c8, 0x0ffc, pcxw 	 },  /* 0x05c8 - 0x05cb */
+	{ 0x05cc, 0x0ffe, pcxw 	 },  /* 0x05cc - 0x05cd */
+	{ 0x05ce, 0x0ffe, pcxw_  },  /* 0x05ce - 0x05cf */
+	{ 0x05d0, 0x0ffc, pcxw_  },  /* 0x05d0 - 0x05d3 */
+	{ 0x05d4, 0x0ffe, pcxw_  },  /* 0x05d4 - 0x05d5 */
+	{ 0x05d6, 0x0fff, pcxw 	 },  /* 0x05d6 - 0x05d6 */
+	{ 0x05d7, 0x0fff, pcxw_  },  /* 0x05d7 - 0x05d7 */
+	{ 0x05d8, 0x0ffc, pcxw_  },  /* 0x05d8 - 0x05db */
+	{ 0x05dc, 0x0ffe, pcxw2  },  /* 0x05dc - 0x05dd */
+	{ 0x05de, 0x0fff, pcxw_  },  /* 0x05de - 0x05de */
+	{ 0x05df, 0x0fff, pcxw2  },  /* 0x05df - 0x05df */
+	{ 0x05e0, 0x0ffc, pcxw2  },  /* 0x05e0 - 0x05e3 */
+	{ 0x05e4, 0x0fff, pcxw2  },  /* 0x05e4 - 0x05e4 */
+	{ 0x05e5, 0x0fff, pcxw_  },  /* 0x05e5 - 0x05e5 */
+	{ 0x05e6, 0x0ffe, pcxw2  },  /* 0x05e6 - 0x05e7 */
+	{ 0x05e8, 0x0ff8, pcxw2  },  /* 0x05e8 - 0x05ef */
+	{ 0x05f0, 0x0ff0, pcxw2  },  /* 0x05f0 - 0x05ff */
 	{ 0x0600, 0x0ff0, pcxl   },  /* 0x0600 - 0x060f */
 	{ 0x0610, 0x0ff0, pcxl   },  /* 0x0610 - 0x061f */
 	{ 0x0000, 0x0000, pcx    }	/* terminate table */
@@ -1386,36 +1285,51 @@
 	[pcxu]	{ "PA8000 (PCX-U)",	"2.0" },
 	[pcxu_]	{ "PA8200 (PCX-U+)",	"2.0" },
 	[pcxw]	{ "PA8500 (PCX-W)",	"2.0" },
-	[pcxw_]	{ "PA8600 (PCX-W+)",	"2.0" }
+	[pcxw_]	{ "PA8600 (PCX-W+)",	"2.0" },
+	[pcxw2]	{ "PA8700 (PCX-W2)",	"2.0" }
 };
 
-char *parisc_getHWtype(unsigned short hw_type)
-{
-	if (hw_type <= HPHW_CIO) {
-		return hw_type_name[hw_type];
-	} else {
-		return "Unknown Type";
-	}
-}
-
-char *parisc_getHWdescription(unsigned short hw_type, unsigned long hversion,
-		unsigned long sversion)
+const char * __init
+parisc_hardware_description(struct parisc_device_id *id)
 {
 	struct hp_hardware *listptr;
 	
-	for (listptr = hp_hardware_list; listptr->name; listptr++) {
-		if ((listptr->hw_type==hw_type) &&
-				(listptr->hversion==hversion) &&
-				(listptr->sversion==sversion)){
+	for (listptr = hp_hardware_list; listptr->hw_type != HPHW_FAULTY; listptr++) {
+		if ((listptr->hw_type == id->hw_type) &&
+				(listptr->hversion == id->hversion) &&
+				(listptr->sversion == id->sversion)){
 			return listptr->name;
 		}
 	}
+
+	/*
+	 * ok, the above hardware table isn't complete, and we haven't found
+	 * our device in this table. So let's now try to find a generic name
+	 * to describe the given hardware...
+	 */
+	switch (id->hw_type) {
+		case HPHW_NPROC:
+			return "Unknown machine";
+
+		case HPHW_A_DIRECT:
+			switch (id->sversion) {
+				case 0x0D: return "MUX port";
+				case 0x0E: return "RS-232 port";
+			}
+			break;
+			
+		case HPHW_MEMORY:
+			return "Memory";
+			
+	}
+	
 	return "unknown device";
 }
 
 
 /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */
-enum cpu_type parisc_get_cpu_type(unsigned long hversion)
+enum cpu_type __init
+parisc_get_cpu_type(unsigned long hversion)
 {
 	struct hp_cpu_type_mask *ptr;
 	unsigned short model = ((unsigned short) (hversion)) >> 4;
@@ -1424,23 +1338,8 @@
 		if (ptr->model == (model & ptr->mask))
 			return ptr->cpu;
 	}
-	panic("parisc_get_cpu_type() could not identify CPU type\n");
+	panic("could not identify CPU type\n");
 
 	return pcx;	/* not reached: */
 }
 
-
-struct hp_hardware *parisc_get_reference(unsigned short hw_type,
-		unsigned long hversion, unsigned long sversion)
-{
-	struct hp_hardware *listptr = hp_hardware_list;
-
-	for (listptr = hp_hardware_list; listptr->name; listptr++) {
-		if ((listptr->hw_type == hw_type) &&
-				(listptr->hversion == hversion) &&
-				(listptr->sversion == sversion)) {
-			return listptr;
-		}
-	}
-	return NULL;
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/head.S linux/arch/parisc/kernel/head.S
--- linux.orig/arch/parisc/kernel/head.S	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/head.S	2002-08-12 22:14:25.000000000 +0000
@@ -8,17 +8,14 @@
  * Copyright 1999 SuSE GmbH (Philipp Rumpf)
  * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
  *
- * Initial Version 04-23-1999 by Helge Deller (helge.deller@ruhr-uni-bochum.de)
+ * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
  */
 
+#include <linux/autoconf.h>	/* for CONFIG_SMP */
 
 #include <asm/offset.h>
 #include <asm/psw.h>
 
-#define __ASSEMBLY__
-/*********
-#include <asm/pdc.h>
-*********/
 #include <asm/assembly.h>
 #include <asm/pgtable.h>
 
@@ -36,6 +33,15 @@
 	.export __setup_end
 __setup_end:
 
+	.data
+
+	.export boot_args
+boot_args:
+	.word 0 /* arg0 */
+	.word 0 /* arg1 */
+	.word 0 /* arg2 */
+	.word 0 /* arg3 */
+
 	.text
 	.align	4	
 	.import init_task_union,data
@@ -52,43 +58,129 @@
 	.callinfo
 
 	/* Make sure sr4-sr7 are set to zero for the kernel address space */
-
-	mtsp		%r0,%sr4
-	mtsp		%r0,%sr5
-	mtsp		%r0,%sr6
-	mtsp		%r0,%sr7
+	mtsp	%r0,%sr4
+	mtsp	%r0,%sr5
+	mtsp	%r0,%sr6
+	mtsp	%r0,%sr7
+
+	/* Clear BSS (shouldn't the boot loader do this?) */
+
+	.import _edata,data
+	.import _end,data
+
+	ldil            L%PA(_edata),%r3
+	ldo             R%PA(_edata)(%r3),%r3
+	ldil            L%PA(_end),%r4
+	ldo             R%PA(_end)(%r4),%r4
+$bss_loop:
+	cmpb,<<,n       %r3,%r4,$bss_loop
+	stb,ma          %r0,1(%r3)
+
+	/* Save away the arguments the boot loader passed in (32 bit args) */
+
+	ldil            L%PA(boot_args),%r1
+	ldo             R%PA(boot_args)(%r1),%r1
+	stw,ma          %arg0,4(%r1)
+	stw,ma          %arg1,4(%r1)
+	stw,ma          %arg2,4(%r1)
+	stw,ma          %arg3,4(%r1)
 
 	/* Initialize startup VM. Just map first 8 MB of memory */
-
 	ldil		L%PA(pg0),%r1
 	ldo		R%PA(pg0)(%r1),%r1
 	ldo		_PAGE_TABLE(%r1),%r3
+
 	ldil		L%PA(swapper_pg_dir),%r4
 	ldo		R%PA(swapper_pg_dir)(%r4),%r4
 	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
 	mtctl		%r4,%cr25	/* Initialize user root pointer */
-	stw		%r3,0xc00(%r4)	/* Hardwired 0xc0000000 kernel vaddr start */
+
+#if (__PAGE_OFFSET != 0x10000000UL)
+Error! Code below (the next two stw's) needs to be changed
+#endif
+
+	stw             %r3,0x100(%r4)  /* Hardwired 0x1... kernel Vaddr start*/
 	ldo		0x1000(%r3),%r3
-	stw		%r3,0xc04(%r4)
-	ldo		_PAGE_KERNEL(%r0),%r3 /* Hardwired 0x0 phys addr start */
+	stw             %r3,0x104(%r4)
+	ldo		_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
 $pgt_fill_loop:
 	stwm		%r3,4(%r1)
 	ldo		0x1000(%r3),%r3
 	bb,>=		%r3,8,$pgt_fill_loop
 	nop
 
+
+	/* Load the return address...er...crash 'n burn */
+	copy		%r0,%r2
+
+	/* And the RFI Target address too */
+	ldil            L%start_kernel,%r11
+	ldo             R%start_kernel(%r11),%r11
+
+	/* And the initial task pointer */
+
+	ldil            L%init_task_union,%r6
+	ldo             R%init_task_union(%r6),%r6
+	mtctl           %r6,%cr30
+
+	/* And the stack pointer too */
+
+	ldo             TASK_SZ_ALGN(%r6),%sp
+
+	/* And the interrupt stack */
+
+	ldil            L%interrupt_stack,%r6
+	ldo             R%interrupt_stack(%r6),%r6
+	mtctl           %r6,%cr31
+
+#ifdef CONFIG_SMP
+	/* Set the smp rendevous address into page zero.
+	** It would be safer to do this in init_smp_config() but
+	** it's just way easier to deal with here because
+	** of 64-bit function ptrs and the address is local to this file.
+	*/
+	ldil		L%PA(smp_slave_stext),%r10
+	ldo		R%PA(smp_slave_stext)(%r10),%r10
+	stw		%r10,0x10(%r0)	/* MEM_RENDEZ */
+	stw		%r0,0x28(%r0)	/* MEM_RENDEZ_HI - assume addr < 4GB */
+
+	/* FALLTHROUGH */
+	.procend
+
+	/*
+	** Code Common to both Monarch and Slave processors.
+	** Entry:
+	**    %r11 must contain RFI target address.
+	**    %r25/%r26 args to pass to target function
+	**    %r2  in case rfi target decides it didn't like something
+	**
+	** Caller must init: SR4-7, %sp, %r10, %cr24/25, 
+	*/
+common_stext:
+	.proc
+	.callinfo
+#else
+	/* Clear PDC entry point - we won't use it */
+	stw		%r0,0x10(%r0)	/* MEM_RENDEZ */
+	stw		%r0,0x28(%r0)	/* MEM_RENDEZ_HI */
+#endif
+
+	/* PARANOID: clear user scratch/user space SR's */
+	mtsp	%r0,%sr0
+	mtsp	%r0,%sr1
+	mtsp	%r0,%sr2
+	mtsp	%r0,%sr3
+
+	/* Initialize Protection Registers */
+	mtctl	%r0,%cr8
+	mtctl	%r0,%cr9
+	mtctl	%r0,%cr12
+	mtctl	%r0,%cr13
+
 	/* Initialize the global data pointer */
 	ldil		L%$global$,%dp
 	ldo		R%$global$(%dp),%dp
-	
-	/* And the stack pointer, physical too */
-	ldil		L%init_task_union+TASK_SZ_ALGN,%sp
-	ldo		R%init_task_union+TASK_SZ_ALGN(%sp),%sp
-
-	/* we need this to take interruptions directly after the rfi below */
-	/* (which we need for PA2.0 boxes) */
-	mtctl		%r0, %cr30
-	
+
 	/*
 	 * Set up our interrupt table.  HPMCs might not work after this! 
 	 *
@@ -96,7 +188,6 @@
 	 * following short sequence of instructions can determine this
 	 * (without being illegal on a PA1.1 machine).
 	 */
-	
 	ldi		32,%r10
 	mtctl		%r10,%cr11
 	.level 2.0
@@ -114,30 +205,30 @@
 $install_iva:
 	mtctl		%r10,%cr14
 
-	/* Disable (most) interruptions */
-	mtsm		%r0			
-	
+	/* Disable Q bit so we can load the iia queue */
+	rsm            PSW_SM_Q,%r0
+
 	/* kernel PSW:
-	 *  - no interruptions except for HPMC and TOC (which are handled by PDC)
+	 *  - no interruptions except HPMC and TOC (which are handled by PDC)
 	 *  - Q bit set (IODC / PDC interruptions)
 	 *  - big-endian
 	 *  - virtually mapped
 	 */
-
 	ldil		L%KERNEL_PSW,%r10
 	ldo		R%KERNEL_PSW(%r10),%r10
 	mtctl		%r10,%ipsw
-	
-	/* Set the space pointers for the post-RFI world */
-	mtctl		%r0,%cr17		/* Clear two-level IIA Space Queue */
-	mtctl		%r0,%cr17		/*    effectively setting kernel space. */
-
-	/* And the return address(es) too */
-	ldil		L%start_parisc,%r10
-	ldo		R%start_parisc(%r10),%r10
-	mtctl		%r10,%cr18
-	ldo		4(%r10),%r10
-	mtctl		%r10,%cr18
+
+	/* Set the space pointers for the post-RFI world
+	** Clear the two-level IIA Space Queue, effectively setting
+	** Kernel space.
+	*/
+	mtctl		%r0,%cr17
+	mtctl		%r0,%cr17
+
+	/* Load RFI target into PC queue */
+	mtctl		%r11,%cr18
+	ldo		4(%r11),%r11
+	mtctl		%r11,%cr18
 
 	/* Jump to hyperspace */
 	rfi
@@ -145,6 +236,71 @@
 
 	.procend
 
+#ifdef CONFIG_SMP
+
+	.import smp_init_current_idle_task,data
+	.import	smp_callin,code
+
+smp_callin_rtn:
+        .proc
+	.callinfo
+	break	1,1		/*  Break if returned from start_secondary */
+	nop
+	nop
+        .procend
+
+/***************************************************************************
+*
+* smp_slave_stext is executed by all non-monarch Processors when the Monarch
+* pokes the slave CPUs in smp.c:smp_boot_cpus().
+*
+* Once here, registers values are initialized in order to branch to virtual
+* mode. Once all available/eligible CPUs are in virtual mode, all are
+* released and start out by executing their own idle task.
+*****************************************************************************/
+
+
+smp_slave_stext:
+        .proc
+	.callinfo
+
+	/*
+	** Initialize Space registers
+	*/
+	mtsp	   %r0,%sr4
+	mtsp	   %r0,%sr5
+	mtsp	   %r0,%sr6
+	mtsp	   %r0,%sr7
+
+	/*  Initialize the SP - monarch sets up smp_init_current_idle_task */
+	ldil		L%PA(smp_init_current_idle_task),%sp
+	ldo		R%PA(smp_init_current_idle_task)(%sp),%sp
+	ldw		0(%sp),%sp	/* load task address */
+	mtctl           %sp,%cr30       /* store in cr30 */
+	addil		L%TASK_SZ_ALGN,%sp	/* stack is above task */
+	ldo		R%TASK_SZ_ALGN(%r1),%sp
+
+	/* point CPU to kernel page tables */
+	ldil		L%PA(swapper_pg_dir),%r4
+	ldo		R%PA(swapper_pg_dir)(%r4),%r4
+	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
+	mtctl		%r4,%cr25	/* Initialize user root pointer */
+
+	/* Load RFI *return* address in case smp_callin bails */
+	ldil		L%smp_callin_rtn,%r2
+	ldo		R%smp_callin_rtn(%r2),%r2
+
+	/* Load RFI target address.  */
+	ldil		L%smp_callin,%r11
+	ldo		R%smp_callin(%r11),%r11
+	
+	/* ok...common code can handle the rest */
+	b		common_stext
+	nop
+
+	.procend
+#endif /* CONFIG_SMP */
+
 	.data
 
 	.align	4
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/head64.S linux/arch/parisc/kernel/head64.S
--- linux.orig/arch/parisc/kernel/head64.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/head64.S	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,333 @@
+/*
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1999 by Helge Deller
+ * Copyright 1999 SuSE GmbH (Philipp Rumpf)
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ * Copyright 2000 Hewlett Packard (Paul Bame, bame@puffin.external.hp.com)
+ * Copyright (C) 2001 Grant Grundler (Hewlett Packard)
+ *
+ * Initial Version 04-23-1999 by Helge Deller <deller@gmx.de>
+ */
+
+
+#include <linux/autoconf.h>	/* for CONFIG_SMP */
+
+#include <asm/offset.h>
+#include <asm/psw.h>
+
+#include <asm/assembly.h>
+#include <asm/pgtable.h>
+#include <asm/pdc.h>		/* for PDC_PSW defines */
+
+
+	.level 2.0
+
+	.section	.initcall.init
+	.align		4
+	.export __initcall_start
+__initcall_start:
+	.export __initcall_end
+__initcall_end:
+	.export __setup_start
+__setup_start:
+	.export __setup_end
+__setup_end:
+
+	.data
+
+	.export boot_args
+boot_args:
+	.word 0 /* arg0 */
+	.word 0 /* arg1 */
+	.word 0 /* arg2 */
+	.word 0 /* arg3 */
+
+	.text
+	.align	4	
+
+	.export stext
+	.export _stext,data		/* Kernel want it this way! */
+_stext:
+stext:
+	.proc
+	.callinfo
+
+	/* Make sure sr4-sr7 are set to zero for the kernel address space */
+	mtsp	%r0,%sr4
+	mtsp	%r0,%sr5
+	mtsp	%r0,%sr6
+	mtsp	%r0,%sr7
+
+	/* Clear BSS (shouldn't the boot loader do this?) */
+
+	.import _edata,data
+	.import _end,data
+
+	ldil            L%PA(_edata),%r3
+	ldo             R%PA(_edata)(%r3),%r3
+	ldil            L%PA(_end),%r4
+	ldo             R%PA(_end)(%r4),%r4
+$bss_loop:
+	cmpb,<<,n       %r3,%r4,$bss_loop
+	stb,ma          %r0,1(%r3)
+
+	/* Save away the arguments the boot loader passed in (32 bit args) */
+
+	ldil            L%PA(boot_args),%r1
+	ldo             R%PA(boot_args)(%r1),%r1
+	stw,ma          %arg0,4(%r1)
+	stw,ma          %arg1,4(%r1)
+	stw,ma          %arg2,4(%r1)
+	stw,ma          %arg3,4(%r1)
+
+	/* Initialize startup VM. Just map first 8 MB of memory */
+
+	ldil		L%PA(pg0),%r1
+	ldo		R%PA(pg0)(%r1),%r1
+
+	ldil		L%PA(pmd0),%r5
+	ldo		R%PA(pmd0)(%r5),%r5
+	ldo		_PAGE_TABLE(%r5),%r3
+
+	ldil		L%PA(swapper_pg_dir),%r4
+	ldo		R%PA(swapper_pg_dir)(%r4),%r4
+
+	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
+	mtctl		%r4,%cr25	/* Initialize user root pointer */
+
+#if (__PAGE_OFFSET != 0x10000000UL)
+Error! Code below (the next five std's) needs to be changed
+#endif
+
+	std             %r3,0x00(%r4)   /* Hardwired 0x1... kernel Vaddr start*/
+
+	ldo		_PAGE_TABLE(%r1),%r3
+	std             %r3,0x400(%r5)  /* Hardwired 0x1... kernel Vaddr start*/
+	ldo		0x1000(%r3),%r3
+	std             %r3,0x408(%r5)
+	ldo		0x1000(%r3),%r3
+	std             %r3,0x410(%r5)
+	ldo		0x1000(%r3),%r3
+	std             %r3,0x418(%r5)
+
+	ldo		_PAGE_KERNEL(%r0),%r3 /* Hardwired 0 phys addr start */
+$pgt_fill_loop:
+	std,ma		%r3,8(%r1)
+	ldo		0x1000(%r3),%r3
+	bb,>=		%r3,8,$pgt_fill_loop
+	nop
+
+	/* And the RFI Target address too */
+	load32          start_kernel, %r11
+
+	/* And the stack pointer too */
+	load32		PA(init_task_union+TASK_SZ_ALGN),%sp
+
+	/* And the initial task pointer */
+
+	load32          init_task_union,%r6
+	mtctl           %r6,%cr30
+
+	/* And the interrupt stack */
+
+	load32          interrupt_stack,%r6
+	mtctl           %r6,%cr31
+
+	/* Act like PDC just called us - that's how slave CPUs enter */
+#define MEM_PDC_LO 0x388
+#define MEM_PDC_HI 0x35C
+	ldw		MEM_PDC_LO(%r0),%r3
+	ldw		MEM_PDC_HI(%r0),%r6
+	depd		%r6, 31, 32, %r3	/* move to upper word */
+
+#ifdef CONFIG_SMP
+	/* Set the smp rendevous address into page zero.
+	** It would be safer to do this in init_smp_config() but
+	** it's just way easier to deal with here because
+	** of 64-bit function ptrs and the address is local to this file.
+	*/
+	ldil		L%PA(smp_slave_stext),%r10
+	ldo		R%PA(smp_slave_stext)(%r10),%r10
+	stw		%r10,0x10(%r0)	/* MEM_RENDEZ */
+	stw		%r0,0x28(%r0)	/* MEM_RENDEZ_HI - assume addr < 4GB */
+
+	/* FALLTHROUGH */
+	.procend
+
+	/*
+	** Code Common to both Monarch and Slave processors.
+	** Entry:
+	**    %r3	PDCE_PROC address
+	**    %r11	RFI target address.
+	**
+	** Caller must init: SR4-7, %sp, %r10, %cr24/25, 
+	*/
+common_stext:
+	.proc
+	.callinfo
+#else /* CONFIG_SMP */
+	/* Clear PDC's CPU handoff address - we won't use it */
+	stw		%r0,0x10(%r0)	/* MEM_RENDEZ */
+	stw		%r0,0x28(%r0)	/* MEM_RENDEZ_HI */
+#endif /* CONFIG_SMP */
+
+	/* Save the rfi target address */
+	std		%r11,  TASK_PT_GR11-TASK_SZ_ALGN(%sp)
+
+#ifndef CONFIG_PDC_NARROW
+	/* Switch to wide mode; Superdome doesn't support narrow PDC
+	** calls.
+	*/
+1:	mfia		%rp		/* clear upper part of pcoq */
+	ldo		2f-1b(%rp),%rp
+	depdi		0,31,32,%rp
+	bv		(%rp)
+	ssm		PSW_SM_W,%r0
+2:
+#endif /* CONFIG_PDC_NARROW */
+
+	/* Set Wide mode as the "Default" (eg for traps)
+	** First trap occurs *right* after (or part of) rfi for slave CPUs.
+	** Someday, palo might not do this for the Monarch either.
+	*/
+
+	ldo		PDC_PSW(%r0),%arg0		/* 21 */
+	ldo		PDC_PSW_SET_DEFAULTS(%r0),%arg1	/* 2 */
+	ldo		PDC_PSW_WIDE_BIT(%r0),%arg2	/* 2 */
+
+	load32		PA(stext_pdc_ret), %rp
+
+	bv		(%r3)
+	copy		%r0,%arg3
+
+stext_pdc_ret:
+	/* restore rfi target address*/
+	ldd		TASK_PT_GR11-TASK_SZ_ALGN(%sp), %r11
+
+	/* PARANOID: clear user scratch/user space SR's */
+	mtsp	%r0,%sr0
+	mtsp	%r0,%sr1
+	mtsp	%r0,%sr2
+	mtsp	%r0,%sr3
+
+	/* Initialize Protection Registers */
+	mtctl	%r0,%cr8
+	mtctl	%r0,%cr9
+	mtctl	%r0,%cr12
+	mtctl	%r0,%cr13
+
+	/* Prepare to RFI! Man all the cannons! */
+	tovirt_r1       %sp
+
+	/* Initialize the global data pointer */
+	load32		__gp,%dp
+
+	/* Set up our interrupt table.  HPMCs might not work after this! */
+	ldil		L%PA(fault_vector_20),%r10
+	ldo		R%PA(fault_vector_20)(%r10),%r10
+	mtctl		%r10,%cr14
+
+	b		aligned_rfi
+	nop
+
+	/* the magic spell */
+	.align          256
+aligned_rfi:
+	ssm		0,0
+	nop		/* 1 */
+	nop		/* 2 */
+	nop		/* 3 */
+	nop		/* 4 */
+	nop		/* 5 */
+	nop		/* 6 */
+	nop		/* 7 */
+	nop		/* 8 */
+
+	/* turn off troublesome PSW bits */
+	rsm		PSW_Q+PSW_I+PSW_D+PSW_P+PSW_R, %r0
+
+	/* kernel PSW:
+	 *  - no interruptions except HPMC and TOC (which are handled by PDC)
+	 *  - Q bit set (IODC / PDC interruptions)
+	 *  - big-endian
+	 *  - virtually mapped
+	 */
+	load32		KERNEL_PSW,%r10
+	mtctl		%r10,%ipsw
+
+	/* Set the space pointers for the post-RFI world
+	** Clear the two-level IIA Space Queue, effectively setting
+	** Kernel space.
+	*/
+	mtctl		%r0,%cr17
+	mtctl		%r0,%cr17
+
+	/* Load RFI target into PC queue */
+	mtctl		%r11,%cr18
+	ldo		4(%r11),%r11
+	mtctl		%r11,%cr18
+
+	/* Jump to hyperspace */
+	rfi
+	nop
+
+	.procend
+
+
+#ifdef CONFIG_SMP
+
+	.import smp_init_current_idle_task,data
+	.import	smp_callin,code
+
+/***************************************************************************
+*
+* smp_slave_stext is executed by all non-monarch Processors when the Monarch
+* pokes the slave CPUs in smp.c:smp_boot_cpus().
+*
+* Once here, registers values are initialized in order to branch to virtual
+* mode. Once all available/eligible CPUs are in virtual mode, all are
+* released and start out by executing their own idle task.
+*****************************************************************************/
+
+
+smp_slave_stext:
+        .proc
+	.callinfo
+
+	/*
+	** Initialize Space registers
+	*/
+	mtsp	   %r0,%sr4
+	mtsp	   %r0,%sr5
+	mtsp	   %r0,%sr6
+	mtsp	   %r0,%sr7
+
+	/*  Initialize the SP - monarch sets up smp_init_current_idle_task */
+	load32		PA(smp_init_current_idle_task),%sp
+	ldd		0(%sp),%sp	/* load task address */
+	mtctl           %sp,%cr30       /* store in cr30 */
+	ldo             TASK_SZ_ALGN(%sp),%sp
+	tophys_r1       %sp
+
+	/* point CPU to kernel page tables */
+	load32		PA(swapper_pg_dir),%r4
+	mtctl		%r4,%cr24	/* Initialize kernel root pointer */
+	mtctl		%r4,%cr25	/* Initialize user root pointer */
+
+	/* Setup PDCE_PROC entry */
+	copy		%arg0,%r3
+
+	/* Load RFI target address.  */
+	load32		smp_callin, %r11
+	
+	/* ok...common code can handle the rest */
+	b		common_stext
+	nop
+
+	.procend
+#endif /* CONFIG_SMP */
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/hpmc.S linux/arch/parisc/kernel/hpmc.S
--- linux.orig/arch/parisc/kernel/hpmc.S	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/hpmc.S	2002-08-12 22:14:13.000000000 +0000
@@ -43,7 +43,6 @@
 	.level		1.1
 	.data
 
-#define __ASSEMBLY__
 #include <asm/assembly.h>
 #include <asm/pdc.h>
 
@@ -262,12 +261,10 @@
 	mtsp	%r0, %sr6
 	mtsp	%r0, %sr7
 
-	tovirt  %r30        /* make sp virtual */
+	tovirt_r1 %r30      /* make sp virtual */
 
 	rsm 8,%r0           /* Clear Q bit */
-	ldi     1,%r1
-	mtctl   %r1,%cr29   /* Set trap code to "1" for HPMC */
-	mtctl   %r0,%cr30   /* Force interruptions to use hpmc stack */
+	ldi     1,%r8       /* Set trap code to "1" for HPMC */
 	ldil    L%PA(intr_save), %r1
 	ldo     R%PA(intr_save)(%r1), %r1
 	be      0(%sr7,%r1)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/init_task.c linux/arch/parisc/kernel/init_task.c
--- linux.orig/arch/parisc/kernel/init_task.c	2001-09-17 22:29:09.000000000 +0000
+++ linux/arch/parisc/kernel/init_task.c	2002-08-12 22:14:00.000000000 +0000
@@ -18,10 +18,11 @@
  * way process stacks are handled. This is done by having a special
  * "init_task" linker map entry..
  */
+unsigned char interrupt_stack[ISTACK_SIZE] __attribute__ ((section("init_istack"), aligned(4096)));
 union task_union init_task_union 
 	__attribute__((section("init_task"), aligned(4096))) = { INIT_TASK(init_task_union.task) };
 
-unsigned long swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { 0, };
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__ ((aligned(4096))) = { {0}, };
 #ifdef __LP64__
 unsigned long pmd0[PTRS_PER_PMD] __attribute__ ((aligned(4096))) = { 0, };
 #endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/inventory.c linux/arch/parisc/kernel/inventory.c
--- linux.orig/arch/parisc/kernel/inventory.c	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/kernel/inventory.c	2002-08-12 22:14:03.000000000 +0000
@@ -1,40 +1,157 @@
-
-/* Copyright (c) 1999 The Puffin Group */
-/* Written by David Kennedy and Alex deVries */
+/*
+ * inventory.c
+ *
+ * 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.
+ *
+ * Copyright (c) 1999 The Puffin Group (David Kennedy and Alex deVries)
+ * Copyright (c) 2001 Matthew Wilcox for Hewlett-Packard
+ *
+ * These are the routines to discover what hardware exists in this box.
+ * This task is complicated by there being 3 different ways of
+ * performing an inventory, depending largely on the age of the box.
+ * The recommended way to do this is to check to see whether the machine
+ * is a `Snake' first, then try System Map, then try PAT.  We try System
+ * Map before checking for a Snake -- this probably doesn't cause any
+ * problems, but...
+ */
 
 #include <linux/types.h>
 #include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/pdc.h>
+#include <asm/processor.h>
+#include <asm/page.h>
 
 /*
 ** Debug options
-**    DEBUG_PAT	Dump details which PDC PAT provides about ranges/devices.
+** DEBUG_PAT Dump details which PDC PAT provides about ranges/devices.
 */
 #undef DEBUG_PAT
 
-extern char *parisc_getHWtype(unsigned short hw_type);
+int pdc_type = PDC_TYPE_ILLEGAL;
+
+void __init setup_pdc(void)
+{
+	long status;
+	unsigned int bus_id;
+	struct pdc_system_map_mod_info module_result;
+	struct pdc_module_path module_path;
+	struct pdc_model model;
+#ifdef __LP64__
+	struct pdc_pat_cell_num cell_info;
+#endif
 
-extern struct hp_device * register_module(void *hpa);
-extern void print_devices(char * buf);
+	/* Determine the pdc "type" used on this machine */
 
+	printk(KERN_INFO "Determining PDC firmware type: ");
 
-int pdc_hpa_processor(void *address);
+	status = pdc_system_map_find_mods(&module_result, &module_path, 0);
+	if (status == PDC_OK) {
+		pdc_type = PDC_TYPE_SYSTEM_MAP;
+		printk("System Map.\n");
+		return;
+	}
 
-#ifndef __LP64__ 
-static	u8 iodc_data[32] __attribute__ ((aligned (64)));
-static	struct pdc_model model __attribute__ ((aligned (8)));
+	/*
+	 * If the machine doesn't support PDC_SYSTEM_MAP then either it
+	 * is a pdc pat box, or it is an older box. All 64 bit capable
+	 * machines are either pdc pat boxes or they support PDC_SYSTEM_MAP.
+	 */
+
+	/*
+	 * TODO: We should test for 64 bit capability and give a
+	 * clearer message.
+	 */
+
+#ifdef __LP64__
+	status = pdc_pat_cell_get_number(&cell_info);
+	if (status == PDC_OK) {
+		pdc_type = PDC_TYPE_PAT;
+		printk("64 bit PAT.\n");
+		return;
+	}
 #endif
-static	unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
-static	struct pdc_hpa processor_hpa __attribute__ ((aligned (8)));
-static	struct pdc_system_map module_result __attribute__ ((aligned (8)));
-static	struct pdc_module_path module_path __attribute__ ((aligned (8)));
+
+	/* Check the CPU's bus ID.  There's probably a better test.  */
+
+	status = pdc_model_info(&model);
+
+	bus_id = (model.hversion >> (4 + 7)) & 0x1f;
+
+	switch (bus_id) {
+	case 0x4:		/* 720, 730, 750, 735, 755 */
+	case 0x6:		/* 705, 710 */
+	case 0x7:		/* 715, 725 */
+	case 0x8:		/* 745, 747, 742 */
+	case 0xA:		/* 712 and similiar */
+	case 0xC:		/* 715/64, at least */
+
+		pdc_type = PDC_TYPE_SNAKE;
+		printk("Snake.\n");
+		return;
+
+	default:		/* Everything else */
+
+		printk("Unsupported.\n");
+		panic("If this is a 64-bit machine, please try a 64-bit kernel.\n");
+	}
+}
+
+#define PDC_PAGE_ADJ_SHIFT (PAGE_SHIFT - 12) /* pdc pages are always 4k */
+
+static void __init
+set_pmem_entry(physmem_range_t *pmem_ptr, unsigned long start,
+	       unsigned long pages4k)
+{
+	/* Rather than aligning and potentially throwing away
+	 * memory, we'll assume that any ranges are already
+	 * nicely aligned with any reasonable page size, and
+	 * panic if they are not (it's more likely that the
+	 * pdc info is bad in this case).
+	 */
+
+	if (   ((start & (PAGE_SIZE - 1)) != 0)
+	    || ((pages4k & ((1UL << PDC_PAGE_ADJ_SHIFT) - 1)) != 0) ) {
+
+		panic("Memory range doesn't align with page size!\n");
+	}
+
+	pmem_ptr->start_pfn = (start >> PAGE_SHIFT);
+	pmem_ptr->pages = (pages4k >> PDC_PAGE_ADJ_SHIFT);
+}
+
+static void __init pagezero_memconfig(void)
+{
+	unsigned long npages;
+
+	/* Use the 32 bit information from page zero to create a single
+	 * entry in the pmem_ranges[] table.
+	 *
+	 * We currently don't support machines with contiguous memory
+	 * >= 4 Gb, who report that memory using 64 bit only fields
+	 * on page zero. It's not worth doing until it can be tested,
+	 * and it is not clear we can support those machines for other
+	 * reasons.
+	 *
+	 * If that support is done in the future, this is where it
+	 * should be done.
+	 */
+
+	npages = (PAGE_ALIGN(PAGE0->imm_max_mem) >> PAGE_SHIFT);
+	set_pmem_entry(pmem_ranges,0UL,npages);
+	npmem_ranges = 1;
+}
 
 #ifdef __LP64__
-#include <asm/pdcpat.h>
 
-int pdc_pat = 0;
+/* All of the PDC PAT specific code is 64-bit only */
 
 /*
 **  The module object is filled via PDC_PAT_CELL[Return Cell Module].
@@ -47,30 +164,37 @@
 **
 */
 
-static int
-pat_query_module( ulong pcell_loc, ulong mod_index)
+static int __init 
+pat_query_module(ulong pcell_loc, ulong mod_index)
 {
-	extern int num_devices;
-	extern struct hp_device devices[];
-
 	pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
-        struct hp_device * dev = &devices[num_devices];
-	uint64_t temp;             /* 64-bit scratch value */
-	long status;               /* PDC return value status */
+	pdc_pat_cell_mod_maddr_block_t io_pdc_cell;
+	unsigned long bytecnt;
+	unsigned long temp;	/* 64-bit scratch value */
+	long status;		/* PDC return value status */
+	struct parisc_device *dev;
 
 	/* return cell module (PA or Processor view) */
-	status = pdc_pat_cell_module(& pdc_result, pcell_loc, mod_index,
-		PA_VIEW, & pa_pdc_cell);
+	status = pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
+				     PA_VIEW, &pa_pdc_cell);
 
-	if (status != PDC_RET_OK) {
+	if (status != PDC_OK) {
 		/* no more cell modules or error */
 		return status;
 	}
 
+	temp = pa_pdc_cell.cba;
+	dev = alloc_pa_dev(PAT_GET_CBA(temp), &pa_pdc_cell.mod_path);
+	if (!dev) {
+		return PDC_NE_MOD;
+	}
+
+	/* alloc_pa_dev sets dev->hpa */
+
 	/*
-	** save parameters in the hp_device
+	** save parameters in the parisc_device
 	** (The idea being the device driver will call pdc_pat_cell_module()
-	** and store the results in it's own data structure.)
+	** and store the results in its own data structure.)
 	*/
 	dev->pcell_loc = pcell_loc;
 	dev->mod_index = mod_index;
@@ -79,319 +203,410 @@
 	/* REVISIT: who is the consumer of this? not sure yet... */
 	dev->mod_info = pa_pdc_cell.mod_info;	/* pass to PAT_GET_ENTITY() */
 	dev->pmod_loc = pa_pdc_cell.mod_location;
-	dev->mod_path = pa_pdc_cell.mod_path;
 
-	temp = pa_pdc_cell.cba;
-	register_module((void *) PAT_GET_CBA(temp));	/* fills in dev->hpa */
+	register_parisc_device(dev);	/* advertise device */
 
 #ifdef DEBUG_PAT
 	/* dump what we see so far... */
 	switch (PAT_GET_ENTITY(dev->mod_info)) {
-		ulong i;
+		unsigned long i;
 
 	case PAT_ENTITY_PROC:
-		printk ("PAT_ENTITY_PROC: id_eid 0x%lx\n", pa_pdc_cell.mod[0]);
+		printk(KERN_DEBUG "PAT_ENTITY_PROC: id_eid 0x%lx\n",
+			pa_pdc_cell.mod[0]);
 		break;
 
 	case PAT_ENTITY_MEM:
-		printk ("PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
-			pa_pdc_cell.mod[0],
-			pa_pdc_cell.mod[1],
+		printk(KERN_DEBUG 
+			"PAT_ENTITY_MEM: amount 0x%lx min_gni_base 0x%lx min_gni_len 0x%lx\n",
+			pa_pdc_cell.mod[0], pa_pdc_cell.mod[1], 
 			pa_pdc_cell.mod[2]);
 		break;
 	case PAT_ENTITY_CA:
-		printk ("PAT_ENTITY_CA: %ld\n",pcell_loc);
+		printk(KERN_DEBUG "PAT_ENTITY_CA: %ld\n", pcell_loc);
 		break;
 
 	case PAT_ENTITY_PBC:
-		printk ("PAT_ENTITY_PBC: ");
+		printk(KERN_DEBUG "PAT_ENTITY_PBC: ");
 		goto print_ranges;
 
 	case PAT_ENTITY_SBA:
-		printk ("PAT_ENTITY_SBA: ");
+		printk(KERN_DEBUG "PAT_ENTITY_SBA: ");
 		goto print_ranges;
 
 	case PAT_ENTITY_LBA:
-		printk ("PAT_ENTITY_LBA: ");
+		printk(KERN_DEBUG "PAT_ENTITY_LBA: ");
 
-print_ranges:
-		printk ("ranges %ld\n", pa_pdc_cell.mod[1]);
+ print_ranges:
+		pdc_pat_cell_module(&bytecnt, pcell_loc, mod_index,
+				    IO_VIEW, &io_pdc_cell);
+		printk(KERN_DEBUG "ranges %ld\n", pa_pdc_cell.mod[1]);
 		for (i = 0; i < pa_pdc_cell.mod[1]; i++) {
-			printk ("	%ld: 0x%016lx 0x%016lx 0x%016lx\n", i,
-				pa_pdc_cell.mod[2+i*3],	/* type */
-				pa_pdc_cell.mod[3+i*3],	/* start */
-				pa_pdc_cell.mod[4+i*3]);	/* finish (ie end) */
+			printk(KERN_DEBUG 
+				"  PA_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
+				i, pa_pdc_cell.mod[2 + i * 3],	/* type */
+				pa_pdc_cell.mod[3 + i * 3],	/* start */
+				pa_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */
+			printk(KERN_DEBUG 
+				"  IO_VIEW %ld: 0x%016lx 0x%016lx 0x%016lx\n", 
+				i, io_pdc_cell.mod[2 + i * 3],	/* type */
+				io_pdc_cell.mod[3 + i * 3],	/* start */
+				io_pdc_cell.mod[4 + i * 3]);	/* finish (ie end) */
 		}
-		printk("\n");
+		printk(KERN_DEBUG "\n");
 		break;
 	}
 #endif /* DEBUG_PAT */
-	return PDC_RET_OK;
+	return PDC_OK;
 }
 
 
-static int do_pat_inventory(void)
-{
-	ulong mod_index=0;
-	int status;
-	ulong cell_num;
-	ulong pcell_loc;
+/* pat pdc can return information about a variety of different
+ * types of memory (e.g. firmware,i/o, etc) but we only care about
+ * the usable physical ram right now. Since the firmware specific
+ * information is allocated on the stack, we'll be generous, in
+ * case there is a lot of other information we don't care about.
+ */
 
-	pdc_pat = (pdc_pat_cell_get_number(&pdc_result) == PDC_OK);
-	if (!pdc_pat)
-	{
-		return 0;
-	}
-
-	cell_num = pdc_result[0];	/* Cell number call was made */
-
-	/* As of PDC PAT ARS 2.5, ret[1] is NOT architected! */
-	pcell_loc = pdc_result[1];	/* Physical location of the cell */
-
-#ifdef DEBUG_PAT
-	printk("CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_num, pcell_loc);
-#endif
-
-        status = pdc_pat_cell_num_to_loc(&pdc_result, cell_num);
-        if (status == PDC_BAD_OPTION)
-	{
-		/* Prelude (and it's successors: Lclass, A400/500) only
-		** implement PDC_PAT_CELL sub-options 0 and 2.
-		** "Home cook'n is best anyhow!"
-		*/
-	} else if (PDC_OK == status) {
-		/* so far only Halfdome supports this */
-		pcell_loc = pdc_result[0];
-	} else {
-		panic("WTF? CELL_GET_NUMBER give me invalid cell number?");
-	}
-
-	while (PDC_RET_OK == pat_query_module(pcell_loc, mod_index))
-	{
-		mod_index++;
-	}
-
-	return mod_index;
-}
-#endif /* __LP64__ */
+#define PAT_MAX_RANGES (4 * MAX_PHYSMEM_RANGES)
 
-static int do_newer_workstation_inventory(void)
+static void __init pat_memconfig(void)
 {
+	unsigned long actual_len;
+	struct pdc_pat_pd_addr_map_entry mem_table[PAT_MAX_RANGES+1];
+	struct pdc_pat_pd_addr_map_entry *mtbl_ptr;
+	physmem_range_t *pmem_ptr;
 	long status;
-	int i, num = 0;
+	int entries;
+	unsigned long length;
+	int i;
+
+	length = (PAT_MAX_RANGES + 1) * sizeof(struct pdc_pat_pd_addr_map_entry);
+
+	status = pdc_pat_pd_get_addr_map(&actual_len, mem_table, length, 0L);
+
+	if ((status != PDC_OK)
+	    || ((actual_len % sizeof(struct pdc_pat_pd_addr_map_entry)) != 0)) {
+
+		/* The above pdc call shouldn't fail, but, just in
+		 * case, just use the PAGE0 info.
+		 */
+
+		printk("\n\n\n");
+		printk(KERN_WARNING "WARNING! Could not get full memory configuration. "
+			"All memory may not be used!\n\n\n");
+		pagezero_memconfig();
+		return;
+	}
 
-	/* So the idea here is to simply try one SYSTEM_MAP call.  If 
-	   that one works, great, otherwise do it another way */
+	entries = actual_len / sizeof(struct pdc_pat_pd_addr_map_entry);
 
-	status = pdc_system_map_find_mods(&module_result,&module_path,0);
+	if (entries > PAT_MAX_RANGES) {
+		printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
+		printk(KERN_WARNING "Some memory may not be used!\n");
+	}
 
-	if (status == PDC_RET_OK) {
-		/* This is for newer non-PDC-PAT boxes */
+	/* Copy information into the firmware independent pmem_ranges
+	 * array, skipping types we don't care about. Notice we said
+	 * "may" above. We'll use all the entries that were returned.
+	 */
+
+	npmem_ranges = 0;
+	mtbl_ptr = mem_table;
+	pmem_ptr = pmem_ranges; /* Global firmware independent table */
+	for (i = 0; i < entries; i++,mtbl_ptr++) {
+		if (   (mtbl_ptr->entry_type != PAT_MEMORY_DESCRIPTOR)
+		    || (mtbl_ptr->memory_type != PAT_MEMTYPE_MEMORY)
+		    || (mtbl_ptr->pages == 0)
+		    || (   (mtbl_ptr->memory_usage != PAT_MEMUSE_GENERAL)
+			&& (mtbl_ptr->memory_usage != PAT_MEMUSE_GI)
+			&& (mtbl_ptr->memory_usage != PAT_MEMUSE_GNI) ) ) {
 
-		printk("a newer box...\n");
-		for(i=0, status=PDC_RET_OK; status != PDC_RET_NE_PROC && 
-			status != PDC_RET_NE_MOD ;i++) {
+			continue;
+		}
 
-			status = pdc_system_map_find_mods(&module_result,&module_path,i);
-			if (status == PDC_RET_OK) {
-				num++;
-				register_module(module_result.mod_addr);
-			}
+		if (npmem_ranges == MAX_PHYSMEM_RANGES) {
+			printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
+			printk(KERN_WARNING "Some memory will not be used!\n");
+			break;
 		}
-	}
 
-	return (num > 0);
+		set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages);
+		npmem_ranges++;
+	}
 }
 
-#ifndef __LP64__
-static	struct  pdc_memory_map r_addr __attribute__ ((aligned (8)));
-
-static int really_do_oldhw_inventory(void)
+static int __init pat_inventory(void)
 {
-	int i, mod, num = 0;
 	int status;
-	unsigned int hw_type;
-	unsigned int func;
+	ulong mod_index = 0;
+	struct pdc_pat_cell_num cell_info;
 
-	/* This is undocumented at the time of writing, but basically 
-	   we're setting up mod_path so that bc[0..4]=0xff, and step
-	   through mod to get the "Path Structure for GSC Modules".  If
-	   it works, use the returned HPA and determine the hardware type.  */
+	/*
+	** Note:  Prelude (and it's successors: Lclass, A400/500) only
+	**        implement PDC_PAT_CELL sub-options 0 and 2.
+	*/
+	status = pdc_pat_cell_get_number(&cell_info);
+	if (status != PDC_OK) {
+		return 0;
+	}
 
-	for (i=0;i<6;i++) module_path.bc[i]=0xff;
+#ifdef DEBUG_PAT
+	printk(KERN_DEBUG "CELL_GET_NUMBER: 0x%lx 0x%lx\n", cell_info.cell_num, 
+	       cell_info.cell_loc);
+#endif
 
-	for (mod=0;mod<16;mod++) {
-		char *stype = NULL;
+	while (PDC_OK == pat_query_module(cell_info.cell_loc, mod_index)) {
+		mod_index++;
+	}
 
-		module_path.mod=mod;
-		status = pdc_mem_map_hpa(&r_addr, &module_path);
-		if (status!=PDC_RET_OK) continue;
-	
-		status = pdc_iodc_read(&pdc_result,(void *) r_addr.hpa,
-			0, &iodc_data,32 );
-		if (status!=PDC_RET_OK) continue;
-		hw_type = iodc_data[3]&0x1f;
+	return mod_index;
+}
 
-		switch (hw_type)
-		{
-		case HPHW_NPROC:	/* 0 */
-			stype="Processor"; break;
+/* We only look for extended memory ranges on a 64 bit capable box */
+static void __init sprockets_memconfig(void)
+{
+	struct pdc_memory_table_raddr r_addr;
+	struct pdc_memory_table mem_table[MAX_PHYSMEM_RANGES];
+	struct pdc_memory_table *mtbl_ptr;
+	physmem_range_t *pmem_ptr;
+	long status;
+	int entries;
+	int i;
 
-		case HPHW_MEMORY:	/* 1 */
-			stype="Memory"; break;
+	status = pdc_mem_mem_table(&r_addr,mem_table,
+				(unsigned long)MAX_PHYSMEM_RANGES);
 
-		case HPHW_B_DMA:	/* 2 */
-			stype="Type B DMA"; break;
+	if (status != PDC_OK) {
 
-		case HPHW_A_DMA:	/* 4 */
-			stype="Type A DMA"; break;
+		/* The above pdc call only works on boxes with sprockets
+		 * firmware (newer B,C,J class). Other non PAT PDC machines
+		 * do support more than 3.75 Gb of memory, but we don't
+		 * support them yet.
+		 */
 
-		case HPHW_A_DIRECT:	/* 5 */
-			stype="Type A Direct"; break;
+		pagezero_memconfig();
+		return;
+	}
+
+	if (r_addr.entries_total > MAX_PHYSMEM_RANGES) {
+		printk(KERN_WARNING "This Machine has more memory ranges than we support!\n");
+		printk(KERN_WARNING "Some memory will not be used!\n");
+	}
 
-		case HPHW_BCPORT:	/* 7 */
-			stype="Bus Converter Port"; break;
+	entries = (int)r_addr.entries_returned;
 
-		case HPHW_CONSOLE:	/* 9 */
-			stype="Console"; break;
+	npmem_ranges = 0;
+	mtbl_ptr = mem_table;
+	pmem_ptr = pmem_ranges; /* Global firmware independent table */
+	for (i = 0; i < entries; i++,mtbl_ptr++) {
+		set_pmem_entry(pmem_ptr++,mtbl_ptr->paddr,mtbl_ptr->pages);
+		npmem_ranges++;
+	}
+}
 
-		case HPHW_FIO:		/* 10 - Graphics */
-			stype="Foreign I/O (Graphics)"; break;
+#else   /* !__LP64__ */
 
-		case HPHW_BA:		/* 11 - Bus Adapter */
-			stype="Bus Adapter"; break;
+#define pat_inventory() do { } while (0)
+#define pat_memconfig() do { } while (0)
+#define sprockets_memconfig() pagezero_memconfig()
 
-		case HPHW_IOA:		/* 12 */
-			stype="I/O Adapter"; break;
+#endif	/* !__LP64__ */
 
-		case HPHW_BRIDGE:	/* 13 */
-			stype="Bridge"; break;
 
-		case HPHW_FABRIC:	/* 14 */
-			stype="Fabric"; break;
+#ifndef CONFIG_PA20
 
-		case HPHW_FAULTY:	/* 31 */
-			stype="Faulty HW"; break;
+/* Code to support Snake machines (7[2350], 7[235]5, 715/Scorpio) */
 
-		case HPHW_OTHER:	/* 42 */
-		default:	
-			printk("Don't know this hw_type: %d\n", hw_type);
-			break;
-		}
+static struct parisc_device * __init
+legacy_create_device(struct pdc_memory_map *r_addr,
+		struct pdc_module_path *module_path)
+{
+	struct parisc_device *dev;
+	int status = pdc_mem_map_hpa(r_addr, module_path);
+	if (status != PDC_OK)
+		return NULL;
+
+	dev = alloc_pa_dev(r_addr->hpa, &module_path->path);
+	if (dev == NULL)
+		return NULL;
 
-		// This is kluged. But don't want to replicate code for
-		// most of the above cases.
-		if (stype) {
-#ifdef DBG_PDC_QUERY
-			// parisc/kernel/drivers.c
-			extern int num_devices; 
-			extern struct hp_device devices[];
-			struct hp_hardware *h;
-#endif
+	register_parisc_device(dev);
+	return dev;
+}
 
-			status = pdc_mem_map_hpa(&r_addr, &module_path);
-			if (status==PDC_RET_OK && register_module((void *) r_addr.hpa) != NULL)
-					num++;
-
-
-		    if (hw_type == HPHW_BA) {
-			/* Now, we're checking for devices for each
-			   module.  I seem to think that the
-			   modules in question are Lasi (2), 2nd Lasi (6)
-			   Wax (5).  To do this, set bc[5]=0, and set
-			   bc[4] to the module, and step through the
-			   functions. */
-
-			for (i=0;i<4;i++) module_path.bc[i]=0xff;
-			module_path.bc[4]=mod;
-			for (func=0;func<16;func++) {
-				module_path.mod = func;
-				module_path.bc[5]=0;
-				status = pdc_mem_map_hpa(&r_addr, &module_path);
-				if (status!=PDC_RET_OK) continue;
-				if (register_module((void *) r_addr.hpa) != NULL) 
-					num++;
-			}
+/**
+ * snake_inventory
+ *
+ * Before PDC_SYSTEM_MAP was invented, the PDC_MEM_MAP call was used.
+ * To use it, we initialise the mod_path.bc to 0xff and try all values of
+ * mod to get the HPA for the top-level devices.  Bus adapters may have
+ * sub-devices which are discovered by setting bc[5] to 0 and bc[4] to the
+ * module, then trying all possible functions.
+ */
+static void __init snake_inventory(void)
+{
+	int mod;
+	for (mod = 0; mod < 16; mod++) {
+		struct parisc_device *dev;
+		struct pdc_module_path module_path;
+		struct pdc_memory_map r_addr;
+		unsigned int func;
+
+		memset(module_path.path.bc, 0xff, 6);
+		module_path.path.mod = mod;
+		dev = legacy_create_device(&r_addr, &module_path);
+		if ((!dev) || (dev->id.hw_type != HPHW_BA))
+			continue;
+
+		memset(module_path.path.bc, 0xff, 4);
+		module_path.path.bc[4] = mod;
+
+		for (func = 0; func < 16; func++) {
+			module_path.path.bc[5] = 0;
+			module_path.path.mod = func;
+			legacy_create_device(&r_addr, &module_path);
 		}
-		// reset module_path.bc[]
-		for (i=0;i<6;i++) module_path.bc[i]=0xff;
+	}
+}
 
+#else /* CONFIG_PA20 */
+#define snake_inventory() do { } while (0)
+#endif  /* CONFIG_PA20 */
+
+/* Common 32/64 bit based code goes here */
+
+/**
+ * add_system_map_addresses - Add additional addresses to the parisc device.
+ * @dev: The parisc device.
+ * @num_addrs: Then number of addresses to add;
+ * @module_instance: The system_map module instance.
+ *
+ * This function adds any additional addresses reported by the system_map
+ * firmware to the parisc device.
+ */
+static void __init
+add_system_map_addresses(struct parisc_device *dev, int num_addrs, 
+			 int module_instance)
+{
+	int i;
+	long status;
+	struct pdc_system_map_addr_info addr_result;
 
-#ifdef DBG_PDC_QUERY
-//
-// Let print_devices() dump everything which is registered.
-//
-			h = devices[num_devices-1].reference;
+	dev->addr = kmalloc(num_addrs * sizeof(unsigned long), GFP_KERNEL);
+	if(!dev->addr) {
+		printk(KERN_ERR "%s %s(): memory allocation failure\n",
+		       __FILE__, __FUNCTION__);
+		return;
+	}
 
-			if (h) stype = h->name;
-			printk("Found %s at %d\n", stype, module_path.mod);
-#endif
+	for(i = 1; i <= num_addrs; ++i) {
+		status = pdc_system_map_find_addrs(&addr_result, 
+						   module_instance, i);
+		if(PDC_OK == status) {
+			dev->addr[dev->num_addrs] = (unsigned long)addr_result.mod_addr;
+			dev->num_addrs++;
+		} else {
+			printk(KERN_WARNING 
+			       "Bad PDC_FIND_ADDRESS status return (%ld) for index %d\n",
+			       status, i);
 		}
 	}
-	return num;
 }
 
-static int
-do_old_inventory(void)
+/**
+ * do_system_map_inventory - Retrieve firmware devices via SYSTEM_MAP.
+ *
+ * This function attempts to retrieve and register all the devices firmware
+ * knows about via the SYSTEM_MAP PDC call.
+ */
+static void __init system_map_inventory(void)
 {
-        unsigned int bus_id;
-	long status;
-	int ok = 0;
-
-	printk(" an older box...\n");
+	int i;
+	long status = PDC_OK;
+    
+	/*
+	 * first stop the usb controller, otherwise the machine
+	 * might crash during iommu setup
+	 */
+	pdc_suspend_usb();
+
+	for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) {
+		struct parisc_device *dev;
+		struct pdc_system_map_mod_info module_result;
+		struct pdc_module_path module_path;
+
+		status = pdc_system_map_find_mods(&module_result,
+				&module_path, i);
+		if (status != PDC_OK)
+			continue;
+		
+		dev = alloc_pa_dev(module_result.mod_addr, &module_path.path);
+		if (!dev)
+			continue;
+		
+		register_parisc_device(dev);
+
+		/* if available, get the additional addresses for a module */
+		if (!module_result.add_addrs)
+			continue;
 
-	/* Here, we're going to check the model, and decide
-	   if we should even bother trying. */
+		add_system_map_addresses(dev, module_result.add_addrs, i);
+	}
 
-	status = pdc_model_info(&model);
+	walk_central_bus();
+	return;
+}
 
-	bus_id = (model.hversion >> (4+7) ) &0x1f;
+void __init do_memory_inventory(void)
+{
+	switch (pdc_type) {
 
-	/* Here, we're checking the HVERSION of the CPU.
-	   We're only checking the 0th CPU, since it'll
-	   be the same on an SMP box. */
+	case PDC_TYPE_PAT:
+		pat_memconfig();
+		break;
 
-	switch (bus_id) {
-		case 0x4: 	/* 720, 730, 750, 735, 755 */
-		case 0x6: 	/* 705, 710 */
-		case 0x7: 	/* 715, 725 */
-		case 0x8: 	/* 745, 747, 742 */
-		case 0xA: 	/* 712 and similiar */
-		case 0xC: 	/* 715/64, at least */
-
-		/* Do inventory using MEM_MAP */
-		really_do_oldhw_inventory();
-		ok = 1;
+	case PDC_TYPE_SYSTEM_MAP:
+		sprockets_memconfig();
 		break;
-	default: 	/* Everything else */
-		printk("This is a very very old machine, with a bus_id of 0x%x.\n",bus_id);
-		panic("This will probably never run Linux.\n");
+
+	case PDC_TYPE_SNAKE:
+		pagezero_memconfig();
+		return;
+
+	default:
+		panic("Unknown PDC type!\n");
 	}
 
-	return ok;
+	if (npmem_ranges == 0 || pmem_ranges[0].start_pfn != 0) {
+		printk(KERN_WARNING "Bad memory configuration returned!\n");
+		printk(KERN_WARNING "Some memory may not be used!\n");
+		pagezero_memconfig();
+	}
 }
 
-#endif /* !__LP64__ */
+void __init do_device_inventory(void)
+{
+	printk(KERN_INFO "Searching for devices...\n");
 
-void do_inventory(void){
-	if((pdc_hpa_processor(&processor_hpa))<0){
-		printk(KERN_INFO "Couldn't get the HPA of the processor.\n" );
-	}
+	switch (pdc_type) {
+
+	case PDC_TYPE_PAT:
+		pat_inventory();
+		break;
 
-	printk("Searching for devices in PDC firmware... ");
-	printk("processor hpa 0x%lx\n", processor_hpa.hpa);
+	case PDC_TYPE_SYSTEM_MAP:
+		system_map_inventory();
+		break;
 
-	if (!(
-		do_newer_workstation_inventory()
-#ifdef __LP64__
-		|| do_pat_inventory()
-#else /* __LP64__ */
-		|| do_old_inventory()
-#endif /* __LP64__ */
-	    ))
-	{
-	    panic("I can't get the hardware inventory on this machine");
+	case PDC_TYPE_SNAKE:
+		snake_inventory();
+		break;
+
+	default:
+		panic("Unknown PDC type!\n");
 	}
-	print_devices(NULL);
-}
 
+	printk(KERN_INFO "Found devices:\n");
+	print_parisc_devices();
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/ioctl32.c linux/arch/parisc/kernel/ioctl32.c
--- linux.orig/arch/parisc/kernel/ioctl32.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/ioctl32.c	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,3758 @@
+/* $Id: ioctl32.c,v 1.12 2002/07/08 20:52:15 grundler Exp $
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ *
+ * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
+ * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * ioctls.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include "sys32.h"
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/ioctl.h>
+#include <linux/if.h>
+#include <linux/slab.h>
+#include <linux/hdreg.h>
+#include <linux/raid/md.h>
+#include <linux/kd.h>
+#include <linux/route.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/vt.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/fd.h>
+#include <linux/ppp_defs.h>
+#include <linux/if_ppp.h>
+#include <linux/if_pppox.h>
+#include <linux/mtio.h>
+#include <linux/cdrom.h>
+#include <linux/loop.h>
+#include <linux/auto_fs.h>
+#include <linux/devfs_fs.h>
+#include <linux/tty.h>
+#include <linux/vt_kern.h>
+#include <linux/fb.h>
+#include <linux/ext2_fs.h>
+#include <linux/videodev.h>
+#include <linux/netdevice.h>
+#include <linux/raw.h>
+#include <linux/smb_fs.h>
+#include <linux/blkpg.h>
+#include <linux/blk.h>
+#include <linux/elevator.h>
+#include <linux/rtc.h>
+#include <linux/serial.h>
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+/* Ugh. This header really is not clean */
+/* #define min min
+#define max max */
+#include <linux/lvm.h>
+#endif /* LVM */
+
+#include <scsi/scsi.h>
+/* Ugly hack. */
+#undef __KERNEL__
+#include <scsi/scsi_ioctl.h>
+#define __KERNEL__
+#include <scsi/sg.h>
+
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <asm/perf.h>
+#include <linux/ethtool.h>
+#include <linux/soundcard.h>
+
+#include <linux/atm.h>
+#include <linux/atmarp.h>
+#include <linux/atmclip.h>
+#include <linux/atmdev.h>
+#include <linux/atmioc.h>
+#include <linux/atmlec.h>
+#include <linux/atmmpc.h>
+#include <linux/atmsvc.h>
+#include <linux/atm_tcp.h>
+#include <linux/sonet.h>
+#include <linux/atm_suni.h>
+
+#include <asm/module.h>	/* get #define module_map() */
+
+/* Use this to get at 32-bit user passed pointers. 
+   See sys_sparc32.c for description about these. */
+#define A(__x) ((unsigned long)(__x))
+
+/* Aiee. Someone does not find a difference between int and long */
+#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
+#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
+#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
+#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
+
+extern asmlinkage int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 *)arg))
+		return -EFAULT;
+	return err;
+}
+ 
+static int rw_long(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	if(get_user(val, (u32 *)arg))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user(val, (u32 *)arg))
+		return -EFAULT;
+	return err;
+}
+
+static int siocprivate(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	int err = sys_ioctl(fd, cmd, arg);
+	if ((unsigned) err > -4095)
+		printk(KERN_WARNING 
+			"ioctl(%d, 0x%x, %p) -- SIOCDEVPRIVATE-based ioctls aren't really\n"
+			"supported, though some will work by accident.\n",
+		    fd, cmd, (void *)arg);
+	return err;
+}
+
+static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
+	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
+	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
+	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
+	}
+	return sys_ioctl(fd, cmd, arg);
+}
+ 
+static int do_siocgstamp(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct timeval32 *up = (struct timeval32 *)arg;
+	struct timeval ktv;
+	mm_segment_t old_fs = get_fs();
+	int err;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&ktv);
+	set_fs(old_fs);
+	if(!err) {
+		err = put_user(ktv.tv_sec, &up->tv_sec);
+		err |= __put_user(ktv.tv_usec, &up->tv_usec);
+	}
+	return err;
+}
+
+struct ifmap32 {
+	u32 mem_start;
+	u32 mem_end;
+	unsigned short base_addr;
+	unsigned char irq;
+	unsigned char dma;
+	unsigned char port;
+};
+
+struct ifreq32 {
+#define IFHWADDRLEN     6
+#define IFNAMSIZ        16
+        union {
+                char    ifrn_name[IFNAMSIZ];            /* if name, e.g. "en0" */
+        } ifr_ifrn;
+        union {
+                struct  sockaddr ifru_addr;
+                struct  sockaddr ifru_dstaddr;
+                struct  sockaddr ifru_broadaddr;
+                struct  sockaddr ifru_netmask;
+                struct  sockaddr ifru_hwaddr;
+                short   ifru_flags;
+                int     ifru_ivalue;
+                int     ifru_mtu;
+                struct  ifmap32 ifru_map;
+                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
+		char	ifru_newname[IFNAMSIZ];
+                __kernel_caddr_t32 ifru_data;
+        } ifr_ifru;
+};
+
+struct ifconf32 {
+        int     ifc_len;                        /* size of buffer       */
+        __kernel_caddr_t32  ifcbuf;
+};
+
+static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct net_device *dev;
+	struct ifreq32 ifr32;
+	int err;
+
+	if (copy_from_user(&ifr32, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+		return -EFAULT;
+
+	dev = dev_get_by_index(ifr32.ifr_ifindex);
+	if (!dev)
+		return -ENODEV;
+
+	strcpy(ifr32.ifr_name, dev->name);
+
+	err = copy_to_user((struct ifreq32 *)arg, &ifr32, sizeof(struct ifreq32));
+	return (err ? -EFAULT : 0);
+}
+
+static inline int dev_ifconf(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifconf32 ifc32;
+	struct ifconf ifc;
+	struct ifreq32 *ifr32;
+	struct ifreq *ifr;
+	mm_segment_t old_fs;
+	unsigned int i, j;
+	int err;
+
+	if (copy_from_user(&ifc32, (struct ifconf32 *)arg, sizeof(struct ifconf32)))
+		return -EFAULT;
+
+	if(ifc32.ifcbuf == 0) {
+		ifc32.ifc_len = 0;
+		ifc.ifc_len = 0;
+		ifc.ifc_buf = NULL;
+	} else {
+		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32)) + 1) *
+			sizeof (struct ifreq);
+		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
+		if (!ifc.ifc_buf)
+			return -ENOMEM;
+	}
+	ifr = ifc.ifc_req;
+	ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
+	for (i = 0; i < ifc32.ifc_len; i += sizeof (struct ifreq32)) {
+		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
+			kfree (ifc.ifc_buf);
+			return -EFAULT;
+		}
+	}
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);	
+	set_fs (old_fs);
+	if (!err) {
+		ifr = ifc.ifc_req;
+		ifr32 = (struct ifreq32 *)A(ifc32.ifcbuf);
+		for (i = 0, j = 0; i < ifc32.ifc_len && j < ifc.ifc_len;
+		     i += sizeof (struct ifreq32), j += sizeof (struct ifreq)) {
+			if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
+				err = -EFAULT;
+				break;
+			}
+		}
+		if (!err) {
+			if (i <= ifc32.ifc_len)
+				ifc32.ifc_len = i;
+			else
+				ifc32.ifc_len = i - sizeof (struct ifreq32);
+			if (copy_to_user((struct ifconf32 *)arg, &ifc32, sizeof(struct ifconf32)))
+				err = -EFAULT;
+		}
+	}
+	if(ifc.ifc_buf != NULL)
+		kfree (ifc.ifc_buf);
+	return err;
+}
+
+static int dev_ifsioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err;
+	
+	switch (cmd) {
+	case SIOCSIFMAP:
+		err = copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(ifr.ifr_name));
+		err |= __get_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
+		err |= __get_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
+		err |= __get_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
+		err |= __get_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
+		err |= __get_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
+		err |= __get_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
+		if (err)
+			return -EFAULT;
+		break;
+	case SIOCGPPPSTATS:
+	case SIOCGPPPCSTATS:
+	case SIOCGPPPVER:
+	case SIOCETHTOOL:
+		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+			return -EFAULT;
+		ifr.ifr_data = (__kernel_caddr_t)get_free_page(GFP_KERNEL);
+		if (!ifr.ifr_data)
+			return -EAGAIN;
+		if(cmd == SIOCETHTOOL) {
+			u32 data;
+
+			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+			if(copy_from_user(ifr.ifr_data,
+					  (char *)A(data),
+					  sizeof(struct ethtool_cmd))) {
+				free_page((unsigned long)ifr.ifr_data);
+				return -EFAULT;
+			}
+		}
+		break;
+	default:
+		if (copy_from_user(&ifr, (struct ifreq32 *)arg, sizeof(struct ifreq32)))
+			return -EFAULT;
+		break;
+	}
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		switch (cmd) {
+		case SIOCGIFFLAGS:
+		case SIOCGIFMETRIC:
+		case SIOCGIFMTU:
+		case SIOCGIFMEM:
+		case SIOCGIFHWADDR:
+		case SIOCGIFINDEX:
+		case SIOCGIFADDR:
+		case SIOCGIFBRDADDR:
+		case SIOCGIFDSTADDR:
+		case SIOCGIFNETMASK:
+		case SIOCGIFTXQLEN:
+			if (copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(struct ifreq32)))
+				return -EFAULT;
+			break;
+		case SIOCGPPPSTATS:
+		case SIOCGPPPCSTATS:
+		case SIOCGPPPVER:
+		case SIOCETHTOOL:
+		{
+			u32 data;
+			int len;
+
+			__get_user(data, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_data));
+			if(cmd == SIOCETHTOOL)
+				len = sizeof(struct ethtool_cmd);
+			if(cmd == SIOCGPPPVER)
+				len = strlen((char *)ifr.ifr_data) + 1;
+			else if(cmd == SIOCGPPPCSTATS)
+				len = sizeof(struct ppp_comp_stats);
+			else
+				len = sizeof(struct ppp_stats);
+
+			len = copy_to_user((char *)A(data), ifr.ifr_data, len);
+			free_page((unsigned long)ifr.ifr_data);
+			if(len)
+				return -EFAULT;
+			break;
+		}
+		case SIOCGIFMAP:
+			err = copy_to_user((struct ifreq32 *)arg, &ifr, sizeof(ifr.ifr_name));
+			err |= __put_user(ifr.ifr_map.mem_start, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_start));
+			err |= __put_user(ifr.ifr_map.mem_end, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.mem_end));
+			err |= __put_user(ifr.ifr_map.base_addr, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.base_addr));
+			err |= __put_user(ifr.ifr_map.irq, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.irq));
+			err |= __put_user(ifr.ifr_map.dma, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.dma));
+			err |= __put_user(ifr.ifr_map.port, &(((struct ifreq32 *)arg)->ifr_ifru.ifru_map.port));
+			if (err)
+				err = -EFAULT;
+			break;
+		}
+	}
+	return err;
+}
+
+struct rtentry32 {
+        u32   		rt_pad1;
+        struct sockaddr rt_dst;         /* target address               */
+        struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
+        struct sockaddr rt_genmask;     /* target network mask (IP)     */
+        unsigned short  rt_flags;
+        short           rt_pad2;
+        u32   		rt_pad3;
+        unsigned char   rt_tos;
+        unsigned char   rt_class;
+        short           rt_pad4;
+        short           rt_metric;      /* +1 for binary compatibility! */
+        /* char * */ u32 rt_dev;        /* forcing the device at add    */
+        u32   		rt_mtu;         /* per route MTU/Window         */
+        u32   		rt_window;      /* Window clamping              */
+        unsigned short  rt_irtt;        /* Initial RTT                  */
+
+};
+
+static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct rtentry r;
+	char devname[16];
+	u32 rtdev;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	ret = copy_from_user (&r.rt_dst, &(((struct rtentry32 *)arg)->rt_dst), 3 * sizeof(struct sockaddr));
+	ret |= __get_user (r.rt_flags, &(((struct rtentry32 *)arg)->rt_flags));
+	ret |= __get_user (r.rt_metric, &(((struct rtentry32 *)arg)->rt_metric));
+	ret |= __get_user (r.rt_mtu, &(((struct rtentry32 *)arg)->rt_mtu));
+	ret |= __get_user (r.rt_window, &(((struct rtentry32 *)arg)->rt_window));
+	ret |= __get_user (r.rt_irtt, &(((struct rtentry32 *)arg)->rt_irtt));
+	ret |= __get_user (rtdev, &(((struct rtentry32 *)arg)->rt_dev));
+	if (rtdev) {
+		ret |= copy_from_user (devname, (char *)A(rtdev), 15);
+		r.rt_dev = devname; devname[15] = 0;
+	} else
+		r.rt_dev = 0;
+	if (ret)
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, cmd, (long)&r);
+	set_fs (old_fs);
+	return ret;
+}
+
+struct hd_geometry32 {
+	unsigned char heads;
+	unsigned char sectors;
+	unsigned short cylinders;
+	u32 start;
+};
+                        
+static inline int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct hd_geometry geo;
+	int err;
+	
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, HDIO_GETGEO, (unsigned long)&geo);
+	set_fs (old_fs);
+	if (!err) {
+		err = copy_to_user ((struct hd_geometry32 *)arg, &geo, 4);
+		err |= __put_user (geo.start, &(((struct hd_geometry32 *)arg)->start));
+	}
+	return err ? -EFAULT : 0;
+}
+
+
+#if 0
+/* looks like SPARC only - eg sbus video */
+struct  fbcmap32 {
+	int             index;          /* first element (0 origin) */
+	int             count;
+	u32		red;
+	u32		green;
+	u32		blue;
+};
+
+
+static inline int fbiogetputcmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct fbcmap f;
+	int ret;
+	char red[256], green[256], blue[256];
+	u32 r, g, b;
+	mm_segment_t old_fs = get_fs();
+	
+	ret = get_user(f.index, &(((struct fbcmap32 *)arg)->index));
+	ret |= __get_user(f.count, &(((struct fbcmap32 *)arg)->count));
+	ret |= __get_user(r, &(((struct fbcmap32 *)arg)->red));
+	ret |= __get_user(g, &(((struct fbcmap32 *)arg)->green));
+	ret |= __get_user(b, &(((struct fbcmap32 *)arg)->blue));
+	if (ret)
+		return -EFAULT;
+	if ((f.index < 0) || (f.index > 255)) return -EINVAL;
+	if (f.index + f.count > 256)
+		f.count = 256 - f.index;
+	if (cmd == FBIOPUTCMAP32) {
+		ret = copy_from_user (red, (char *)A(r), f.count);
+		ret |= copy_from_user (green, (char *)A(g), f.count);
+		ret |= copy_from_user (blue, (char *)A(b), f.count);
+		if (ret)
+			return -EFAULT;
+	}
+	f.red = red; f.green = green; f.blue = blue;
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, (cmd == FBIOPUTCMAP32) ? FBIOPUTCMAP_SPARC : FBIOGETCMAP_SPARC, (long)&f);
+	set_fs (old_fs);
+	if (!ret && cmd == FBIOGETCMAP32) {
+		ret = copy_to_user ((char *)A(r), red, f.count);
+		ret |= copy_to_user ((char *)A(g), green, f.count);
+		ret |= copy_to_user ((char *)A(b), blue, f.count);
+	}
+	return ret ? -EFAULT : 0;
+}
+
+struct fbcursor32 {
+	short set;		/* what to set, choose from the list above */
+	short enable;		/* cursor on/off */
+	struct fbcurpos pos;	/* cursor position */
+	struct fbcurpos hot;	/* cursor hot spot */
+	struct fbcmap32 cmap;	/* color map info */
+	struct fbcurpos size;	/* cursor bit map size */
+	u32	image;		/* cursor image bits */
+	u32	mask;		/* cursor mask bits */
+};
+	
+static inline int fbiogscursor(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct fbcursor f;
+	int ret;
+	char red[2], green[2], blue[2];
+	char image[128], mask[128];
+	u32 r, g, b;
+	u32 m, i;
+	mm_segment_t old_fs = get_fs();
+	
+	ret = copy_from_user (&f, (struct fbcursor32 *)arg, 2 * sizeof (short) + 2 * sizeof(struct fbcurpos));
+	ret |= __get_user(f.size.fbx, &(((struct fbcursor32 *)arg)->size.fbx));
+	ret |= __get_user(f.size.fby, &(((struct fbcursor32 *)arg)->size.fby));
+	ret |= __get_user(f.cmap.index, &(((struct fbcursor32 *)arg)->cmap.index));
+	ret |= __get_user(f.cmap.count, &(((struct fbcursor32 *)arg)->cmap.count));
+	ret |= __get_user(r, &(((struct fbcursor32 *)arg)->cmap.red));
+	ret |= __get_user(g, &(((struct fbcursor32 *)arg)->cmap.green));
+	ret |= __get_user(b, &(((struct fbcursor32 *)arg)->cmap.blue));
+	ret |= __get_user(m, &(((struct fbcursor32 *)arg)->mask));
+	ret |= __get_user(i, &(((struct fbcursor32 *)arg)->image));
+	if (ret)
+		return -EFAULT;
+	if (f.set & FB_CUR_SETCMAP) {
+		if ((uint) f.size.fby > 32)
+			return -EINVAL;
+		ret = copy_from_user (mask, (char *)A(m), f.size.fby * 4);
+		ret |= copy_from_user (image, (char *)A(i), f.size.fby * 4);
+		if (ret)
+			return -EFAULT;
+		f.image = image; f.mask = mask;
+	}
+	if (f.set & FB_CUR_SETCMAP) {
+		ret = copy_from_user (red, (char *)A(r), 2);
+		ret |= copy_from_user (green, (char *)A(g), 2);
+		ret |= copy_from_user (blue, (char *)A(b), 2);
+		if (ret)
+			return -EFAULT;
+		f.cmap.red = red; f.cmap.green = green; f.cmap.blue = blue;
+	}
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, FBIOSCURSOR, (long)&f);
+	set_fs (old_fs);
+	return ret;
+}
+#endif /* 0 */
+
+struct fb_fix_screeninfo32 {
+	char			id[16];
+        __kernel_caddr_t32	smem_start;
+	__u32			smem_len;
+	__u32			type;
+	__u32			type_aux;
+	__u32			visual;
+	__u16			xpanstep;
+	__u16			ypanstep;
+	__u16			ywrapstep;
+	__u32			line_length;
+        __kernel_caddr_t32	mmio_start;
+	__u32			mmio_len;
+	__u32			accel;
+	__u16			reserved[3];
+};
+
+struct fb_cmap32 {
+	__u32			start;
+	__u32			len;
+	__kernel_caddr_t32	red;
+	__kernel_caddr_t32	green;
+	__kernel_caddr_t32	blue;
+	__kernel_caddr_t32	transp;
+};
+
+static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	u32 red = 0, green = 0, blue = 0, transp = 0;
+	struct fb_fix_screeninfo fix;
+	struct fb_cmap cmap;
+	void *karg;
+	int err = 0;
+
+	memset(&cmap, 0, sizeof(cmap));
+	switch (cmd) {
+	case FBIOGET_FSCREENINFO:
+		karg = &fix;
+		break;
+	case FBIOGETCMAP:
+	case FBIOPUTCMAP:
+		karg = &cmap;
+		err = __get_user(cmap.start, &((struct fb_cmap32 *)arg)->start);
+		err |= __get_user(cmap.len, &((struct fb_cmap32 *)arg)->len);
+		err |= __get_user(red, &((struct fb_cmap32 *)arg)->red);
+		err |= __get_user(green, &((struct fb_cmap32 *)arg)->green);
+		err |= __get_user(blue, &((struct fb_cmap32 *)arg)->blue);
+		err |= __get_user(transp, &((struct fb_cmap32 *)arg)->transp);
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+		err = -ENOMEM;
+		cmap.red = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+		if (!cmap.red)
+			goto out;
+		cmap.green = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+		if (!cmap.green)
+			goto out;
+		cmap.blue = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+		if (!cmap.blue)
+			goto out;
+		if (transp) {
+			cmap.transp = kmalloc(cmap.len * sizeof(__u16), GFP_KERNEL);
+			if (!cmap.transp)
+				goto out;
+		}
+			
+		if (cmd == FBIOGETCMAP)
+			break;
+
+		err = __copy_from_user(cmap.red, (char *)A(red), cmap.len * sizeof(__u16));
+		err |= __copy_from_user(cmap.green, (char *)A(green), cmap.len * sizeof(__u16));
+		err |= __copy_from_user(cmap.blue, (char *)A(blue), cmap.len * sizeof(__u16));
+		if (cmap.transp) err |= __copy_from_user(cmap.transp, (char *)A(transp), cmap.len * sizeof(__u16));
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+		break;
+	default:
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk(KERN_WARNING
+					"%s: Unknown fb ioctl cmd fd(%d) "
+					"cmd(%08x) arg(%08lx)\n",
+					__FUNCTION__, fd, cmd, arg);
+		} while(0);
+		return -ENOSYS;
+	}
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)karg);
+	set_fs(old_fs);
+	if (err)
+		goto out;
+	switch (cmd) {
+		struct fb_fix_screeninfo32 fix32;
+	case FBIOGET_FSCREENINFO:
+		memset(&fix32, 0, sizeof(fix32));
+		memcpy(fix32.id, fix.id, sizeof(fix32.id));
+		fix32.smem_start = (__u32)(unsigned long)fix.smem_start;
+		fix32.smem_len	= fix.smem_len;
+		fix32.type	= fix.type;
+		fix32.type_aux	= fix.type_aux;
+		fix32.visual	= fix.visual;
+		fix32.xpanstep	= fix.xpanstep;
+		fix32.ypanstep	= fix.ypanstep;
+		fix32.ywrapstep = fix.ywrapstep;
+		fix32.line_length = fix.line_length;
+		fix32.mmio_start = (__u32)(unsigned long)fix.mmio_start;
+		fix32.mmio_len	= fix.mmio_len;
+		fix32.accel	= fix.accel;
+		memcpy(fix32.reserved, fix.reserved, sizeof(fix32.reserved));
+		err = __copy_to_user((void *) arg, (const void *) &fix32, sizeof(fix32));
+
+printk("fix  : %lx %x  %x %x %x  %x %x %x %x  %lx %x %x\n",
+	fix.smem_start, fix.smem_len,
+	fix.type, fix.type_aux, fix.visual,
+	fix.xpanstep, fix.ypanstep, fix.ywrapstep, fix.line_length,
+	fix.mmio_start, fix.mmio_len, fix.accel);
+printk("fix32: %x %x  %x %x %x  %x %x %x %x  %x %x %x\n",
+	fix32.smem_start, fix32.smem_len,
+	fix32.type, fix32.type_aux, fix32.visual,
+	fix32.xpanstep, fix32.ypanstep, fix32.ywrapstep, fix32.line_length,
+	fix32.mmio_start, fix32.mmio_len, fix32.accel);
+
+		break;
+	case FBIOGETCMAP:
+		err = __copy_to_user((char *)A(red), cmap.red, cmap.len * sizeof(__u16));
+		err |= __copy_to_user((char *)A(green), cmap.blue, cmap.len * sizeof(__u16));
+		err |= __copy_to_user((char *)A(blue), cmap.blue, cmap.len * sizeof(__u16));
+		if (cmap.transp)
+			err |= __copy_to_user((char *)A(transp), cmap.transp, cmap.len * sizeof(__u16));
+		break;
+	case FBIOPUTCMAP:
+		break;
+	}
+	if (err)
+		err = -EFAULT;
+
+out:	if (cmap.red) kfree(cmap.red);
+	if (cmap.green) kfree(cmap.green);
+	if (cmap.blue) kfree(cmap.blue);
+	if (cmap.transp) kfree(cmap.transp);
+	return err;
+}
+
+static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	unsigned long kval;
+	unsigned int *uvp;
+	int error;
+
+	set_fs(KERNEL_DS);
+	error = sys_ioctl(fd, cmd, (long)&kval);
+	set_fs(old_fs);
+
+	if(error == 0) {
+		uvp = (unsigned int *)arg;
+		if(put_user(kval, uvp))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+struct floppy_struct32 {
+	unsigned int	size;
+	unsigned int	sect;
+	unsigned int	head;
+	unsigned int	track;
+	unsigned int	stretch;
+	unsigned char	gap;
+	unsigned char	rate;
+	unsigned char	spec1;
+	unsigned char	fmt_gap;
+	const __kernel_caddr_t32 name;
+};
+
+struct floppy_drive_params32 {
+	char		cmos;
+	u32		max_dtr;
+	u32		hlt;
+	u32		hut;
+	u32		srt;
+	u32		spinup;
+	u32		spindown;
+	unsigned char	spindown_offset;
+	unsigned char	select_delay;
+	unsigned char	rps;
+	unsigned char	tracks;
+	u32		timeout;
+	unsigned char	interleave_sect;
+	struct floppy_max_errors max_errors;
+	char		flags;
+	char		read_track;
+	short		autodetect[8];
+	int		checkfreq;
+	int		native_format;
+};
+
+struct floppy_drive_struct32 {
+	signed char	flags;
+	u32		spinup_date;
+	u32		select_date;
+	u32		first_read_date;
+	short		probed_format;
+	short		track;
+	short		maxblock;
+	short		maxtrack;
+	int		generation;
+	int		keep_data;
+	int		fd_ref;
+	int		fd_device;
+	int		last_checked;
+	__kernel_caddr_t32 dmabuf;
+	int		bufblocks;
+};
+
+struct floppy_fdc_state32 {
+	int		spec1;
+	int		spec2;
+	int		dtr;
+	unsigned char	version;
+	unsigned char	dor;
+	u32		address;
+	unsigned int	rawcmd:2;
+	unsigned int	reset:1;
+	unsigned int	need_configure:1;
+	unsigned int	perp_mode:2;
+	unsigned int	has_fifo:1;
+	unsigned int	driver_version;
+	unsigned char	track[4];
+};
+
+struct floppy_write_errors32 {
+	unsigned int	write_errors;
+	u32		first_error_sector;
+	int		first_error_generation;
+	u32		last_error_sector;
+	int		last_error_generation;
+	unsigned int	badness;
+};
+
+#define FDSETPRM32 _IOW(2, 0x42, struct floppy_struct32)
+#define FDDEFPRM32 _IOW(2, 0x43, struct floppy_struct32)
+#define FDGETPRM32 _IOR(2, 0x04, struct floppy_struct32)
+#define FDSETDRVPRM32 _IOW(2, 0x90, struct floppy_drive_params32)
+#define FDGETDRVPRM32 _IOR(2, 0x11, struct floppy_drive_params32)
+#define FDGETDRVSTAT32 _IOR(2, 0x12, struct floppy_drive_struct32)
+#define FDPOLLDRVSTAT32 _IOR(2, 0x13, struct floppy_drive_struct32)
+#define FDGETFDCSTAT32 _IOR(2, 0x15, struct floppy_fdc_state32)
+#define FDWERRORGET32  _IOR(2, 0x17, struct floppy_write_errors32)
+
+static struct {
+	unsigned int	cmd32;
+	unsigned int	cmd;
+} fd_ioctl_trans_table[] = {
+	{ FDSETPRM32, FDSETPRM },
+	{ FDDEFPRM32, FDDEFPRM },
+	{ FDGETPRM32, FDGETPRM },
+	{ FDSETDRVPRM32, FDSETDRVPRM },
+	{ FDGETDRVPRM32, FDGETDRVPRM },
+	{ FDGETDRVSTAT32, FDGETDRVSTAT },
+	{ FDPOLLDRVSTAT32, FDPOLLDRVSTAT },
+	{ FDGETFDCSTAT32, FDGETFDCSTAT },
+	{ FDWERRORGET32, FDWERRORGET }
+};
+
+#define NR_FD_IOCTL_TRANS (sizeof(fd_ioctl_trans_table)/sizeof(fd_ioctl_trans_table[0]))
+
+static int fd_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	void *karg = NULL;
+	unsigned int kcmd = 0;
+	int i, err;
+
+	for (i = 0; i < NR_FD_IOCTL_TRANS; i++)
+		if (cmd == fd_ioctl_trans_table[i].cmd32) {
+			kcmd = fd_ioctl_trans_table[i].cmd;
+			break;
+		}
+	if (!kcmd)
+		return -EINVAL;
+
+	switch (cmd) {
+		case FDSETPRM32:
+		case FDDEFPRM32:
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f;
+
+			f = karg = kmalloc(sizeof(struct floppy_struct), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETPRM32)
+				break;
+			err = __get_user(f->size, &((struct floppy_struct32 *)arg)->size);
+			err |= __get_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
+			err |= __get_user(f->head, &((struct floppy_struct32 *)arg)->head);
+			err |= __get_user(f->track, &((struct floppy_struct32 *)arg)->track);
+			err |= __get_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
+			err |= __get_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
+			err |= __get_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
+			err |= __get_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
+			err |= __get_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
+			err |= __get_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			if (err) {
+				err = -EFAULT;
+				goto out;
+			}
+			break;
+		}
+		case FDSETDRVPRM32:
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params *f;
+
+			f = karg = kmalloc(sizeof(struct floppy_drive_params), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			if (cmd == FDGETDRVPRM32)
+				break;
+			err = __get_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
+			err |= __get_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
+			err |= __get_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
+			err |= __get_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
+			err |= __get_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
+			err |= __get_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
+			err |= __get_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
+			err |= __get_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
+			err |= __get_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
+			err |= __get_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
+			err |= __get_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
+			err |= __get_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
+			err |= __get_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
+			err |= __copy_from_user(&f->max_errors, &((struct floppy_drive_params32 *)arg)->max_errors, sizeof(f->max_errors));
+			err |= __get_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
+			err |= __get_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
+			err |= __copy_from_user(f->autodetect, ((struct floppy_drive_params32 *)arg)->autodetect, sizeof(f->autodetect));
+			err |= __get_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
+			err |= __get_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
+			if (err) {
+				err = -EFAULT;
+				goto out;
+			}
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+			karg = kmalloc(sizeof(struct floppy_drive_struct), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDGETFDCSTAT32:
+			karg = kmalloc(sizeof(struct floppy_fdc_state), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		case FDWERRORGET32:
+			karg = kmalloc(sizeof(struct floppy_write_errors), GFP_KERNEL);
+			if (!karg)
+				return -ENOMEM;
+			break;
+		default:
+			return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err)
+		goto out;
+	switch (cmd) {
+		case FDGETPRM32:
+		{
+			struct floppy_struct *f = karg;
+
+			err = __put_user(f->size, &((struct floppy_struct32 *)arg)->size);
+			err |= __put_user(f->sect, &((struct floppy_struct32 *)arg)->sect);
+			err |= __put_user(f->head, &((struct floppy_struct32 *)arg)->head);
+			err |= __put_user(f->track, &((struct floppy_struct32 *)arg)->track);
+			err |= __put_user(f->stretch, &((struct floppy_struct32 *)arg)->stretch);
+			err |= __put_user(f->gap, &((struct floppy_struct32 *)arg)->gap);
+			err |= __put_user(f->rate, &((struct floppy_struct32 *)arg)->rate);
+			err |= __put_user(f->spec1, &((struct floppy_struct32 *)arg)->spec1);
+			err |= __put_user(f->fmt_gap, &((struct floppy_struct32 *)arg)->fmt_gap);
+			err |= __put_user((u64)f->name, &((struct floppy_struct32 *)arg)->name);
+			break;
+		}
+		case FDGETDRVPRM32:
+		{
+			struct floppy_drive_params *f = karg;
+
+			err = __put_user(f->cmos, &((struct floppy_drive_params32 *)arg)->cmos);
+			err |= __put_user(f->max_dtr, &((struct floppy_drive_params32 *)arg)->max_dtr);
+			err |= __put_user(f->hlt, &((struct floppy_drive_params32 *)arg)->hlt);
+			err |= __put_user(f->hut, &((struct floppy_drive_params32 *)arg)->hut);
+			err |= __put_user(f->srt, &((struct floppy_drive_params32 *)arg)->srt);
+			err |= __put_user(f->spinup, &((struct floppy_drive_params32 *)arg)->spinup);
+			err |= __put_user(f->spindown, &((struct floppy_drive_params32 *)arg)->spindown);
+			err |= __put_user(f->spindown_offset, &((struct floppy_drive_params32 *)arg)->spindown_offset);
+			err |= __put_user(f->select_delay, &((struct floppy_drive_params32 *)arg)->select_delay);
+			err |= __put_user(f->rps, &((struct floppy_drive_params32 *)arg)->rps);
+			err |= __put_user(f->tracks, &((struct floppy_drive_params32 *)arg)->tracks);
+			err |= __put_user(f->timeout, &((struct floppy_drive_params32 *)arg)->timeout);
+			err |= __put_user(f->interleave_sect, &((struct floppy_drive_params32 *)arg)->interleave_sect);
+			err |= __copy_to_user(&((struct floppy_drive_params32 *)arg)->max_errors, &f->max_errors, sizeof(f->max_errors));
+			err |= __put_user(f->flags, &((struct floppy_drive_params32 *)arg)->flags);
+			err |= __put_user(f->read_track, &((struct floppy_drive_params32 *)arg)->read_track);
+			err |= __copy_to_user(((struct floppy_drive_params32 *)arg)->autodetect, f->autodetect, sizeof(f->autodetect));
+			err |= __put_user(f->checkfreq, &((struct floppy_drive_params32 *)arg)->checkfreq);
+			err |= __put_user(f->native_format, &((struct floppy_drive_params32 *)arg)->native_format);
+			break;
+		}
+		case FDGETDRVSTAT32:
+		case FDPOLLDRVSTAT32:
+		{
+			struct floppy_drive_struct *f = karg;
+
+			err = __put_user(f->flags, &((struct floppy_drive_struct32 *)arg)->flags);
+			err |= __put_user(f->spinup_date, &((struct floppy_drive_struct32 *)arg)->spinup_date);
+			err |= __put_user(f->select_date, &((struct floppy_drive_struct32 *)arg)->select_date);
+			err |= __put_user(f->first_read_date, &((struct floppy_drive_struct32 *)arg)->first_read_date);
+			err |= __put_user(f->probed_format, &((struct floppy_drive_struct32 *)arg)->probed_format);
+			err |= __put_user(f->track, &((struct floppy_drive_struct32 *)arg)->track);
+			err |= __put_user(f->maxblock, &((struct floppy_drive_struct32 *)arg)->maxblock);
+			err |= __put_user(f->maxtrack, &((struct floppy_drive_struct32 *)arg)->maxtrack);
+			err |= __put_user(f->generation, &((struct floppy_drive_struct32 *)arg)->generation);
+			err |= __put_user(f->keep_data, &((struct floppy_drive_struct32 *)arg)->keep_data);
+			err |= __put_user(f->fd_ref, &((struct floppy_drive_struct32 *)arg)->fd_ref);
+			err |= __put_user(f->fd_device, &((struct floppy_drive_struct32 *)arg)->fd_device);
+			err |= __put_user(f->last_checked, &((struct floppy_drive_struct32 *)arg)->last_checked);
+			err |= __put_user((u64)f->dmabuf, &((struct floppy_drive_struct32 *)arg)->dmabuf);
+			err |= __put_user((u64)f->bufblocks, &((struct floppy_drive_struct32 *)arg)->bufblocks);
+			break;
+		}
+		case FDGETFDCSTAT32:
+		{
+			struct floppy_fdc_state *f = karg;
+
+			err = __put_user(f->spec1, &((struct floppy_fdc_state32 *)arg)->spec1);
+			err |= __put_user(f->spec2, &((struct floppy_fdc_state32 *)arg)->spec2);
+			err |= __put_user(f->dtr, &((struct floppy_fdc_state32 *)arg)->dtr);
+			err |= __put_user(f->version, &((struct floppy_fdc_state32 *)arg)->version);
+			err |= __put_user(f->dor, &((struct floppy_fdc_state32 *)arg)->dor);
+			err |= __put_user(f->address, &((struct floppy_fdc_state32 *)arg)->address);
+			err |= __copy_to_user((char *)&((struct floppy_fdc_state32 *)arg)->address
+			    		   + sizeof(((struct floppy_fdc_state32 *)arg)->address),
+					   (char *)&f->address + sizeof(f->address), sizeof(int));
+			err |= __put_user(f->driver_version, &((struct floppy_fdc_state32 *)arg)->driver_version);
+			err |= __copy_to_user(((struct floppy_fdc_state32 *)arg)->track, f->track, sizeof(f->track));
+			break;
+		}
+		case FDWERRORGET32:
+		{
+			struct floppy_write_errors *f = karg;
+
+			err = __put_user(f->write_errors, &((struct floppy_write_errors32 *)arg)->write_errors);
+			err |= __put_user(f->first_error_sector, &((struct floppy_write_errors32 *)arg)->first_error_sector);
+			err |= __put_user(f->first_error_generation, &((struct floppy_write_errors32 *)arg)->first_error_generation);
+			err |= __put_user(f->last_error_sector, &((struct floppy_write_errors32 *)arg)->last_error_sector);
+			err |= __put_user(f->last_error_generation, &((struct floppy_write_errors32 *)arg)->last_error_generation);
+			err |= __put_user(f->badness, &((struct floppy_write_errors32 *)arg)->badness);
+			break;
+		}
+		default:
+			break;
+	}
+	if (err)
+		err = -EFAULT;
+
+out:	if (karg) kfree(karg);
+	return err;
+}
+
+struct ppp_option_data32 {
+	__kernel_caddr_t32	ptr;
+	__u32			length;
+	int			transmit;
+};
+#define PPPIOCSCOMPRESS32	_IOW('t', 77, struct ppp_option_data32)
+
+struct ppp_idle32 {
+	__kernel_time_t32 xmit_idle;
+	__kernel_time_t32 recv_idle;
+};
+#define PPPIOCGIDLE32		_IOR('t', 63, struct ppp_idle32)
+
+static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct ppp_option_data32 data32;
+	struct ppp_option_data data;
+	struct ppp_idle32 idle32;
+	struct ppp_idle idle;
+	unsigned int kcmd;
+	void *karg;
+	int err = 0;
+
+	switch (cmd) {
+	case PPPIOCGIDLE32:
+		kcmd = PPPIOCGIDLE;
+		karg = &idle;
+		break;
+	case PPPIOCSCOMPRESS32:
+		if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32)))
+			return -EFAULT;
+		data.ptr = kmalloc (data32.length, GFP_KERNEL);
+		if (!data.ptr)
+			return -ENOMEM;
+		if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) {
+			kfree(data.ptr);
+			return -EFAULT;
+		}
+		data.length = data32.length;
+		data.transmit = data32.transmit;
+		kcmd = PPPIOCSCOMPRESS;
+		karg = &data;
+		break;
+	default:
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk(KERN_WARNING
+					"ppp_ioctl: Unknown cmd fd(%d) "
+					"cmd(%08x) arg(%08x)\n",
+					(int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	switch (cmd) {
+	case PPPIOCGIDLE32:
+		if (err)
+			return err;
+		idle32.xmit_idle = idle.xmit_idle;
+		idle32.recv_idle = idle.recv_idle;
+		if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32)))
+			return -EFAULT;
+		break;
+	case PPPIOCSCOMPRESS32:
+		kfree(data.ptr);
+		break;
+	default:
+		break;
+	}
+	return err;
+}
+
+
+struct mtget32 {
+	__u32	mt_type;
+	__u32	mt_resid;
+	__u32	mt_dsreg;
+	__u32	mt_gstat;
+	__u32	mt_erreg;
+	__kernel_daddr_t32	mt_fileno;
+	__kernel_daddr_t32	mt_blkno;
+};
+#define MTIOCGET32	_IOR('m', 2, struct mtget32)
+
+struct mtpos32 {
+	__u32	mt_blkno;
+};
+#define MTIOCPOS32	_IOR('m', 3, struct mtpos32)
+
+struct mtconfiginfo32 {
+	__u32	mt_type;
+	__u32	ifc_type;
+	__u16	irqnr;
+	__u16	dmanr;
+	__u16	port;
+	__u32	debug;
+	__u32	have_dens:1;
+	__u32	have_bsf:1;
+	__u32	have_fsr:1;
+	__u32	have_bsr:1;
+	__u32	have_eod:1;
+	__u32	have_seek:1;
+	__u32	have_tell:1;
+	__u32	have_ras1:1;
+	__u32	have_ras2:1;
+	__u32	have_ras3:1;
+	__u32	have_qfa:1;
+	__u32	pad1:5;
+	char	reserved[10];
+};
+#define	MTIOCGETCONFIG32	_IOR('m', 4, struct mtconfiginfo32)
+#define	MTIOCSETCONFIG32	_IOW('m', 5, struct mtconfiginfo32)
+
+static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct mtconfiginfo info;
+	struct mtget get;
+	struct mtpos pos;
+	unsigned long kcmd;
+	void *karg;
+	int err = 0;
+
+	switch(cmd) {
+	case MTIOCPOS32:
+		kcmd = MTIOCPOS;
+		karg = &pos;
+		break;
+	case MTIOCGET32:
+		kcmd = MTIOCGET;
+		karg = &get;
+		break;
+	case MTIOCGETCONFIG32:
+		kcmd = MTIOCGETCONFIG;
+		karg = &info;
+		break;
+	case MTIOCSETCONFIG32:
+		kcmd = MTIOCSETCONFIG;
+		karg = &info;
+		err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+		err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+		err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+		err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+		err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+		err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+		err |= __copy_from_user((char *)&info.debug + sizeof(info.debug),
+				     (char *)&((struct mtconfiginfo32 *)arg)->debug
+				     + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32));
+		if (err)
+			return -EFAULT;
+		break;
+	default:
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk(KERN_WARNING
+					"mt_ioctl: Unknown cmd fd(%d) "
+					"cmd(%08x) arg(%08x)\n",
+					(int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, kcmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err)
+		return err;
+	switch (cmd) {
+	case MTIOCPOS32:
+		err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno);
+		break;
+	case MTIOCGET32:
+		err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type);
+		err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid);
+		err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg);
+		err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat);
+		err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg);
+		err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno);
+		err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno);
+		break;
+	case MTIOCGETCONFIG32:
+		err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type);
+		err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
+		err |= __put_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr);
+		err |= __put_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr);
+		err |= __put_user(info.port, &((struct mtconfiginfo32 *)arg)->port);
+		err |= __put_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug);
+		err |= __copy_to_user((char *)&((struct mtconfiginfo32 *)arg)->debug
+			    		   + sizeof(((struct mtconfiginfo32 *)arg)->debug),
+					   (char *)&info.debug + sizeof(info.debug), sizeof(__u32));
+		break;
+	case MTIOCSETCONFIG32:
+		break;
+	}
+	return err ? -EFAULT: 0;
+}
+
+struct cdrom_read32 {
+	int			cdread_lba;
+	__kernel_caddr_t32	cdread_bufaddr;
+	int			cdread_buflen;
+};
+
+struct cdrom_read_audio32 {
+	union cdrom_addr	addr;
+	u_char			addr_format;
+	int			nframes;
+	__kernel_caddr_t32	buf;
+};
+
+struct cdrom_generic_command32 {
+	unsigned char		cmd[CDROM_PACKET_SIZE];
+	__kernel_caddr_t32	buffer;
+	unsigned int		buflen;
+	int			stat;
+	__kernel_caddr_t32	sense;
+	__kernel_caddr_t32	reserved[3];
+};
+
+static int cdrom_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct cdrom_read cdread;
+	struct cdrom_read_audio cdreadaudio;
+	struct cdrom_generic_command cgc;
+	__kernel_caddr_t32 addr;
+	char *data = 0;
+	void *karg;
+	int err = 0;
+
+	switch(cmd) {
+	case CDROMREADMODE2:
+	case CDROMREADMODE1:
+	case CDROMREADRAW:
+	case CDROMREADCOOKED:
+		karg = &cdread;
+		err = __get_user(cdread.cdread_lba, &((struct cdrom_read32 *)arg)->cdread_lba);
+		err |= __get_user(addr, &((struct cdrom_read32 *)arg)->cdread_bufaddr);
+		err |= __get_user(cdread.cdread_buflen, &((struct cdrom_read32 *)arg)->cdread_buflen);
+		if (err)
+			return -EFAULT;
+		data = kmalloc(cdread.cdread_buflen, GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+		cdread.cdread_bufaddr = data;
+		break;
+	case CDROMREADAUDIO:
+		karg = &cdreadaudio;
+		err = copy_from_user(&cdreadaudio.addr, &((struct cdrom_read_audio32 *)arg)->addr, sizeof(cdreadaudio.addr));
+		err |= __get_user(cdreadaudio.addr_format, &((struct cdrom_read_audio32 *)arg)->addr_format);
+		err |= __get_user(cdreadaudio.nframes, &((struct cdrom_read_audio32 *)arg)->nframes); 
+		err |= __get_user(addr, &((struct cdrom_read_audio32 *)arg)->buf);
+		if (err)
+			return -EFAULT;
+		data = kmalloc(cdreadaudio.nframes * 2352, GFP_KERNEL);
+		if (!data)
+			return -ENOMEM;
+		cdreadaudio.buf = data;
+		break;
+	case CDROM_SEND_PACKET:
+		karg = &cgc;
+		err = copy_from_user(cgc.cmd, &((struct cdrom_generic_command32 *)arg)->cmd, sizeof(cgc.cmd));
+		err |= __get_user(addr, &((struct cdrom_generic_command32 *)arg)->buffer);
+		err |= __get_user(cgc.buflen, &((struct cdrom_generic_command32 *)arg)->buflen);
+		if (err)
+			return -EFAULT;
+		if ((data = kmalloc(cgc.buflen, GFP_KERNEL)) == NULL)
+			return -ENOMEM;
+		cgc.buffer = data;
+		break;
+	default:
+		do {
+			static int count = 0;
+			if (++count <= 20)
+				printk(KERN_WARNING
+					"cdrom_ioctl: Unknown cmd fd(%d) "
+					"cmd(%08x) arg(%08x)\n",
+					(int)fd, (unsigned int)cmd, (unsigned int)arg);
+		} while(0);
+		return -EINVAL;
+	}
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)karg);
+	set_fs (old_fs);
+	if (err)
+		goto out;
+	switch (cmd) {
+	case CDROMREADMODE2:
+	case CDROMREADMODE1:
+	case CDROMREADRAW:
+	case CDROMREADCOOKED:
+		err = copy_to_user((char *)A(addr), data, cdread.cdread_buflen);
+		break;
+	case CDROMREADAUDIO:
+		err = copy_to_user((char *)A(addr), data, cdreadaudio.nframes * 2352);
+		break;
+	case CDROM_SEND_PACKET:
+		err = copy_to_user((char *)A(addr), data, cgc.buflen);
+		break;
+	default:
+		break;
+	}
+out:	if (data)
+		kfree(data);
+	return err ? -EFAULT : 0;
+}
+
+struct loop_info32 {
+	int			lo_number;      /* ioctl r/o */
+	__kernel_dev_t32	lo_device;      /* ioctl r/o */
+	unsigned int		lo_inode;       /* ioctl r/o */
+	__kernel_dev_t32	lo_rdevice;     /* ioctl r/o */
+	int			lo_offset;
+	int			lo_encrypt_type;
+	int			lo_encrypt_key_size;    /* ioctl w/o */
+	int			lo_flags;       /* ioctl r/o */
+	char			lo_name[LO_NAME_SIZE];
+	unsigned char		lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+	unsigned int		lo_init[2];
+	char			reserved[4];
+};
+
+static int loop_status(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	struct loop_info l;
+	int err = -EINVAL;
+
+	switch(cmd) {
+	case LOOP_SET_STATUS:
+		err = get_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
+		err |= __get_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
+		err |= __get_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
+		err |= __get_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
+		err |= __copy_from_user((char *)&l.lo_offset, (char *)&((struct loop_info32 *)arg)->lo_offset,
+					   8 + (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+		if (err) {
+			err = -EFAULT;
+		} else {
+			set_fs (KERNEL_DS);
+			err = sys_ioctl (fd, cmd, (unsigned long)&l);
+			set_fs (old_fs);
+		}
+		break;
+	case LOOP_GET_STATUS:
+		set_fs (KERNEL_DS);
+		err = sys_ioctl (fd, cmd, (unsigned long)&l);
+		set_fs (old_fs);
+		if (!err) {
+			err = put_user(l.lo_number, &((struct loop_info32 *)arg)->lo_number);
+			err |= __put_user(l.lo_device, &((struct loop_info32 *)arg)->lo_device);
+			err |= __put_user(l.lo_inode, &((struct loop_info32 *)arg)->lo_inode);
+			err |= __put_user(l.lo_rdevice, &((struct loop_info32 *)arg)->lo_rdevice);
+			err |= __copy_to_user((char *)&((struct loop_info32 *)arg)->lo_offset,
+					   (char *)&l.lo_offset, (unsigned long)l.lo_init - (unsigned long)&l.lo_offset);
+			if (err)
+				err = -EFAULT;
+		}
+		break;
+	default: {
+		static int count = 0;
+		if (++count <= 20)
+			printk(KERN_WARNING
+				"%s: Unknown loop ioctl cmd, fd(%d) "
+				"cmd(%08x) arg(%08lx)\n",
+				__FUNCTION__, fd, cmd, arg);
+	}
+	}
+	return err;
+}
+
+#ifdef CONFIG_VT
+extern int tty_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
+
+static int vt_check(struct file *file)
+{
+	struct tty_struct *tty;
+	struct inode *inode = file->f_dentry->d_inode;
+	
+	if (file->f_op->ioctl != tty_ioctl)
+		return -EINVAL;
+	                
+	tty = (struct tty_struct *)file->private_data;
+	if (tty_paranoia_check(tty, inode->i_rdev, "tty_ioctl"))
+		return -EINVAL;
+	                                                
+	if (tty->driver.ioctl != vt_ioctl)
+		return -EINVAL;
+	
+	/*
+	 * To have permissions to do most of the vt ioctls, we either have
+	 * to be the owner of the tty, or super-user.
+	 */
+	if (current->tty == tty || suser())
+		return 1;
+	return 0;                                                    
+}
+
+struct consolefontdesc32 {
+	unsigned short charcount;       /* characters in font (256 or 512) */
+	unsigned short charheight;      /* scan lines per character (1-32) */
+	u32 chardata;			/* font data in expanded form */
+};
+
+static int do_fontx_ioctl(unsigned int fd, int cmd, struct consolefontdesc32 *user_cfd, struct file *file)
+{
+	struct consolefontdesc cfdarg;
+	struct console_font_op op;
+	int i, perm;
+
+	perm = vt_check(file);
+	if (perm < 0) return perm;
+	
+	if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc32)))
+		return -EFAULT;
+	
+	cfdarg.chardata = (unsigned char *)A(((struct consolefontdesc32 *)&cfdarg)->chardata);
+ 	
+	switch (cmd) {
+	case PIO_FONTX:
+		if (!perm)
+			return -EPERM;
+		op.op = KD_FONT_OP_SET;
+		op.flags = 0;
+		op.width = 8;
+		op.height = cfdarg.charheight;
+		op.charcount = cfdarg.charcount;
+		op.data = cfdarg.chardata;
+		return con_font_op(fg_console, &op);
+	case GIO_FONTX:
+		if (!cfdarg.chardata)
+			return 0;
+		op.op = KD_FONT_OP_GET;
+		op.flags = 0;
+		op.width = 8;
+		op.height = cfdarg.charheight;
+		op.charcount = cfdarg.charcount;
+		op.data = cfdarg.chardata;
+		i = con_font_op(fg_console, &op);
+		if (i)
+			return i;
+		cfdarg.charheight = op.height;
+		cfdarg.charcount = op.charcount;
+		((struct consolefontdesc32 *)&cfdarg)->chardata	= (unsigned long)cfdarg.chardata;
+		if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc32)))
+			return -EFAULT;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+struct console_font_op32 {
+	unsigned int op;        /* operation code KD_FONT_OP_* */
+	unsigned int flags;     /* KD_FONT_FLAG_* */
+	unsigned int width, height;     /* font size */
+	unsigned int charcount;
+	u32 data;    /* font data with height fixed to 32 */
+};
+                                        
+static int do_kdfontop_ioctl(unsigned int fd, unsigned int cmd, struct console_font_op32 *fontop, struct file *file)
+{
+	struct console_font_op op;
+	int perm = vt_check(file), i;
+	struct vt_struct *vt;
+	
+	if (perm < 0) return perm;
+	
+	if (copy_from_user(&op, (void *) fontop, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	if (!perm && op.op != KD_FONT_OP_GET)
+		return -EPERM;
+	op.data = (unsigned char *)A(((struct console_font_op32 *)&op)->data);
+	op.flags |= KD_FONT_FLAG_OLD;
+	vt = (struct vt_struct *)((struct tty_struct *)file->private_data)->driver_data;
+	i = con_font_op(vt->vc_num, &op);
+	if (i) return i;
+	((struct console_font_op32 *)&op)->data = (unsigned long)op.data;
+	if (copy_to_user((void *) fontop, &op, sizeof(struct console_font_op32)))
+		return -EFAULT;
+	return 0;
+}
+
+struct unimapdesc32 {
+	unsigned short entry_ct;
+	u32 entries;
+};
+
+static int do_unimap_ioctl(unsigned int fd, unsigned int cmd, struct unimapdesc32 *user_ud, struct file *file)
+{
+	struct unimapdesc32 tmp;
+	int perm = vt_check(file);
+	
+	if (perm < 0) return perm;
+	if (copy_from_user(&tmp, user_ud, sizeof tmp))
+		return -EFAULT;
+	switch (cmd) {
+	case PIO_UNIMAP:
+		if (!perm) return -EPERM;
+		return con_set_unimap(fg_console, tmp.entry_ct, (struct unipair *)A(tmp.entries));
+	case GIO_UNIMAP:
+		return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), (struct unipair *)A(tmp.entries));
+	}
+	return 0;
+}
+#endif
+
+#if 0
+static int do_smb_getmountuid(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	__kernel_uid_t kuid;
+	int err;
+
+	cmd = SMB_IOC_GETMOUNTUID;
+
+	set_fs(KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&kuid);
+	set_fs(old_fs);
+
+	if (err >= 0)
+		err = put_user(kuid, (__kernel_uid_t32 *)arg);
+
+	return err;
+}
+#endif
+
+struct atmif_sioc32 {
+        int                number;
+        int                length;
+        __kernel_caddr_t32 arg;
+};
+
+struct atm_iobuf32 {
+	int                length;
+	__kernel_caddr_t32 buffer;
+};
+
+#define ATM_GETLINKRATE32 _IOW('a', ATMIOC_ITF+1, struct atmif_sioc32)
+#define ATM_GETNAMES32    _IOW('a', ATMIOC_ITF+3, struct atm_iobuf32)
+#define ATM_GETTYPE32     _IOW('a', ATMIOC_ITF+4, struct atmif_sioc32)
+#define ATM_GETESI32	  _IOW('a', ATMIOC_ITF+5, struct atmif_sioc32)
+#define ATM_GETADDR32	  _IOW('a', ATMIOC_ITF+6, struct atmif_sioc32)
+#define ATM_RSTADDR32	  _IOW('a', ATMIOC_ITF+7, struct atmif_sioc32)
+#define ATM_ADDADDR32	  _IOW('a', ATMIOC_ITF+8, struct atmif_sioc32)
+#define ATM_DELADDR32	  _IOW('a', ATMIOC_ITF+9, struct atmif_sioc32)
+#define ATM_GETCIRANGE32  _IOW('a', ATMIOC_ITF+10, struct atmif_sioc32)
+#define ATM_SETCIRANGE32  _IOW('a', ATMIOC_ITF+11, struct atmif_sioc32)
+#define ATM_SETESI32      _IOW('a', ATMIOC_ITF+12, struct atmif_sioc32)
+#define ATM_SETESIF32     _IOW('a', ATMIOC_ITF+13, struct atmif_sioc32)
+#define ATM_GETSTAT32     _IOW('a', ATMIOC_SARCOM+0, struct atmif_sioc32)
+#define ATM_GETSTATZ32    _IOW('a', ATMIOC_SARCOM+1, struct atmif_sioc32)
+#define ATM_GETLOOP32	  _IOW('a', ATMIOC_SARCOM+2, struct atmif_sioc32)
+#define ATM_SETLOOP32	  _IOW('a', ATMIOC_SARCOM+3, struct atmif_sioc32)
+#define ATM_QUERYLOOP32	  _IOW('a', ATMIOC_SARCOM+4, struct atmif_sioc32)
+
+static struct {
+        unsigned int cmd32;
+        unsigned int cmd;
+} atm_ioctl_map[] = {
+        { ATM_GETLINKRATE32, ATM_GETLINKRATE },
+	{ ATM_GETNAMES32,    ATM_GETNAMES },
+        { ATM_GETTYPE32,     ATM_GETTYPE },
+        { ATM_GETESI32,      ATM_GETESI },
+        { ATM_GETADDR32,     ATM_GETADDR },
+        { ATM_RSTADDR32,     ATM_RSTADDR },
+        { ATM_ADDADDR32,     ATM_ADDADDR },
+        { ATM_DELADDR32,     ATM_DELADDR },
+        { ATM_GETCIRANGE32,  ATM_GETCIRANGE },
+	{ ATM_SETCIRANGE32,  ATM_SETCIRANGE },
+	{ ATM_SETESI32,      ATM_SETESI },
+	{ ATM_SETESIF32,     ATM_SETESIF },
+	{ ATM_GETSTAT32,     ATM_GETSTAT },
+	{ ATM_GETSTATZ32,    ATM_GETSTATZ },
+	{ ATM_GETLOOP32,     ATM_GETLOOP },
+	{ ATM_SETLOOP32,     ATM_SETLOOP },
+	{ ATM_QUERYLOOP32,   ATM_QUERYLOOP }
+};
+
+#define NR_ATM_IOCTL (sizeof(atm_ioctl_map)/sizeof(atm_ioctl_map[0]))
+
+
+static int do_atm_iobuf(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct atm_iobuf32 iobuf32;
+	struct atm_iobuf   iobuf = { 0, NULL };
+	mm_segment_t old_fs;
+	int err;
+
+	err = copy_from_user(&iobuf32, (struct atm_iobuf32*)arg,
+	    sizeof(struct atm_iobuf32));
+	if (err)
+		return -EFAULT;
+
+	iobuf.length = iobuf32.length;
+
+	if (iobuf32.buffer == (__kernel_caddr_t32) NULL || iobuf32.length == 0) {
+		iobuf.buffer = (void*)(unsigned long)iobuf32.buffer;
+	} else {
+		iobuf.buffer = kmalloc(iobuf.length, GFP_KERNEL);
+		if (iobuf.buffer == NULL) {
+			err = -ENOMEM;
+			goto out;
+		}
+
+		err = copy_from_user(iobuf.buffer, A(iobuf32.buffer), iobuf.length);
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	old_fs = get_fs(); set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&iobuf);      
+	set_fs (old_fs);
+        if(err)
+		goto out;
+
+        if(iobuf.buffer && iobuf.length > 0) {
+		err = copy_to_user(A(iobuf32.buffer), iobuf.buffer, iobuf.length);
+		if (err) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+	err = __put_user(iobuf.length, &(((struct atm_iobuf32*)arg)->length));
+
+ out:
+        if(iobuf32.buffer && iobuf32.length > 0)
+		kfree(iobuf.buffer);
+
+	return err;
+}
+
+
+static int do_atmif_sioc(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+        struct atmif_sioc32 sioc32;
+        struct atmif_sioc   sioc = { 0, 0, NULL };
+        mm_segment_t old_fs;
+        int err;
+        
+        err = copy_from_user(&sioc32, (struct atmif_sioc32*)arg,
+			     sizeof(struct atmif_sioc32));
+        if (err)
+                return -EFAULT;
+
+        sioc.number = sioc32.number;
+        sioc.length = sioc32.length;
+        
+	if (sioc32.arg == (__kernel_caddr_t32) NULL || sioc32.length == 0) {
+		sioc.arg = (void*)(unsigned long)sioc32.arg;
+        } else {
+                sioc.arg = kmalloc(sioc.length, GFP_KERNEL);
+                if (sioc.arg == NULL) {
+                        err = -ENOMEM;
+			goto out;
+		}
+                
+                err = copy_from_user(sioc.arg, A(sioc32.arg), sioc32.length);
+                if (err) {
+                        err = -EFAULT;
+                        goto out;
+                }
+        }
+        
+        old_fs = get_fs(); set_fs (KERNEL_DS);
+        err = sys_ioctl (fd, cmd, (unsigned long)&sioc);	
+        set_fs (old_fs);
+        if(err) {
+                goto out;
+	}
+        
+        if(sioc.arg && sioc.length > 0) {
+                err = copy_to_user(A(sioc32.arg), sioc.arg, sioc.length);
+                if (err) {
+                        err = -EFAULT;
+                        goto out;
+                }
+        }
+        err = __put_user(sioc.length, &(((struct atmif_sioc32*)arg)->length));
+        
+ out:
+        if(sioc32.arg && sioc32.length > 0)
+		kfree(sioc.arg);
+        
+	return err;
+}
+
+
+static int do_atm_ioctl(unsigned int fd, unsigned int cmd32, unsigned long arg)
+{
+        int i;
+        unsigned int cmd = 0;
+        
+	switch (cmd32) {
+	case SONET_GETSTAT:
+	case SONET_GETSTATZ:
+	case SONET_GETDIAG:
+	case SONET_SETDIAG:
+	case SONET_CLRDIAG:
+	case SONET_SETFRAMING:
+	case SONET_GETFRAMING:
+	case SONET_GETFRSENSE:
+		return do_atmif_sioc(fd, cmd32, arg);
+	}
+
+		for (i = 0; i < NR_ATM_IOCTL; i++) {
+			if (cmd32 == atm_ioctl_map[i].cmd32) {
+				cmd = atm_ioctl_map[i].cmd;
+				break;
+			}
+		}
+	        if (i == NR_ATM_IOCTL) {
+	        return -EINVAL;
+	        }
+        
+        switch (cmd) {
+	case ATM_GETNAMES:
+		return do_atm_iobuf(fd, cmd, arg);
+	    
+	case ATM_GETLINKRATE:
+        case ATM_GETTYPE:
+        case ATM_GETESI:
+        case ATM_GETADDR:
+        case ATM_RSTADDR:
+        case ATM_ADDADDR:
+        case ATM_DELADDR:
+        case ATM_GETCIRANGE:
+	case ATM_SETCIRANGE:
+	case ATM_SETESI:
+	case ATM_SETESIF:
+	case ATM_GETSTAT:
+	case ATM_GETSTATZ:
+	case ATM_GETLOOP:
+	case ATM_SETLOOP:
+	case ATM_QUERYLOOP:
+                return do_atmif_sioc(fd, cmd, arg);
+        }
+
+        return -EINVAL;
+}
+
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+/* Ugh, LVM. Pitty it was not cleaned up before accepted :((. */
+typedef struct {
+	uint8_t vg_name[NAME_LEN];
+	uint32_t vg_number;
+	uint32_t vg_access;
+	uint32_t vg_status;
+	uint32_t lv_max;
+	uint32_t lv_cur;
+	uint32_t lv_open;
+	uint32_t pv_max;
+	uint32_t pv_cur;
+	uint32_t pv_act;
+	uint32_t dummy;
+	uint32_t vgda;
+	uint32_t pe_size;
+	uint32_t pe_total;
+	uint32_t pe_allocated;
+	uint32_t pvg_total;
+	u32 proc;
+	u32 pv[ABS_MAX_PV + 1];
+	u32 lv[ABS_MAX_LV + 1];
+    	uint8_t vg_uuid[UUID_LEN+1];	/* volume group UUID */
+	uint8_t dummy1[200];
+} vg32_t;
+
+typedef struct {
+	uint8_t id[2];
+	uint16_t version;
+	lvm_disk_data_t pv_on_disk;
+	lvm_disk_data_t vg_on_disk;
+	lvm_disk_data_t pv_namelist_on_disk;
+	lvm_disk_data_t lv_on_disk;
+	lvm_disk_data_t pe_on_disk;
+	uint8_t pv_name[NAME_LEN];
+	uint8_t vg_name[NAME_LEN];
+	uint8_t system_id[NAME_LEN];
+	kdev_t pv_dev;
+	uint32_t pv_number;
+	uint32_t pv_status;
+	uint32_t pv_allocatable;
+	uint32_t pv_size;
+	uint32_t lv_cur;
+	uint32_t pe_size;
+	uint32_t pe_total;
+	uint32_t pe_allocated;
+	uint32_t pe_stale;
+	u32 pe;
+	u32 inode;
+	uint8_t pv_uuid[UUID_LEN+1];
+} pv32_t;
+
+typedef struct {
+	char lv_name[NAME_LEN];
+	u32 lv;
+} lv_req32_t;
+
+typedef struct {
+	u32 lv_index;
+	u32 lv;
+	/* Transfer size because user space and kernel space differ */
+	uint16_t size;
+} lv_status_byindex_req32_t;
+
+typedef struct {
+	__kernel_dev_t32 dev;
+	u32   lv;
+} lv_status_bydev_req32_t;
+
+typedef struct {
+	uint8_t lv_name[NAME_LEN];
+	kdev_t old_dev;
+	kdev_t new_dev;
+	u32 old_pe;
+	u32 new_pe;
+} le_remap_req32_t;
+
+typedef struct {
+	char pv_name[NAME_LEN];
+	u32 pv;
+} pv_status_req32_t;
+
+typedef struct {
+	uint8_t lv_name[NAME_LEN];
+	uint8_t vg_name[NAME_LEN];
+	uint32_t lv_access;
+	uint32_t lv_status;
+	uint32_t lv_open;
+	kdev_t lv_dev;
+	uint32_t lv_number;
+	uint32_t lv_mirror_copies;
+	uint32_t lv_recovery;
+	uint32_t lv_schedule;
+	uint32_t lv_size;
+	u32 lv_current_pe;
+	uint32_t lv_current_le;
+	uint32_t lv_allocated_le;
+	uint32_t lv_stripes;
+	uint32_t lv_stripesize;
+	uint32_t lv_badblock;
+	uint32_t lv_allocation;
+	uint32_t lv_io_timeout;
+	uint32_t lv_read_ahead;
+	/* delta to version 1 starts here */
+	u32 lv_snapshot_org;
+	u32 lv_snapshot_prev;
+	u32 lv_snapshot_next;
+	u32 lv_block_exception;
+	uint32_t lv_remap_ptr;
+	uint32_t lv_remap_end;
+	uint32_t lv_chunk_size;
+	uint32_t lv_snapshot_minor;
+	char dummy[200];
+} lv32_t;
+
+typedef struct {
+	u32 hash[2];
+	u32 rsector_org;
+	kdev_t rdev_org;
+	u32 rsector_new;
+	kdev_t rdev_new;
+} lv_block_exception32_t;
+
+static void put_lv_t(lv_t *l)
+{
+	if (l->lv_current_pe) vfree(l->lv_current_pe);
+	if (l->lv_block_exception) vfree(l->lv_block_exception);
+	kfree(l);
+}
+
+static lv_t *get_lv_t(u32 p, int *errp)
+{
+	int err, i;
+	u32 ptr1, ptr2;
+	size_t size;
+	lv_block_exception32_t *lbe32;
+	lv_block_exception_t *lbe;
+	lv32_t *ul = (lv32_t *)A(p);
+	lv_t *l = (lv_t *) kmalloc(sizeof(lv_t), GFP_KERNEL);
+
+	if (!l) {
+		*errp = -ENOMEM;
+		return NULL;
+	}
+	memset(l, 0, sizeof(lv_t));
+	err = copy_from_user(l, ul, (long)&((lv32_t *)0)->lv_current_pe);
+	err |= __copy_from_user(&l->lv_current_le, &ul->lv_current_le,
+				((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le));
+	err |= __copy_from_user(&l->lv_remap_ptr, &ul->lv_remap_ptr,
+				((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr));
+	err |= __get_user(ptr1, &ul->lv_current_pe);
+	err |= __get_user(ptr2, &ul->lv_block_exception);
+	if (err) {
+		kfree(l);
+		*errp = -EFAULT;
+		return NULL;
+	}
+	if (ptr1) {
+		size = l->lv_allocated_le * sizeof(pe_t);
+		l->lv_current_pe = vmalloc(size);
+		if (l->lv_current_pe)
+			err = copy_from_user(l->lv_current_pe, (void *)A(ptr1), size);
+	}
+	if (!err && ptr2) {
+		size = l->lv_remap_end * sizeof(lv_block_exception_t);
+		l->lv_block_exception = lbe = vmalloc(size);
+		if (l->lv_block_exception) {
+			lbe32 = (lv_block_exception32_t *)A(ptr2);
+			memset(lbe, 0, size);
+			for (i = 0; i < l->lv_remap_end; i++, lbe++, lbe32++) {
+				err |= get_user(lbe->rsector_org, &lbe32->rsector_org);
+				err |= __get_user(lbe->rdev_org, &lbe32->rdev_org);
+				err |= __get_user(lbe->rsector_new, &lbe32->rsector_new);
+				err |= __get_user(lbe->rdev_new, &lbe32->rdev_new);
+			}
+		}
+	}
+	if (err || (ptr1 && !l->lv_current_pe) || (ptr2 && !l->lv_block_exception)) {
+		if (!err)
+			*errp = -ENOMEM;
+		else
+			*errp = -EFAULT;
+		put_lv_t(l);
+		return NULL;
+	}
+	return l;
+}
+
+static int copy_lv_t(u32 ptr, lv_t *l)
+{
+	int err;
+	lv32_t *ul = (lv32_t *)A(ptr);
+	u32 ptr1;
+	size_t size;
+
+	err = get_user(ptr1, &ul->lv_current_pe);
+	if (err)
+		return -EFAULT;
+	err = copy_to_user(ul, l, (long)&((lv32_t *)0)->lv_current_pe);
+	err |= __copy_to_user(&ul->lv_current_le, &l->lv_current_le,
+				((long)&ul->lv_snapshot_org) - ((long)&ul->lv_current_le));
+	err |= __copy_to_user(&ul->lv_remap_ptr, &l->lv_remap_ptr,
+				((long)&ul->dummy[0]) - ((long)&ul->lv_remap_ptr));
+	size = l->lv_allocated_le * sizeof(pe_t);
+	if (ptr1)
+		err |= __copy_to_user((void *)A(ptr1), l->lv_current_pe, size);
+	return err ? -EFAULT : 0;
+}
+
+static int do_lvm_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	vg_t *v = NULL;
+	union {
+		lv_req_t lv_req;
+		le_remap_req_t le_remap;
+		lv_status_byindex_req_t lv_byindex;
+	        lv_status_bydev_req_t lv_bydev;
+		pv_status_req_t pv_status;
+	} u;
+	pv_t p;
+	int err;
+	u32 ptr = 0;
+	int i;
+	mm_segment_t old_fs;
+	void *karg = &u;
+
+	switch (cmd) {
+	case VG_STATUS:
+		v = kmalloc(sizeof(vg_t), GFP_KERNEL);
+		if (!v)
+			return -ENOMEM;
+		karg = v;
+		break;
+
+	case VG_CREATE_OLD:
+	case VG_CREATE:
+		v = kmalloc(sizeof(vg_t), GFP_KERNEL);
+		if (!v)
+			return -ENOMEM;
+		if (copy_from_user(v, (void *)arg, (long)&((vg32_t *)0)->proc)) {
+			kfree(v);
+			return -EFAULT;
+		}
+		/* 'proc' field is unused, just NULL it out. */
+		v->proc = NULL;
+		if (copy_from_user(v->vg_uuid, ((vg32_t *)arg)->vg_uuid, UUID_LEN+1)) {
+			kfree(v);
+			return -EFAULT;
+		}
+		    
+		karg = v;
+		memset(v->pv, 0, sizeof(v->pv) + sizeof(v->lv));
+		if (v->pv_max > ABS_MAX_PV || v->lv_max > ABS_MAX_LV)
+			return -EPERM;
+		for (i = 0; i < v->pv_max; i++) {
+			err = __get_user(ptr, &((vg32_t *)arg)->pv[i]);
+			if (err)
+				break;
+			if (ptr) {
+				v->pv[i] = kmalloc(sizeof(pv_t), GFP_KERNEL);
+				if (!v->pv[i]) {
+					err = -ENOMEM;
+					break;
+				}
+				err = copy_from_user(v->pv[i], (void *)A(ptr),
+						     sizeof(pv32_t) - 8 - UUID_LEN+1);
+				if (err) {
+					err = -EFAULT;
+					break;
+				}
+				err = copy_from_user(v->pv[i]->pv_uuid,
+						     ((pv32_t *)A(ptr))->pv_uuid,
+						     UUID_LEN+1);
+				if (err) {
+				        err = -EFAULT;
+					break;
+				}
+
+				v->pv[i]->pe = NULL;
+				v->pv[i]->bd = NULL;
+			}
+		}
+		if (!err) {
+			for (i = 0; i < v->lv_max; i++) {
+				err = __get_user(ptr, &((vg32_t *)arg)->lv[i]);
+				if (err)
+					break;
+				if (ptr) {
+					v->lv[i] = get_lv_t(ptr, &err);
+					if (err)
+						break;
+				}
+			}
+		}
+		break;
+
+	case LV_CREATE:
+	case LV_EXTEND:
+	case LV_REDUCE:
+	case LV_REMOVE:
+	case LV_RENAME:
+	case LV_STATUS_BYNAME:
+	        err = copy_from_user(&u.pv_status, arg, sizeof(u.pv_status.pv_name));
+		if (err)
+			return -EFAULT;
+		if (cmd != LV_REMOVE) {
+			err = __get_user(ptr, &((lv_req32_t *)arg)->lv);
+			if (err)
+				return err;
+			u.lv_req.lv = get_lv_t(ptr, &err);
+		} else
+			u.lv_req.lv = NULL;
+		break;
+
+	case LV_STATUS_BYINDEX:
+		err = get_user(u.lv_byindex.lv_index,
+			       &((lv_status_byindex_req32_t *)arg)->lv_index);
+		err |= __get_user(ptr, &((lv_status_byindex_req32_t *)arg)->lv);
+		if (err)
+			return err;
+		u.lv_byindex.lv = get_lv_t(ptr, &err);
+		break;
+
+	case LV_STATUS_BYDEV:
+	        err = get_user(u.lv_bydev.dev, &((lv_status_bydev_req32_t *)arg)->dev);
+		err |= __get_user(ptr, &((lv_status_bydev_req32_t *)arg)->lv);
+		if (err)
+			return err;
+		u.lv_bydev.lv = get_lv_t(ptr, &err);
+		break;
+
+	case VG_EXTEND:
+		err = copy_from_user(&p, (void *)arg, sizeof(pv32_t) - 8 - UUID_LEN+1);
+		if (err)
+			return -EFAULT;
+		err = copy_from_user(p.pv_uuid, ((pv32_t *)arg)->pv_uuid, UUID_LEN+1);
+		if (err)
+			return -EFAULT;
+		p.pe = NULL;
+		p.bd = NULL;
+		karg = &p;
+		break;
+
+	case PV_CHANGE:
+	case PV_STATUS:
+		err = copy_from_user(&u.pv_status, arg, sizeof(u.lv_req.lv_name));
+		if (err)
+			return -EFAULT;
+		err = __get_user(ptr, &((pv_status_req32_t *)arg)->pv);
+		if (err)
+			return err;
+		u.pv_status.pv = &p;
+		if (cmd == PV_CHANGE) {
+			err = copy_from_user(&p, (void *)A(ptr),
+					     sizeof(pv32_t) - 8 - UUID_LEN+1);
+			if (err)
+				return -EFAULT;
+			p.pe = NULL;
+			p.bd = NULL;
+		}
+		break;
+	};
+
+        old_fs = get_fs(); set_fs (KERNEL_DS);
+        err = sys_ioctl (fd, cmd, (unsigned long)karg);
+        set_fs (old_fs);
+
+	switch (cmd) {
+	case VG_STATUS:
+		if (!err) {
+			if (copy_to_user((void *)arg, v, (long)&((vg32_t *)0)->proc) ||
+			    clear_user(&((vg32_t *)arg)->proc, sizeof(vg32_t) - (long)&((vg32_t *)0)->proc))
+				err = -EFAULT;
+		}
+		if (copy_to_user(((vg32_t *)arg)->vg_uuid, v->vg_uuid, UUID_LEN+1)) {
+		        err = -EFAULT;
+		}
+		kfree(v);
+		break;
+
+	case VG_CREATE_OLD:
+	case VG_CREATE:
+		for (i = 0; i < v->pv_max; i++) {
+			if (v->pv[i])
+				kfree(v->pv[i]);
+		}
+		for (i = 0; i < v->lv_max; i++) {
+			if (v->lv[i])
+				put_lv_t(v->lv[i]);
+		}
+		kfree(v);
+		break;
+
+	case LV_STATUS_BYNAME:
+		if (!err && u.lv_req.lv)
+			err = copy_lv_t(ptr, u.lv_req.lv);
+		/* Fall through */
+
+        case LV_CREATE:
+	case LV_EXTEND:
+	case LV_REDUCE:
+		if (u.lv_req.lv)
+			put_lv_t(u.lv_req.lv);
+		break;
+
+	case LV_STATUS_BYINDEX:
+		if (u.lv_byindex.lv) {
+			if (!err)
+				err = copy_lv_t(ptr, u.lv_byindex.lv);
+			put_lv_t(u.lv_byindex.lv);
+		}
+		break;
+
+	case LV_STATUS_BYDEV:
+	        if (u.lv_bydev.lv) {
+			if (!err)
+				err = copy_lv_t(ptr, u.lv_bydev.lv);
+			put_lv_t(u.lv_byindex.lv);
+	        }
+	        break;
+
+	case PV_STATUS:
+		if (!err) {
+			err = copy_to_user((void *)A(ptr), &p, sizeof(pv32_t) - 8 - UUID_LEN+1);
+			if (err)
+				return -EFAULT;
+			err = copy_to_user(((pv_t *)A(ptr))->pv_uuid, p.pv_uuid, UUID_LEN + 1);
+			if (err)
+				return -EFAULT;
+		}
+		break;
+	};
+
+	return err;
+}
+#endif
+
+#ifdef CONFIG_GENRTC
+#endif
+
+#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
+/* This really belongs in include/linux/drm.h -DaveM */
+#include "../../../drivers/char/drm/drm.h"
+
+typedef struct drm32_version {
+	int    version_major;	  /* Major version			    */
+	int    version_minor;	  /* Minor version			    */
+	int    version_patchlevel;/* Patch level			    */
+	int    name_len;	  /* Length of name buffer		    */
+	u32    name;		  /* Name of driver			    */
+	int    date_len;	  /* Length of date buffer		    */
+	u32    date;		  /* User-space buffer to hold date	    */
+	int    desc_len;	  /* Length of desc buffer		    */
+	u32    desc;		  /* User-space buffer to hold desc	    */
+} drm32_version_t;
+#define DRM32_IOCTL_VERSION    DRM_IOWR(0x00, drm32_version_t)
+
+static int drm32_version(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_version_t *uversion = (drm32_version_t *)arg;
+	char *name_ptr, *date_ptr, *desc_ptr;
+	u32 tmp1, tmp2, tmp3;
+	drm_version_t kversion;
+	mm_segment_t old_fs;
+	int ret;
+
+	memset(&kversion, 0, sizeof(kversion));
+	if (get_user(kversion.name_len, &uversion->name_len) ||
+	    get_user(kversion.date_len, &uversion->date_len) ||
+	    get_user(kversion.desc_len, &uversion->desc_len) ||
+	    get_user(tmp1, &uversion->name) ||
+	    get_user(tmp2, &uversion->date) ||
+	    get_user(tmp3, &uversion->desc))
+		return -EFAULT;
+
+	name_ptr = (char *) A(tmp1);
+	date_ptr = (char *) A(tmp2);
+	desc_ptr = (char *) A(tmp3);
+
+	ret = -ENOMEM;
+	if (kversion.name_len && name_ptr) {
+		kversion.name = kmalloc(kversion.name_len, GFP_KERNEL);
+		if (!kversion.name)
+			goto out;
+	}
+	if (kversion.date_len && date_ptr) {
+		kversion.date = kmalloc(kversion.date_len, GFP_KERNEL);
+		if (!kversion.date)
+			goto out;
+	}
+	if (kversion.desc_len && desc_ptr) {
+		kversion.desc = kmalloc(kversion.desc_len, GFP_KERNEL);
+		if (!kversion.desc)
+			goto out;
+	}
+
+        old_fs = get_fs();
+	set_fs(KERNEL_DS);
+        ret = sys_ioctl (fd, DRM_IOCTL_VERSION, (unsigned long)&kversion);
+        set_fs(old_fs);
+
+	if (!ret) {
+		if ((kversion.name &&
+		     copy_to_user(name_ptr, kversion.name, kversion.name_len)) ||
+		    (kversion.date &&
+		     copy_to_user(date_ptr, kversion.date, kversion.date_len)) ||
+		    (kversion.desc &&
+		     copy_to_user(desc_ptr, kversion.desc, kversion.desc_len)))
+			ret = -EFAULT;
+		if (put_user(kversion.version_major, &uversion->version_major) ||
+		    put_user(kversion.version_minor, &uversion->version_minor) ||
+		    put_user(kversion.version_patchlevel, &uversion->version_patchlevel) ||
+		    put_user(kversion.name_len, &uversion->name_len) ||
+		    put_user(kversion.date_len, &uversion->date_len) ||
+		    put_user(kversion.desc_len, &uversion->desc_len))
+			ret = -EFAULT;
+	}
+
+out:
+	if (kversion.name)
+		kfree(kversion.name);
+	if (kversion.date)
+		kfree(kversion.date);
+	if (kversion.desc)
+		kfree(kversion.desc);
+	return ret;
+}
+
+typedef struct drm32_unique {
+	int	unique_len;	  /* Length of unique			    */
+	u32	unique;		  /* Unique name for driver instantiation   */
+} drm32_unique_t;
+#define DRM32_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm32_unique_t)
+#define DRM32_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm32_unique_t)
+
+static int drm32_getsetunique(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_unique_t *uarg = (drm32_unique_t *)arg;
+	drm_unique_t karg;
+	mm_segment_t old_fs;
+	char *uptr;
+	u32 tmp;
+	int ret;
+
+	if (get_user(karg.unique_len, &uarg->unique_len))
+		return -EFAULT;
+	karg.unique = NULL;
+
+	if (get_user(tmp, &uarg->unique))
+		return -EFAULT;
+
+	uptr = (char *) A(tmp);
+
+	if (uptr) {
+		karg.unique = kmalloc(karg.unique_len, GFP_KERNEL);
+		if (!karg.unique)
+			return -ENOMEM;
+		if (cmd == DRM32_IOCTL_SET_UNIQUE &&
+		    copy_from_user(karg.unique, uptr, karg.unique_len)) {
+			kfree(karg.unique);
+			return -EFAULT;
+		}
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	if (cmd == DRM32_IOCTL_GET_UNIQUE)
+		ret = sys_ioctl (fd, DRM_IOCTL_GET_UNIQUE, (unsigned long)&karg);
+	else
+		ret = sys_ioctl (fd, DRM_IOCTL_SET_UNIQUE, (unsigned long)&karg);
+        set_fs(old_fs);
+
+	if (!ret) {
+		if (cmd == DRM32_IOCTL_GET_UNIQUE &&
+		    uptr != NULL &&
+		    copy_to_user(uptr, karg.unique, karg.unique_len))
+			ret = -EFAULT;
+		if (put_user(karg.unique_len, &uarg->unique_len))
+			ret = -EFAULT;
+	}
+
+	if (karg.unique != NULL)
+		kfree(karg.unique);
+
+	return ret;
+}
+
+typedef struct drm32_map {
+	u32		offset;	 /* Requested physical address (0 for SAREA)*/
+	u32		size;	 /* Requested physical size (bytes)	    */
+	drm_map_type_t	type;	 /* Type of memory to map		    */
+	drm_map_flags_t flags;	 /* Flags				    */
+	u32		handle;  /* User-space: "Handle" to pass to mmap    */
+				 /* Kernel-space: kernel-virtual address    */
+	int		mtrr;	 /* MTRR slot used			    */
+				 /* Private data			    */
+} drm32_map_t;
+#define DRM32_IOCTL_ADD_MAP    DRM_IOWR(0x15, drm32_map_t)
+
+static int drm32_addmap(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_map_t *uarg = (drm32_map_t *) arg;
+	drm_map_t karg;
+	mm_segment_t old_fs;
+	u32 tmp;
+	int ret;
+
+	ret  = get_user(karg.offset, &uarg->offset);
+	ret |= get_user(karg.size, &uarg->size);
+	ret |= get_user(karg.type, &uarg->type);
+	ret |= get_user(karg.flags, &uarg->flags);
+	ret |= get_user(tmp, &uarg->handle);
+	ret |= get_user(karg.mtrr, &uarg->mtrr);
+	if (ret)
+		return -EFAULT;
+
+	karg.handle = (void *) A(tmp);
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, DRM_IOCTL_ADD_MAP, (unsigned long) &karg);
+	set_fs(old_fs);
+
+	if (!ret) {
+		ret  = put_user(karg.offset, &uarg->offset);
+		ret |= put_user(karg.size, &uarg->size);
+		ret |= put_user(karg.type, &uarg->type);
+		ret |= put_user(karg.flags, &uarg->flags);
+		tmp = (u32) (long)karg.handle;
+		ret |= put_user(tmp, &uarg->handle);
+		ret |= put_user(karg.mtrr, &uarg->mtrr);
+		if (ret)
+			ret = -EFAULT;
+	}
+
+	return ret;
+}
+
+typedef struct drm32_buf_info {
+	int	       count;	/* Entries in list			     */
+	u32	       list;    /* (drm_buf_desc_t *) */ 
+} drm32_buf_info_t;
+#define DRM32_IOCTL_INFO_BUFS  DRM_IOWR(0x18, drm32_buf_info_t)
+
+static int drm32_info_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_buf_info_t *uarg = (drm32_buf_info_t *)arg;
+	drm_buf_desc_t *ulist;
+	drm_buf_info_t karg;
+	mm_segment_t old_fs;
+	int orig_count, ret;
+	u32 tmp;
+
+	if (get_user(karg.count, &uarg->count) ||
+	    get_user(tmp, &uarg->list))
+		return -EFAULT;
+
+	ulist = (drm_buf_desc_t *) A(tmp);
+
+	orig_count = karg.count;
+
+	karg.list = kmalloc(karg.count * sizeof(drm_buf_desc_t), GFP_KERNEL);
+	if (!karg.list)
+		return -EFAULT;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, DRM_IOCTL_INFO_BUFS, (unsigned long) &karg);
+	set_fs(old_fs);
+
+	if (!ret) {
+		if (karg.count <= orig_count &&
+		    (copy_to_user(ulist, karg.list,
+				  karg.count * sizeof(drm_buf_desc_t))))
+			ret = -EFAULT;
+		if (put_user(karg.count, &uarg->count))
+			ret = -EFAULT;
+	}
+
+	kfree(karg.list);
+
+	return ret;
+}
+
+typedef struct drm32_buf_free {
+	int	       count;
+	u32	       list;	/* (int *) */
+} drm32_buf_free_t;
+#define DRM32_IOCTL_FREE_BUFS  DRM_IOW( 0x1a, drm32_buf_free_t)
+
+static int drm32_free_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_buf_free_t *uarg = (drm32_buf_free_t *)arg;
+	drm_buf_free_t karg;
+	mm_segment_t old_fs;
+	int *ulist;
+	int ret;
+	u32 tmp;
+
+	if (get_user(karg.count, &uarg->count) ||
+	    get_user(tmp, &uarg->list))
+		return -EFAULT;
+
+	ulist = (int *) A(tmp);
+
+	karg.list = kmalloc(karg.count * sizeof(int), GFP_KERNEL);
+	if (!karg.list)
+		return -ENOMEM;
+
+	ret = -EFAULT;
+	if (copy_from_user(karg.list, ulist, (karg.count * sizeof(int))))
+		goto out;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, DRM_IOCTL_FREE_BUFS, (unsigned long) &karg);
+	set_fs(old_fs);
+
+out:
+	kfree(karg.list);
+
+	return ret;
+}
+
+typedef struct drm32_buf_pub {
+	int		  idx;	       /* Index into master buflist	     */
+	int		  total;       /* Buffer size			     */
+	int		  used;	       /* Amount of buffer in use (for DMA)  */
+	u32		  address;     /* Address of buffer (void *)	     */
+} drm32_buf_pub_t;
+
+typedef struct drm32_buf_map {
+	int	      count;	/* Length of buflist			    */
+	u32	      virtual;	/* Mmaped area in user-virtual (void *)	    */
+	u32 	      list;	/* Buffer information (drm_buf_pub_t *)	    */
+} drm32_buf_map_t;
+#define DRM32_IOCTL_MAP_BUFS   DRM_IOWR(0x19, drm32_buf_map_t)
+
+static int drm32_map_bufs(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_buf_map_t *uarg = (drm32_buf_map_t *)arg;
+	drm32_buf_pub_t *ulist;
+	drm_buf_map_t karg;
+	mm_segment_t old_fs;
+	int orig_count, ret, i;
+	u32 tmp1, tmp2;
+
+	if (get_user(karg.count, &uarg->count) ||
+	    get_user(tmp1, &uarg->virtual) ||
+	    get_user(tmp2, &uarg->list))
+		return -EFAULT;
+
+	karg.virtual = (void *) A(tmp1);
+	ulist = (drm32_buf_pub_t *) A(tmp2);
+
+	orig_count = karg.count;
+
+	karg.list = kmalloc(karg.count * sizeof(drm_buf_pub_t), GFP_KERNEL);
+	if (!karg.list)
+		return -ENOMEM;
+
+	ret = -EFAULT;
+	for (i = 0; i < karg.count; i++) {
+		if (get_user(karg.list[i].idx, &ulist[i].idx) ||
+		    get_user(karg.list[i].total, &ulist[i].total) ||
+		    get_user(karg.list[i].used, &ulist[i].used) ||
+		    get_user(tmp1, &ulist[i].address))
+			goto out;
+
+		karg.list[i].address = (void *) A(tmp1);
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, DRM_IOCTL_MAP_BUFS, (unsigned long) &karg);
+	set_fs(old_fs);
+
+	if (!ret) {
+		for (i = 0; i < orig_count; i++) {
+			tmp1 = (u32) (long) karg.list[i].address;
+			if (put_user(karg.list[i].idx, &ulist[i].idx) ||
+			    put_user(karg.list[i].total, &ulist[i].total) ||
+			    put_user(karg.list[i].used, &ulist[i].used) ||
+			    put_user(tmp1, &ulist[i].address)) {
+				ret = -EFAULT;
+				goto out;
+			}
+		}
+		if (put_user(karg.count, &uarg->count))
+			ret = -EFAULT;
+	}
+
+out:
+	kfree(karg.list);
+	return ret;
+}
+
+typedef struct drm32_dma {
+				/* Indices here refer to the offset into
+				   buflist in drm_buf_get_t.  */
+	int		context;	  /* Context handle		    */
+	int		send_count;	  /* Number of buffers to send	    */
+	u32		send_indices;	  /* List of handles to buffers (int *) */
+	u32		send_sizes;	  /* Lengths of data to send (int *) */
+	drm_dma_flags_t flags;		  /* Flags			    */
+	int		request_count;	  /* Number of buffers requested    */
+	int		request_size;	  /* Desired size for buffers	    */
+	u32		request_indices;  /* Buffer information (int *)	    */
+	u32		request_sizes;    /* (int *) */
+	int		granted_count;	  /* Number of buffers granted	    */
+} drm32_dma_t;
+#define DRM32_IOCTL_DMA	     DRM_IOWR(0x29, drm32_dma_t)
+
+/* RED PEN	The DRM layer blindly dereferences the send/request
+ * 		indice/size arrays even though they are userland
+ * 		pointers.  -DaveM
+ */
+static int drm32_dma(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_dma_t *uarg = (drm32_dma_t *) arg;
+	int *u_si, *u_ss, *u_ri, *u_rs;
+	drm_dma_t karg;
+	mm_segment_t old_fs;
+	int ret;
+	u32 tmp1, tmp2, tmp3, tmp4;
+
+	karg.send_indices = karg.send_sizes = NULL;
+	karg.request_indices = karg.request_sizes = NULL;
+
+	if (get_user(karg.context, &uarg->context) ||
+	    get_user(karg.send_count, &uarg->send_count) ||
+	    get_user(tmp1, &uarg->send_indices) ||
+	    get_user(tmp2, &uarg->send_sizes) ||
+	    get_user(karg.flags, &uarg->flags) ||
+	    get_user(karg.request_count, &uarg->request_count) ||
+	    get_user(karg.request_size, &uarg->request_size) ||
+	    get_user(tmp3, &uarg->request_indices) ||
+	    get_user(tmp4, &uarg->request_sizes) ||
+	    get_user(karg.granted_count, &uarg->granted_count))
+		return -EFAULT;
+
+	u_si = (int *) A(tmp1);
+	u_ss = (int *) A(tmp2);
+	u_ri = (int *) A(tmp3);
+	u_rs = (int *) A(tmp4);
+
+	if (karg.send_count) {
+		karg.send_indices = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
+		karg.send_sizes = kmalloc(karg.send_count * sizeof(int), GFP_KERNEL);
+
+		ret = -ENOMEM;
+		if (!karg.send_indices || !karg.send_sizes)
+			goto out;
+
+		ret = -EFAULT;
+		if (copy_from_user(karg.send_indices, u_si,
+				   (karg.send_count * sizeof(int))) ||
+		    copy_from_user(karg.send_sizes, u_ss,
+				   (karg.send_count * sizeof(int))))
+			goto out;
+	}
+
+	if (karg.request_count) {
+		karg.request_indices = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
+		karg.request_sizes = kmalloc(karg.request_count * sizeof(int), GFP_KERNEL);
+
+		ret = -ENOMEM;
+		if (!karg.request_indices || !karg.request_sizes)
+			goto out;
+
+		ret = -EFAULT;
+		if (copy_from_user(karg.request_indices, u_ri,
+				   (karg.request_count * sizeof(int))) ||
+		    copy_from_user(karg.request_sizes, u_rs,
+				   (karg.request_count * sizeof(int))))
+			goto out;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, DRM_IOCTL_DMA, (unsigned long) &karg);
+	set_fs(old_fs);
+
+	if (!ret) {
+		if (put_user(karg.context, &uarg->context) ||
+		    put_user(karg.send_count, &uarg->send_count) ||
+		    put_user(karg.flags, &uarg->flags) ||
+		    put_user(karg.request_count, &uarg->request_count) ||
+		    put_user(karg.request_size, &uarg->request_size) ||
+		    put_user(karg.granted_count, &uarg->granted_count))
+			ret = -EFAULT;
+
+		if (karg.send_count) {
+			if (copy_to_user(u_si, karg.send_indices,
+					 (karg.send_count * sizeof(int))) ||
+			    copy_to_user(u_ss, karg.send_sizes,
+					 (karg.send_count * sizeof(int))))
+				ret = -EFAULT;
+		}
+		if (karg.request_count) {
+			if (copy_to_user(u_ri, karg.request_indices,
+					 (karg.request_count * sizeof(int))) ||
+			    copy_to_user(u_rs, karg.request_sizes,
+					 (karg.request_count * sizeof(int))))
+				ret = -EFAULT;
+		}
+	}
+
+out:
+	if (karg.send_indices)
+		kfree(karg.send_indices);
+	if (karg.send_sizes)
+		kfree(karg.send_sizes);
+	if (karg.request_indices)
+		kfree(karg.request_indices);
+	if (karg.request_sizes)
+		kfree(karg.request_sizes);
+
+	return ret;
+}
+
+typedef struct drm32_ctx_res {
+	int		count;
+	u32		contexts; /* (drm_ctx_t *) */
+} drm32_ctx_res_t;
+#define DRM32_IOCTL_RES_CTX    DRM_IOWR(0x26, drm32_ctx_res_t)
+
+static int drm32_res_ctx(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	drm32_ctx_res_t *uarg = (drm32_ctx_res_t *) arg;
+	drm_ctx_t *ulist;
+	drm_ctx_res_t karg;
+	mm_segment_t old_fs;
+	int orig_count, ret;
+	u32 tmp;
+
+	karg.contexts = NULL;
+	if (get_user(karg.count, &uarg->count) ||
+	    get_user(tmp, &uarg->contexts))
+		return -EFAULT;
+
+	ulist = (drm_ctx_t *) A(tmp);
+
+	orig_count = karg.count;
+	if (karg.count && ulist) {
+		karg.contexts = kmalloc((karg.count * sizeof(drm_ctx_t)), GFP_KERNEL);
+		if (!karg.contexts)
+			return -ENOMEM;
+		if (copy_from_user(karg.contexts, ulist,
+				   (karg.count * sizeof(drm_ctx_t)))) {
+			kfree(karg.contexts);
+			return -EFAULT;
+		}
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_ioctl(fd, DRM_IOCTL_RES_CTX, (unsigned long) &karg);
+	set_fs(old_fs);
+
+	if (!ret) {
+		if (orig_count) {
+			if (copy_to_user(ulist, karg.contexts,
+					 (orig_count * sizeof(drm_ctx_t))))
+				ret = -EFAULT;
+		}
+		if (put_user(karg.count, &uarg->count))
+			ret = -EFAULT;
+	}
+
+	if (karg.contexts)
+		kfree(karg.contexts);
+
+	return ret;
+}
+
+#endif
+
+static int ret_einval(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return -EINVAL;
+}
+
+static int broken_blkgetsize(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	/* The mkswap binary hard codes it to Intel value :-((( */
+	return w_long(fd, BLKGETSIZE, arg);
+}
+
+struct blkpg_ioctl_arg32 {
+	int op;
+	int flags;
+	int datalen;
+	u32 data;
+};
+                                
+static int blkpg_ioctl_trans(unsigned int fd, unsigned int cmd, struct blkpg_ioctl_arg32 *arg)
+{
+	struct blkpg_ioctl_arg a;
+	struct blkpg_partition p;
+	int err;
+	mm_segment_t old_fs = get_fs();
+	
+	err = get_user(a.op, &arg->op);
+	err |= __get_user(a.flags, &arg->flags);
+	err |= __get_user(a.datalen, &arg->datalen);
+	err |= __get_user((long)a.data, &arg->data);
+	if (err) return err;
+	switch (a.op) {
+	case BLKPG_ADD_PARTITION:
+	case BLKPG_DEL_PARTITION:
+		if (a.datalen < sizeof(struct blkpg_partition))
+			return -EINVAL;
+                if (copy_from_user(&p, a.data, sizeof(struct blkpg_partition)))
+			return -EFAULT;
+		a.data = &p;
+		set_fs (KERNEL_DS);
+		err = sys_ioctl(fd, cmd, (unsigned long)&a);
+		set_fs (old_fs);
+	default:
+		return -EINVAL;
+	}                                        
+	return err;
+}
+
+static int ioc_settimeout(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	return rw_long(fd, AUTOFS_IOC_SETTIMEOUT, arg);
+}
+
+
+struct serial_struct32 {
+	int	type;
+	int	line;
+	unsigned int	port;
+	int	irq;
+	int	flags;
+	int	xmit_fifo_size;
+	int	custom_divisor;
+	int	baud_base;
+	unsigned short	close_delay;
+	char	io_type;
+	char	reserved_char[1];
+	int	hub6;
+	unsigned short	closing_wait; /* time to wait before closing */
+	unsigned short	closing_wait2; /* no longer used... */
+	unsigned int	iomem_base;	/* char * really */
+	unsigned short	iomem_reg_shift;
+	unsigned int	port_high;
+	int	reserved[1];
+};
+
+static int do_tiocgserial(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct serial_struct ss;
+	int ret;
+	struct serial_struct32 * uptr = (struct serial_struct32 *)arg;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl(fd, cmd, (unsigned long) &ss);
+	set_fs(old_fs);
+
+	if (!ret) {
+		/* structs match up to iomem_base */
+		ret = copy_to_user(uptr, &ss, sizeof(struct serial_struct32));
+		ret |= put_user(ss.iomem_base, &uptr->iomem_base);
+		ret |= put_user(ss.iomem_reg_shift, &uptr->iomem_reg_shift);
+		ret |= put_user(ss.port_high, &uptr->port_high);
+		if (ret)
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+
+struct ioctl_trans {
+	unsigned long handler;
+	unsigned int cmd;
+	unsigned int next;
+};
+#define HANDLE_IOCTL(cmd, handler) asm volatile(".dword %1\n.word %0, 0" : : "i" (cmd), "i" (handler));
+
+#define COMPATIBLE_IOCTL(cmd) HANDLE_IOCTL(cmd, sys_ioctl) 
+
+
+#define IOCTL_TABLE_START void ioctl32_foo(void) { asm volatile(".data\nioctl_translations:");
+#define IOCTL_TABLE_END asm volatile("\nioctl_translations_end:\n\t.previous"); }
+
+IOCTL_TABLE_START
+/* List here exlicitly which ioctl's are known to have
+ * compatable types passed or none at all...
+ */
+/* Big T */
+COMPATIBLE_IOCTL(TCGETA)
+COMPATIBLE_IOCTL(TCSETA)
+COMPATIBLE_IOCTL(TCSETAW)
+COMPATIBLE_IOCTL(TCSETAF)
+COMPATIBLE_IOCTL(TCSBRK)
+COMPATIBLE_IOCTL(TCXONC)
+COMPATIBLE_IOCTL(TCFLSH)
+COMPATIBLE_IOCTL(TCGETS)
+COMPATIBLE_IOCTL(TCSETS)
+COMPATIBLE_IOCTL(TCSETSW)
+COMPATIBLE_IOCTL(TCSETSF)
+COMPATIBLE_IOCTL(TIOCLINUX)
+/* Little t */
+COMPATIBLE_IOCTL(TIOCGETD)
+COMPATIBLE_IOCTL(TIOCSETD)
+COMPATIBLE_IOCTL(TIOCEXCL)
+COMPATIBLE_IOCTL(TIOCNXCL)
+COMPATIBLE_IOCTL(TIOCCONS)
+COMPATIBLE_IOCTL(TIOCGSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSSOFTCAR)
+COMPATIBLE_IOCTL(TIOCSWINSZ)
+COMPATIBLE_IOCTL(TIOCGWINSZ)
+COMPATIBLE_IOCTL(TIOCMGET)
+COMPATIBLE_IOCTL(TIOCMBIC)
+COMPATIBLE_IOCTL(TIOCMBIS)
+COMPATIBLE_IOCTL(TIOCMSET)
+COMPATIBLE_IOCTL(TIOCPKT)
+COMPATIBLE_IOCTL(TIOCNOTTY)
+COMPATIBLE_IOCTL(TIOCSTI)
+COMPATIBLE_IOCTL(TIOCOUTQ)
+COMPATIBLE_IOCTL(TIOCSPGRP)
+COMPATIBLE_IOCTL(TIOCGPGRP)
+COMPATIBLE_IOCTL(TIOCSCTTY)
+COMPATIBLE_IOCTL(TIOCGPTN)
+COMPATIBLE_IOCTL(TIOCSPTLCK)
+COMPATIBLE_IOCTL(TIOCSSERIAL)
+COMPATIBLE_IOCTL(TIOCSERGETLSR)
+/* Big F */
+#if 0
+COMPATIBLE_IOCTL(FBIOGTYPE)
+COMPATIBLE_IOCTL(FBIOSATTR)
+COMPATIBLE_IOCTL(FBIOGATTR)
+COMPATIBLE_IOCTL(FBIOSVIDEO)
+COMPATIBLE_IOCTL(FBIOGVIDEO)
+COMPATIBLE_IOCTL(FBIOGCURSOR32)  /* This is not implemented yet. Later it should be converted... */
+COMPATIBLE_IOCTL(FBIOSCURPOS)
+COMPATIBLE_IOCTL(FBIOGCURPOS)
+COMPATIBLE_IOCTL(FBIOGCURMAX)
+#endif
+COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO)
+COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO)
+
+COMPATIBLE_IOCTL(FBIOPAN_DISPLAY)
+COMPATIBLE_IOCTL(FBIOGET_FCURSORINFO)
+COMPATIBLE_IOCTL(FBIOGET_VCURSORINFO)
+COMPATIBLE_IOCTL(FBIOPUT_VCURSORINFO)
+COMPATIBLE_IOCTL(FBIOGET_CURSORSTATE)
+COMPATIBLE_IOCTL(FBIOPUT_CURSORSTATE)
+COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP)
+COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP)
+/* Little f */
+COMPATIBLE_IOCTL(FIOCLEX)
+COMPATIBLE_IOCTL(FIONCLEX)
+COMPATIBLE_IOCTL(FIOASYNC)
+COMPATIBLE_IOCTL(FIONBIO)
+COMPATIBLE_IOCTL(FIONREAD)  /* This is also TIOCINQ */
+/* 0x00 */
+COMPATIBLE_IOCTL(FIBMAP)
+COMPATIBLE_IOCTL(FIGETBSZ)
+/* 0x03 -- HD/IDE ioctl's used by hdparm and friends.
+ *         Some need translations, these do not.
+ */
+COMPATIBLE_IOCTL(HDIO_GET_IDENTITY)
+COMPATIBLE_IOCTL(HDIO_SET_DMA)
+COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS)
+COMPATIBLE_IOCTL(HDIO_SET_UNMASKINTR)
+COMPATIBLE_IOCTL(HDIO_SET_NOWERR)
+COMPATIBLE_IOCTL(HDIO_SET_32BIT)
+COMPATIBLE_IOCTL(HDIO_SET_MULTCOUNT)
+COMPATIBLE_IOCTL(HDIO_DRIVE_CMD)
+COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE)
+COMPATIBLE_IOCTL(HDIO_SCAN_HWIF)
+COMPATIBLE_IOCTL(HDIO_SET_NICE)
+/* 0x02 -- Floppy ioctls */
+COMPATIBLE_IOCTL(FDMSGON)
+COMPATIBLE_IOCTL(FDMSGOFF)
+COMPATIBLE_IOCTL(FDSETEMSGTRESH)
+COMPATIBLE_IOCTL(FDFLUSH)
+COMPATIBLE_IOCTL(FDWERRORCLR)
+COMPATIBLE_IOCTL(FDSETMAXERRS)
+COMPATIBLE_IOCTL(FDGETMAXERRS)
+COMPATIBLE_IOCTL(FDGETDRVTYP)
+COMPATIBLE_IOCTL(FDEJECT)
+COMPATIBLE_IOCTL(FDCLRPRM)
+COMPATIBLE_IOCTL(FDFMTBEG)
+COMPATIBLE_IOCTL(FDFMTEND)
+COMPATIBLE_IOCTL(FDRESET)
+COMPATIBLE_IOCTL(FDTWADDLE)
+COMPATIBLE_IOCTL(FDFMTTRK)
+COMPATIBLE_IOCTL(FDRAWCMD)
+/* 0x12 */
+COMPATIBLE_IOCTL(BLKROSET)
+COMPATIBLE_IOCTL(BLKROGET)
+COMPATIBLE_IOCTL(BLKRRPART)
+COMPATIBLE_IOCTL(BLKFLSBUF)
+COMPATIBLE_IOCTL(BLKRASET)
+COMPATIBLE_IOCTL(BLKFRASET)
+COMPATIBLE_IOCTL(BLKSECTSET)
+COMPATIBLE_IOCTL(BLKSSZGET)
+
+/* RAID */
+COMPATIBLE_IOCTL(RAID_VERSION)
+COMPATIBLE_IOCTL(GET_ARRAY_INFO)
+COMPATIBLE_IOCTL(GET_DISK_INFO)
+COMPATIBLE_IOCTL(PRINT_RAID_DEBUG)
+COMPATIBLE_IOCTL(CLEAR_ARRAY)
+COMPATIBLE_IOCTL(ADD_NEW_DISK)
+COMPATIBLE_IOCTL(HOT_REMOVE_DISK)
+COMPATIBLE_IOCTL(SET_ARRAY_INFO)
+COMPATIBLE_IOCTL(SET_DISK_INFO)
+COMPATIBLE_IOCTL(WRITE_RAID_INFO)
+COMPATIBLE_IOCTL(UNPROTECT_ARRAY)
+COMPATIBLE_IOCTL(PROTECT_ARRAY)
+COMPATIBLE_IOCTL(HOT_ADD_DISK)
+COMPATIBLE_IOCTL(SET_DISK_FAULTY)
+COMPATIBLE_IOCTL(RUN_ARRAY)
+COMPATIBLE_IOCTL(START_ARRAY)
+COMPATIBLE_IOCTL(STOP_ARRAY)
+COMPATIBLE_IOCTL(STOP_ARRAY_RO)
+COMPATIBLE_IOCTL(RESTART_ARRAY_RW)
+
+/* Big K */
+COMPATIBLE_IOCTL(PIO_FONT)
+COMPATIBLE_IOCTL(GIO_FONT)
+COMPATIBLE_IOCTL(KDSIGACCEPT)
+COMPATIBLE_IOCTL(KDGETKEYCODE)
+COMPATIBLE_IOCTL(KDSETKEYCODE)
+COMPATIBLE_IOCTL(KIOCSOUND)
+COMPATIBLE_IOCTL(KDMKTONE)
+COMPATIBLE_IOCTL(KDGKBTYPE)
+COMPATIBLE_IOCTL(KDSETMODE)
+COMPATIBLE_IOCTL(KDGETMODE)
+COMPATIBLE_IOCTL(KDSKBMODE)
+COMPATIBLE_IOCTL(KDGKBMODE)
+COMPATIBLE_IOCTL(KDSKBMETA)
+COMPATIBLE_IOCTL(KDGKBMETA)
+COMPATIBLE_IOCTL(KDGKBENT)
+COMPATIBLE_IOCTL(KDSKBENT)
+COMPATIBLE_IOCTL(KDGKBSENT)
+COMPATIBLE_IOCTL(KDSKBSENT)
+COMPATIBLE_IOCTL(KDGKBDIACR)
+COMPATIBLE_IOCTL(KDSKBDIACR)
+COMPATIBLE_IOCTL(KDGKBLED)
+COMPATIBLE_IOCTL(KDSKBLED)
+COMPATIBLE_IOCTL(KDGETLED)
+COMPATIBLE_IOCTL(KDSETLED)
+COMPATIBLE_IOCTL(GIO_SCRNMAP)
+COMPATIBLE_IOCTL(PIO_SCRNMAP)
+COMPATIBLE_IOCTL(GIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_UNISCRNMAP)
+COMPATIBLE_IOCTL(PIO_FONTRESET)
+COMPATIBLE_IOCTL(PIO_UNIMAPCLR)
+/* Little k */
+#if 0
+COMPATIBLE_IOCTL(KIOCTYPE)
+COMPATIBLE_IOCTL(KIOCLAYOUT)
+COMPATIBLE_IOCTL(KIOCGTRANS)
+COMPATIBLE_IOCTL(KIOCTRANS)
+COMPATIBLE_IOCTL(KIOCCMD)
+COMPATIBLE_IOCTL(KIOCSDIRECT)
+COMPATIBLE_IOCTL(KIOCSLED)
+COMPATIBLE_IOCTL(KIOCGLED)
+COMPATIBLE_IOCTL(KIOCSRATE)
+COMPATIBLE_IOCTL(KIOCGRATE)
+#endif
+/* Big S */
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_IDLUN)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_DOORUNLOCK)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TEST_UNIT_READY)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_ENABLE)
+COMPATIBLE_IOCTL(SCSI_IOCTL_TAGGED_DISABLE)
+COMPATIBLE_IOCTL(SCSI_IOCTL_GET_BUS_NUMBER)
+COMPATIBLE_IOCTL(SCSI_IOCTL_SEND_COMMAND)
+/* Big V */
+COMPATIBLE_IOCTL(VT_SETMODE)
+COMPATIBLE_IOCTL(VT_GETMODE)
+COMPATIBLE_IOCTL(VT_GETSTATE)
+COMPATIBLE_IOCTL(VT_OPENQRY)
+COMPATIBLE_IOCTL(VT_ACTIVATE)
+COMPATIBLE_IOCTL(VT_WAITACTIVE)
+COMPATIBLE_IOCTL(VT_RELDISP)
+COMPATIBLE_IOCTL(VT_DISALLOCATE)
+COMPATIBLE_IOCTL(VT_RESIZE)
+COMPATIBLE_IOCTL(VT_RESIZEX)
+COMPATIBLE_IOCTL(VT_LOCKSWITCH)
+COMPATIBLE_IOCTL(VT_UNLOCKSWITCH)
+/* Little v, the video4linux ioctls */
+COMPATIBLE_IOCTL(VIDIOCGCAP)
+COMPATIBLE_IOCTL(VIDIOCGCHAN)
+COMPATIBLE_IOCTL(VIDIOCSCHAN)
+COMPATIBLE_IOCTL(VIDIOCGPICT)
+COMPATIBLE_IOCTL(VIDIOCSPICT)
+COMPATIBLE_IOCTL(VIDIOCCAPTURE)
+COMPATIBLE_IOCTL(VIDIOCKEY)
+COMPATIBLE_IOCTL(VIDIOCGAUDIO)
+COMPATIBLE_IOCTL(VIDIOCSAUDIO)
+COMPATIBLE_IOCTL(VIDIOCSYNC)
+COMPATIBLE_IOCTL(VIDIOCMCAPTURE)
+COMPATIBLE_IOCTL(VIDIOCGMBUF)
+COMPATIBLE_IOCTL(VIDIOCGUNIT)
+COMPATIBLE_IOCTL(VIDIOCGCAPTURE)
+COMPATIBLE_IOCTL(VIDIOCSCAPTURE)
+/* BTTV specific... */
+COMPATIBLE_IOCTL(_IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]))
+COMPATIBLE_IOCTL(_IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int))
+COMPATIBLE_IOCTL(_IOW('v' , BASE_VIDIOCPRIVATE+3, char [16])) /* struct bttv_pll_info */
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+4, int))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+5, int))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+6, int))
+COMPATIBLE_IOCTL(_IOR('v' , BASE_VIDIOCPRIVATE+7, int))
+/* Little m */
+COMPATIBLE_IOCTL(MTIOCTOP)
+/* Socket level stuff */
+COMPATIBLE_IOCTL(FIOSETOWN)
+COMPATIBLE_IOCTL(SIOCSPGRP)
+COMPATIBLE_IOCTL(FIOGETOWN)
+COMPATIBLE_IOCTL(SIOCGPGRP)
+COMPATIBLE_IOCTL(SIOCATMARK)
+COMPATIBLE_IOCTL(SIOCSIFLINK)
+COMPATIBLE_IOCTL(SIOCSIFENCAP)
+COMPATIBLE_IOCTL(SIOCGIFENCAP)
+COMPATIBLE_IOCTL(SIOCSIFBR)
+COMPATIBLE_IOCTL(SIOCGIFBR)
+COMPATIBLE_IOCTL(SIOCSARP)
+COMPATIBLE_IOCTL(SIOCGARP)
+COMPATIBLE_IOCTL(SIOCDARP)
+COMPATIBLE_IOCTL(SIOCSRARP)
+COMPATIBLE_IOCTL(SIOCGRARP)
+COMPATIBLE_IOCTL(SIOCDRARP)
+COMPATIBLE_IOCTL(SIOCADDDLCI)
+COMPATIBLE_IOCTL(SIOCDELDLCI)
+/* SG stuff */
+COMPATIBLE_IOCTL(SG_SET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_GET_TIMEOUT)
+COMPATIBLE_IOCTL(SG_EMULATED_HOST)
+COMPATIBLE_IOCTL(SG_SET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_GET_TRANSFORM)
+COMPATIBLE_IOCTL(SG_SET_RESERVED_SIZE)
+COMPATIBLE_IOCTL(SG_GET_RESERVED_SIZE)
+COMPATIBLE_IOCTL(SG_GET_SCSI_ID)
+COMPATIBLE_IOCTL(SG_SET_FORCE_LOW_DMA)
+COMPATIBLE_IOCTL(SG_GET_LOW_DMA)
+COMPATIBLE_IOCTL(SG_SET_FORCE_PACK_ID)
+COMPATIBLE_IOCTL(SG_GET_PACK_ID)
+COMPATIBLE_IOCTL(SG_GET_NUM_WAITING)
+COMPATIBLE_IOCTL(SG_SET_DEBUG)
+COMPATIBLE_IOCTL(SG_GET_SG_TABLESIZE)
+COMPATIBLE_IOCTL(SG_GET_COMMAND_Q)
+COMPATIBLE_IOCTL(SG_SET_COMMAND_Q)
+COMPATIBLE_IOCTL(SG_GET_VERSION_NUM)
+COMPATIBLE_IOCTL(SG_NEXT_CMD_LEN)
+COMPATIBLE_IOCTL(SG_SCSI_RESET)
+COMPATIBLE_IOCTL(SG_IO)
+COMPATIBLE_IOCTL(SG_GET_REQUEST_TABLE)
+COMPATIBLE_IOCTL(SG_SET_KEEP_ORPHAN)
+COMPATIBLE_IOCTL(SG_GET_KEEP_ORPHAN)
+/* PPP stuff */
+COMPATIBLE_IOCTL(PPPIOCGFLAGS)
+COMPATIBLE_IOCTL(PPPIOCSFLAGS)
+COMPATIBLE_IOCTL(PPPIOCGASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGUNIT)
+COMPATIBLE_IOCTL(PPPIOCGRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSRASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCGMRU)
+COMPATIBLE_IOCTL(PPPIOCSMRU)
+COMPATIBLE_IOCTL(PPPIOCSMAXCID)
+COMPATIBLE_IOCTL(PPPIOCGXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCSXASYNCMAP)
+COMPATIBLE_IOCTL(PPPIOCXFERUNIT)
+COMPATIBLE_IOCTL(PPPIOCGNPMODE)
+COMPATIBLE_IOCTL(PPPIOCSNPMODE)
+COMPATIBLE_IOCTL(PPPIOCGDEBUG)
+COMPATIBLE_IOCTL(PPPIOCSDEBUG)
+COMPATIBLE_IOCTL(PPPIOCNEWUNIT)
+COMPATIBLE_IOCTL(PPPIOCATTACH)
+COMPATIBLE_IOCTL(PPPIOCDETACH)
+COMPATIBLE_IOCTL(PPPIOCSMRRU)
+COMPATIBLE_IOCTL(PPPIOCCONNECT)
+COMPATIBLE_IOCTL(PPPIOCDISCONN)
+COMPATIBLE_IOCTL(PPPIOCATTCHAN)
+/* PPPOX */
+COMPATIBLE_IOCTL(PPPOEIOCSFWD);
+COMPATIBLE_IOCTL(PPPOEIOCDFWD);
+/* CDROM stuff */
+COMPATIBLE_IOCTL(CDROMPAUSE)
+COMPATIBLE_IOCTL(CDROMRESUME)
+COMPATIBLE_IOCTL(CDROMPLAYMSF)
+COMPATIBLE_IOCTL(CDROMPLAYTRKIND)
+COMPATIBLE_IOCTL(CDROMREADTOCHDR)
+COMPATIBLE_IOCTL(CDROMREADTOCENTRY)
+COMPATIBLE_IOCTL(CDROMSTOP)
+COMPATIBLE_IOCTL(CDROMSTART)
+COMPATIBLE_IOCTL(CDROMEJECT)
+COMPATIBLE_IOCTL(CDROMVOLCTRL)
+COMPATIBLE_IOCTL(CDROMSUBCHNL)
+COMPATIBLE_IOCTL(CDROMEJECT_SW)
+COMPATIBLE_IOCTL(CDROMMULTISESSION)
+COMPATIBLE_IOCTL(CDROM_GET_MCN)
+COMPATIBLE_IOCTL(CDROMRESET)
+COMPATIBLE_IOCTL(CDROMVOLREAD)
+COMPATIBLE_IOCTL(CDROMSEEK)
+COMPATIBLE_IOCTL(CDROMPLAYBLK)
+COMPATIBLE_IOCTL(CDROMCLOSETRAY)
+COMPATIBLE_IOCTL(CDROM_SET_OPTIONS)
+COMPATIBLE_IOCTL(CDROM_CLEAR_OPTIONS)
+COMPATIBLE_IOCTL(CDROM_SELECT_SPEED)
+COMPATIBLE_IOCTL(CDROM_SELECT_DISC)
+COMPATIBLE_IOCTL(CDROM_MEDIA_CHANGED)
+COMPATIBLE_IOCTL(CDROM_DRIVE_STATUS)
+COMPATIBLE_IOCTL(CDROM_DISC_STATUS)
+COMPATIBLE_IOCTL(CDROM_CHANGER_NSLOTS)
+COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
+COMPATIBLE_IOCTL(CDROM_DEBUG)
+COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* Big L */
+COMPATIBLE_IOCTL(LOOP_SET_FD)
+COMPATIBLE_IOCTL(LOOP_CLR_FD)
+/* Big Q for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESET)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_CTRLRATE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETOUTCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETINCOUNT)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PERCMODE)
+COMPATIBLE_IOCTL(SNDCTL_FM_LOAD_INSTR)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_TESTMIDI)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_RESETSAMPLES)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRSYNTHS)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_NRMIDIS)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_INFO)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_THRESHOLD)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_MEMAVL)
+COMPATIBLE_IOCTL(SNDCTL_FM_4OP_ENABLE)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_PANIC)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_OUTOFBAND)
+COMPATIBLE_IOCTL(SNDCTL_SEQ_GETTIME)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_ID)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_CONTROL)
+COMPATIBLE_IOCTL(SNDCTL_SYNTH_REMOVESAMPLE)
+/* Big T for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_TMR_TIMEBASE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_START)
+COMPATIBLE_IOCTL(SNDCTL_TMR_STOP)
+COMPATIBLE_IOCTL(SNDCTL_TMR_CONTINUE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_TEMPO)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SOURCE)
+COMPATIBLE_IOCTL(SNDCTL_TMR_METRONOME)
+COMPATIBLE_IOCTL(SNDCTL_TMR_SELECT)
+/* Little m for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_MIDI_PRETIME)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUMODE)
+COMPATIBLE_IOCTL(SNDCTL_MIDI_MPUCMD)
+/* Big P for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_DSP_RESET)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SYNC)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SPEED)
+COMPATIBLE_IOCTL(SNDCTL_DSP_STEREO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETBLKSIZE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_WRITE_FILTER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_POST)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SUBDIVIDE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFRAGMENT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETFMTS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETFMT)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOSPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETISPACE)
+COMPATIBLE_IOCTL(SNDCTL_DSP_NONBLOCK)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETCAPS)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETTRIGGER)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETIPTR)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETOPTR)
+/* SNDCTL_DSP_MAPINBUF,  XXX needs translation */
+/* SNDCTL_DSP_MAPOUTBUF,  XXX needs translation */
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETSYNCRO)
+COMPATIBLE_IOCTL(SNDCTL_DSP_SETDUPLEX)
+COMPATIBLE_IOCTL(SNDCTL_DSP_GETODELAY)
+COMPATIBLE_IOCTL(SNDCTL_DSP_PROFILE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_RATE)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_CHANNELS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_BITS)
+COMPATIBLE_IOCTL(SOUND_PCM_READ_FILTER)
+/* Big C for sound/OSS */
+COMPATIBLE_IOCTL(SNDCTL_COPR_RESET)
+COMPATIBLE_IOCTL(SNDCTL_COPR_LOAD)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WDATA)
+COMPATIBLE_IOCTL(SNDCTL_COPR_WCODE)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RUN)
+COMPATIBLE_IOCTL(SNDCTL_COPR_HALT)
+COMPATIBLE_IOCTL(SNDCTL_COPR_SENDMSG)
+COMPATIBLE_IOCTL(SNDCTL_COPR_RCVMSG)
+/* Big M for sound/OSS */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_LINE3)
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_READ(SOUND_MIXER_MONITOR))
+COMPATIBLE_IOCTL(SOUND_MIXER_MUTE)
+/* SOUND_MIXER_READ_ENHANCE,  same value as READ_MUTE */
+/* SOUND_MIXER_READ_LOUD,  same value as READ_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_DEVMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_RECMASK)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_STEREODEVS)
+COMPATIBLE_IOCTL(SOUND_MIXER_READ_CAPS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_VOLUME)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_BASS)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_TREBLE)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SYNTH)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_PCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_SPEAKER)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MIC)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_CD)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IMIX)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_ALTPCM)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECLEV)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_IGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_OGAIN)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_LINE3)
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL1))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL2))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_DIGITAL3))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEIN))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_PHONEOUT))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_VIDEO))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_RADIO))
+COMPATIBLE_IOCTL(MIXER_WRITE(SOUND_MIXER_MONITOR))
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_MUTE)
+/* SOUND_MIXER_WRITE_ENHANCE,  same value as WRITE_MUTE */
+/* SOUND_MIXER_WRITE_LOUD,  same value as WRITE_MUTE */
+COMPATIBLE_IOCTL(SOUND_MIXER_WRITE_RECSRC)
+COMPATIBLE_IOCTL(SOUND_MIXER_INFO)
+COMPATIBLE_IOCTL(SOUND_OLD_MIXER_INFO)
+COMPATIBLE_IOCTL(SOUND_MIXER_ACCESS)
+COMPATIBLE_IOCTL(SOUND_MIXER_AGC)
+COMPATIBLE_IOCTL(SOUND_MIXER_3DSE)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE1)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE2)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE3)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE4)
+COMPATIBLE_IOCTL(SOUND_MIXER_PRIVATE5)
+COMPATIBLE_IOCTL(SOUND_MIXER_GETLEVELS)
+COMPATIBLE_IOCTL(SOUND_MIXER_SETLEVELS)
+COMPATIBLE_IOCTL(OSS_GETVERSION)
+/* AUTOFS */
+COMPATIBLE_IOCTL(AUTOFS_IOC_READY)
+COMPATIBLE_IOCTL(AUTOFS_IOC_FAIL)
+COMPATIBLE_IOCTL(AUTOFS_IOC_CATATONIC)
+COMPATIBLE_IOCTL(AUTOFS_IOC_PROTOVER)
+COMPATIBLE_IOCTL(AUTOFS_IOC_EXPIRE)
+/* DEVFS */
+COMPATIBLE_IOCTL(DEVFSDIOC_GET_PROTO_REV)
+COMPATIBLE_IOCTL(DEVFSDIOC_SET_EVENT_MASK)
+COMPATIBLE_IOCTL(DEVFSDIOC_RELEASE_EVENT_QUEUE)
+COMPATIBLE_IOCTL(DEVFSDIOC_SET_DEBUG_MASK)
+/* Raw devices */
+COMPATIBLE_IOCTL(RAW_SETBIND)
+COMPATIBLE_IOCTL(RAW_GETBIND)
+/* SMB ioctls which do not need any translations */
+COMPATIBLE_IOCTL(SMB_IOC_NEWCONN)
+/* Little a */
+COMPATIBLE_IOCTL(ATMSIGD_CTRL)
+COMPATIBLE_IOCTL(ATMARPD_CTRL)
+COMPATIBLE_IOCTL(ATMLEC_CTRL)
+COMPATIBLE_IOCTL(ATMLEC_MCAST)
+COMPATIBLE_IOCTL(ATMLEC_DATA)
+COMPATIBLE_IOCTL(ATM_SETSC)
+COMPATIBLE_IOCTL(SIOCSIFATMTCP)
+COMPATIBLE_IOCTL(SIOCMKCLIP)
+COMPATIBLE_IOCTL(ATMARP_MKIP)
+COMPATIBLE_IOCTL(ATMARP_SETENTRY)
+COMPATIBLE_IOCTL(ATMARP_ENCAP)
+COMPATIBLE_IOCTL(ATMTCP_CREATE)
+COMPATIBLE_IOCTL(ATMTCP_REMOVE)
+COMPATIBLE_IOCTL(ATMMPC_CTRL)
+COMPATIBLE_IOCTL(ATMMPC_DATA)
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+/* 0xfe - lvm */
+COMPATIBLE_IOCTL(VG_SET_EXTENDABLE)
+COMPATIBLE_IOCTL(VG_STATUS_GET_COUNT)
+COMPATIBLE_IOCTL(VG_STATUS_GET_NAMELIST)
+COMPATIBLE_IOCTL(VG_REMOVE)
+COMPATIBLE_IOCTL(VG_RENAME)
+COMPATIBLE_IOCTL(VG_REDUCE)
+COMPATIBLE_IOCTL(PE_LOCK_UNLOCK)
+COMPATIBLE_IOCTL(PV_FLUSH)
+COMPATIBLE_IOCTL(LVM_LOCK_LVM)
+COMPATIBLE_IOCTL(LVM_GET_IOP_VERSION)
+#ifdef LVM_TOTAL_RESET
+COMPATIBLE_IOCTL(LVM_RESET)
+#endif
+COMPATIBLE_IOCTL(LV_SET_ACCESS)
+COMPATIBLE_IOCTL(LV_SET_STATUS)
+COMPATIBLE_IOCTL(LV_SET_ALLOCATION)
+COMPATIBLE_IOCTL(LE_REMAP)
+COMPATIBLE_IOCTL(LV_BMAP)
+COMPATIBLE_IOCTL(LV_SNAPSHOT_USE_RATE)
+#endif /* LVM */
+#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
+COMPATIBLE_IOCTL(DRM_IOCTL_GET_MAGIC)
+COMPATIBLE_IOCTL(DRM_IOCTL_IRQ_BUSID)
+COMPATIBLE_IOCTL(DRM_IOCTL_AUTH_MAGIC)
+COMPATIBLE_IOCTL(DRM_IOCTL_BLOCK)
+COMPATIBLE_IOCTL(DRM_IOCTL_UNBLOCK)
+COMPATIBLE_IOCTL(DRM_IOCTL_CONTROL)
+COMPATIBLE_IOCTL(DRM_IOCTL_ADD_BUFS)
+COMPATIBLE_IOCTL(DRM_IOCTL_MARK_BUFS)
+COMPATIBLE_IOCTL(DRM_IOCTL_ADD_CTX)
+COMPATIBLE_IOCTL(DRM_IOCTL_RM_CTX)
+COMPATIBLE_IOCTL(DRM_IOCTL_MOD_CTX)
+COMPATIBLE_IOCTL(DRM_IOCTL_GET_CTX)
+COMPATIBLE_IOCTL(DRM_IOCTL_SWITCH_CTX)
+COMPATIBLE_IOCTL(DRM_IOCTL_NEW_CTX)
+COMPATIBLE_IOCTL(DRM_IOCTL_ADD_DRAW)
+COMPATIBLE_IOCTL(DRM_IOCTL_RM_DRAW)
+COMPATIBLE_IOCTL(DRM_IOCTL_LOCK)
+COMPATIBLE_IOCTL(DRM_IOCTL_UNLOCK)
+COMPATIBLE_IOCTL(DRM_IOCTL_FINISH)
+#endif /* DRM */
+/* elevator */
+COMPATIBLE_IOCTL(BLKELVGET)
+COMPATIBLE_IOCTL(BLKELVSET)
+/* And these ioctls need translation */
+HANDLE_IOCTL(TIOCGSERIAL, do_tiocgserial)
+HANDLE_IOCTL(SIOCGIFNAME, dev_ifname32)
+HANDLE_IOCTL(SIOCGIFCONF, dev_ifconf)
+HANDLE_IOCTL(SIOCGIFFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMETRIC, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMETRIC, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMTU, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMTU, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMEM, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMEM, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFHWADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFHWADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCADDMULTI, dev_ifsioc)
+HANDLE_IOCTL(SIOCDELMULTI, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFINDEX, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFMAP, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFMAP, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFBRDADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFBRDADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFDSTADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFDSTADDR, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFNETMASK, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFNETMASK, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFPFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFPFLAGS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPSTATS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPCSTATS, dev_ifsioc)
+HANDLE_IOCTL(SIOCGPPPVER, dev_ifsioc)
+HANDLE_IOCTL(SIOCGIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(SIOCSIFTXQLEN, dev_ifsioc)
+HANDLE_IOCTL(SIOCADDRT, routing_ioctl)
+HANDLE_IOCTL(SIOCDELRT, routing_ioctl)
+/* Note SIOCRTMSG is no longer, so this is safe and * the user would have seen just an -EINVAL anyways. */
+HANDLE_IOCTL(SIOCRTMSG, ret_einval)
+HANDLE_IOCTL(SIOCGSTAMP, do_siocgstamp)
+HANDLE_IOCTL(HDIO_GETGEO, hdio_getgeo)
+HANDLE_IOCTL(BLKRAGET, w_long)
+HANDLE_IOCTL(BLKGETSIZE, w_long)
+HANDLE_IOCTL(0x1260, broken_blkgetsize)
+HANDLE_IOCTL(BLKFRAGET, w_long)
+HANDLE_IOCTL(BLKSECTGET, w_long)
+HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans)
+
+HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans)
+HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans)
+HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans)
+
+HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_32BIT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_MULTCOUNT, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_NOWERR, hdio_ioctl_trans)
+HANDLE_IOCTL(HDIO_GET_NICE, hdio_ioctl_trans)
+HANDLE_IOCTL(FDSETPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDDEFPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDSETDRVPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETDRVPRM32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETDRVSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDPOLLDRVSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDGETFDCSTAT32, fd_ioctl_trans)
+HANDLE_IOCTL(FDWERRORGET32, fd_ioctl_trans)
+HANDLE_IOCTL(PPPIOCGIDLE32, ppp_ioctl_trans)
+HANDLE_IOCTL(PPPIOCSCOMPRESS32, ppp_ioctl_trans)
+HANDLE_IOCTL(MTIOCGET32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCPOS32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCGETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(MTIOCSETCONFIG32, mt_ioctl_trans)
+HANDLE_IOCTL(CDROMREADMODE2, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADMODE1, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADRAW, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADCOOKED, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADAUDIO, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROMREADALL, cdrom_ioctl_trans)
+HANDLE_IOCTL(CDROM_SEND_PACKET, cdrom_ioctl_trans)
+HANDLE_IOCTL(LOOP_SET_STATUS, loop_status)
+HANDLE_IOCTL(LOOP_GET_STATUS, loop_status)
+#define AUTOFS_IOC_SETTIMEOUT32 _IOWR(0x93,0x64,unsigned int)
+HANDLE_IOCTL(AUTOFS_IOC_SETTIMEOUT32, ioc_settimeout)
+#ifdef CONFIG_VT
+HANDLE_IOCTL(PIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(GIO_FONTX, do_fontx_ioctl)
+HANDLE_IOCTL(PIO_UNIMAP, do_unimap_ioctl)
+HANDLE_IOCTL(GIO_UNIMAP, do_unimap_ioctl)
+HANDLE_IOCTL(KDFONTOP, do_kdfontop_ioctl)
+#endif
+HANDLE_IOCTL(EXT2_IOC32_GETFLAGS, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_SETFLAGS, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_GETVERSION, do_ext2_ioctl)
+HANDLE_IOCTL(EXT2_IOC32_SETVERSION, do_ext2_ioctl)
+#if 0
+/* One SMB ioctl needs translations. */
+#define SMB_IOC_GETMOUNTUID_32 _IOR('u', 1, __kernel_uid_t32)
+HANDLE_IOCTL(SMB_IOC_GETMOUNTUID_32, do_smb_getmountuid)
+#endif
+HANDLE_IOCTL(ATM_GETLINKRATE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETNAMES32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETTYPE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETESI32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_RSTADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_ADDADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_DELADDR32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETCIRANGE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETCIRANGE32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETESI32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETESIF32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETSTAT32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETSTATZ32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_GETLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_SETLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(ATM_QUERYLOOP32, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETSTAT, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETSTATZ, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_SETDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_CLRDIAG, do_atm_ioctl)
+HANDLE_IOCTL(SONET_SETFRAMING, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETFRAMING, do_atm_ioctl)
+HANDLE_IOCTL(SONET_GETFRSENSE, do_atm_ioctl)
+#if defined(CONFIG_BLK_DEV_LVM) || defined(CONFIG_BLK_DEV_LVM_MODULE)
+HANDLE_IOCTL(VG_STATUS, do_lvm_ioctl)
+HANDLE_IOCTL(VG_CREATE_OLD, do_lvm_ioctl)
+HANDLE_IOCTL(VG_CREATE, do_lvm_ioctl)
+HANDLE_IOCTL(VG_EXTEND, do_lvm_ioctl)
+HANDLE_IOCTL(LV_CREATE, do_lvm_ioctl)
+HANDLE_IOCTL(LV_REMOVE, do_lvm_ioctl)
+HANDLE_IOCTL(LV_EXTEND, do_lvm_ioctl)
+HANDLE_IOCTL(LV_REDUCE, do_lvm_ioctl)
+HANDLE_IOCTL(LV_RENAME, do_lvm_ioctl)
+HANDLE_IOCTL(LV_STATUS_BYNAME, do_lvm_ioctl)
+HANDLE_IOCTL(LV_STATUS_BYINDEX, do_lvm_ioctl)
+HANDLE_IOCTL(LV_STATUS_BYDEV, do_lvm_ioctl)
+HANDLE_IOCTL(PV_CHANGE, do_lvm_ioctl)
+HANDLE_IOCTL(PV_STATUS, do_lvm_ioctl)
+#endif /* LVM */
+#if defined(CONFIG_GENRTC)
+COMPATIBLE_IOCTL(RTC_AIE_ON)
+COMPATIBLE_IOCTL(RTC_AIE_OFF)
+COMPATIBLE_IOCTL(RTC_UIE_ON)
+COMPATIBLE_IOCTL(RTC_UIE_OFF)
+COMPATIBLE_IOCTL(RTC_PIE_ON)
+COMPATIBLE_IOCTL(RTC_PIE_OFF)
+COMPATIBLE_IOCTL(RTC_WIE_ON)
+COMPATIBLE_IOCTL(RTC_WIE_OFF)
+COMPATIBLE_IOCTL(RTC_ALM_SET)   /* struct rtc_time only has ints */
+COMPATIBLE_IOCTL(RTC_ALM_READ)  /* struct rtc_time only has ints */
+COMPATIBLE_IOCTL(RTC_RD_TIME)   /* struct rtc_time only has ints */
+COMPATIBLE_IOCTL(RTC_SET_TIME)  /* struct rtc_time only has ints */
+HANDLE_IOCTL(RTC_IRQP_READ, w_long)
+COMPATIBLE_IOCTL(RTC_IRQP_SET)
+HANDLE_IOCTL(RTC_EPOCH_READ, w_long)
+COMPATIBLE_IOCTL(RTC_EPOCH_SET)
+#endif
+#if defined(CONFIG_DRM) || defined(CONFIG_DRM_MODULE)
+HANDLE_IOCTL(DRM32_IOCTL_VERSION, drm32_version);
+HANDLE_IOCTL(DRM32_IOCTL_GET_UNIQUE, drm32_getsetunique);
+HANDLE_IOCTL(DRM32_IOCTL_SET_UNIQUE, drm32_getsetunique);
+HANDLE_IOCTL(DRM32_IOCTL_ADD_MAP, drm32_addmap);
+HANDLE_IOCTL(DRM32_IOCTL_INFO_BUFS, drm32_info_bufs);
+HANDLE_IOCTL(DRM32_IOCTL_FREE_BUFS, drm32_free_bufs);
+HANDLE_IOCTL(DRM32_IOCTL_MAP_BUFS, drm32_map_bufs);
+HANDLE_IOCTL(DRM32_IOCTL_DMA, drm32_dma);
+HANDLE_IOCTL(DRM32_IOCTL_RES_CTX, drm32_res_ctx);
+#endif /* DRM */
+COMPATIBLE_IOCTL(PA_PERF_ON)
+COMPATIBLE_IOCTL(PA_PERF_OFF)
+COMPATIBLE_IOCTL(PA_PERF_VERSION)
+IOCTL_TABLE_END
+
+unsigned int ioctl32_hash_table[1024];
+
+extern inline unsigned long ioctl32_hash(unsigned long cmd)
+{
+	return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
+}
+
+static void ioctl32_insert_translation(struct ioctl_trans *trans)
+{
+	unsigned long hash;
+	struct ioctl_trans *t;
+
+	hash = ioctl32_hash (trans->cmd);
+	if (!ioctl32_hash_table[hash])
+		ioctl32_hash_table[hash] = (u32)(long)trans;
+	else {
+		t = (struct ioctl_trans *)(long)ioctl32_hash_table[hash];
+		while (t->next)
+			t = (struct ioctl_trans *)(long)t->next;
+		trans->next = 0;
+		t->next = (u32)(long)trans;
+	}
+}
+
+static int __init init_sys32_ioctl(void)
+{
+	int i;
+	extern struct ioctl_trans ioctl_translations[], ioctl_translations_end[];
+
+	for (i = 0; &ioctl_translations[i] < &ioctl_translations_end[0]; i++)
+		ioctl32_insert_translation(&ioctl_translations[i]);
+	return 0;
+}
+
+__initcall(init_sys32_ioctl);
+
+static struct ioctl_trans *additional_ioctls;
+
+/* Always call these with kernel lock held! */
+
+int register_ioctl32_conversion(unsigned int cmd, int (*handler)(unsigned int, unsigned int, unsigned long, struct file *))
+{
+	int i;
+
+panic("register_ioctl32_conversion() is B0RKEN! Called by %p\n", __builtin_return_address(0));
+
+	if (!additional_ioctls) {
+		additional_ioctls = module_map(PAGE_SIZE);
+		if (!additional_ioctls)
+			return -ENOMEM;
+		memset(additional_ioctls, 0, PAGE_SIZE);
+	}
+	for (i = 0; i < PAGE_SIZE/sizeof(struct ioctl_trans); i++)
+		if (!additional_ioctls[i].cmd)
+			break;
+	if (i == PAGE_SIZE/sizeof(struct ioctl_trans))
+		return -ENOMEM;
+	additional_ioctls[i].cmd = cmd;
+	if (!handler)
+		additional_ioctls[i].handler = (u32)(long)sys_ioctl;
+	else
+		additional_ioctls[i].handler = (u32)(long)handler;
+	ioctl32_insert_translation(&additional_ioctls[i]);
+	return 0;
+}
+
+int unregister_ioctl32_conversion(unsigned int cmd)
+{
+	unsigned long hash = ioctl32_hash(cmd);
+	struct ioctl_trans *t, *t1;
+
+	t = (struct ioctl_trans *)(long)ioctl32_hash_table[hash];
+	if (!t) return -EINVAL;
+	if (t->cmd == cmd && t >= additional_ioctls &&
+	    (unsigned long)t < ((unsigned long)additional_ioctls) + PAGE_SIZE) {
+		ioctl32_hash_table[hash] = t->next;
+		t->cmd = 0;
+		return 0;
+	} else while (t->next) {
+		t1 = (struct ioctl_trans *)(long)t->next;
+		if (t1->cmd == cmd && t1 >= additional_ioctls &&
+		    (unsigned long)t1 < ((unsigned long)additional_ioctls) + PAGE_SIZE) {
+			t1->cmd = 0;
+			t->next = t1->next;
+			return 0;
+		}
+		t = t1;
+	}
+	return -EINVAL;
+}
+
+asmlinkage int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct file * filp;
+	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+	unsigned long pafnptr[4];
+	extern char __gp;
+	struct ioctl_trans *t;
+	int error = -EBADF;
+
+	filp = fget(fd);
+	if(!filp)
+		goto out2;
+
+	if (!filp->f_op || !filp->f_op->ioctl) {
+		error = sys_ioctl (fd, cmd, arg);
+		goto out;
+	}
+
+	/* intercept private networking ioctl() calls here since it is
+	 * an onerous task to figure out which ones of the HANDLE_IOCTL
+	 * list map to these values.
+	 */
+	if (cmd >= SIOCDEVPRIVATE && cmd <= SIOCDEVPRIVATE + 0xf) {
+		error = siocprivate(fd, cmd, arg);
+		goto out;
+	}
+
+	t = (struct ioctl_trans *)(long)ioctl32_hash_table [ioctl32_hash (cmd)];
+
+	while (t && t->cmd != cmd)
+		t = (struct ioctl_trans *)(long)t->next;
+	if (t) {
+		handler = (void *) pafnptr;
+		pafnptr[0] = pafnptr[1] = 0UL;
+		pafnptr[2] = (unsigned long) t->handler;
+		pafnptr[3] = A(&__gp);
+		error = handler(fd, cmd, arg, filp);
+	} else {
+		static int count = 0;
+		if (++count <= 20)
+			printk(KERN_WARNING
+				"sys32_ioctl: Unknown cmd fd(%d) "
+				"cmd(%08x) arg(%08x)\n",
+				(int)fd, (unsigned int)cmd, (unsigned int)arg);
+		error = -EINVAL;
+	}
+out:
+	fput(filp);
+out2:
+	return error;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/iosapic.c linux/arch/parisc/kernel/iosapic.c
--- linux.orig/arch/parisc/kernel/iosapic.c	2001-02-09 19:29:44.000000000 +0000
+++ linux/arch/parisc/kernel/iosapic.c	2002-08-12 22:14:07.000000000 +0000
@@ -169,11 +169,13 @@
 
 #include <asm/byteorder.h>	/* get in-line asm for swab */
 #include <asm/pdc.h>
-#include <asm/pdcpat.h>
 #include <asm/page.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 #include <asm/gsc.h>		/* gsc_read/write functions */
+#ifdef CONFIG_SUPERIO
+#include <asm/superio.h>
+#endif
 
 #include <asm/iosapic.h>
 #include "./iosapic_private.h"
@@ -181,7 +183,6 @@
 #define MODULE_NAME "iosapic"
 
 /* "local" compile flags */
-#undef IOSAPIC_CALLBACK
 #undef PCI_BRIDGE_FUNCS
 #undef DEBUG_IOSAPIC
 #undef DEBUG_IOSAPIC_IRT
@@ -282,28 +283,6 @@
 
 #define	IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
 
-#if IOSAPIC_CALLBACK
-/*
-** Shouldn't use callback since SAPIC doesn't have an officially assigned
-** H or S version numbers. Slight long term risk the number chosen would
-** collide with something else.
-** But benefit is cleaner lba/sapic interface.
-** Might be worth it but for just use direct calls for now.
-**
-** Entry below is copied from lba driver.
-** Only thing different is hw_type.
-*/
-static struct pa_iodc_driver iosapic_driver_for[] = {
-	{HPHW_OTHER, 0x782, 0, 0x0000A, 0, 0x00,
-	DRIVER_CHECK_HWTYPE + DRIVER_CHECK_HVERSION + DRIVER_CHECK_SVERSION,
-	"I/O Sapic", "",(void *) iosapic_callback},     
-	{0,0,0,0,0,0,
-	0,
-	(char *) NULL,(char *) NULL,(void *) NULL}                     
-};
-#endif /* IOSAPIO_CALLBACK */
-
-
 static struct iosapic_info *iosapic_list;
 static spinlock_t iosapic_lock;
 static int iosapic_count;
@@ -350,25 +329,22 @@
 static int __init /* return number of entries as success/fail flag */
 iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
 {
-	struct pdc_pat_io_num pdc_io_num; /* PAT PDC return block */
 	long status;              /* PDC return value status */
-	struct irt_entry *table = NULL;  /* start of interrupt routing tbl */
+	struct irt_entry *table;  /* start of interrupt routing tbl */
 	unsigned long num_entries = 0UL;
 
 	ASSERT(NULL != irt);
-	/* FIXME ASSERT(((&pdc_io_num) & (0x3f)) == 0);  enforce 32-byte alignment */
 
-	/* Try PAT_PDC to get interrupt routing table size */
-	DBG(KERN_DEBUG "calling get_irt_size\n");
-	status = pdc_pat_get_irt_size( &pdc_io_num, cell_num);
-	DBG(KERN_DEBUG "get_irt_size: %ld\n", status);
+	if (is_pdc_pat()) {
 
-	switch(status) {
+		/* Use pat pdc routine to get interrupt routing table size */
+		DBG("calling get_irt_size (cell %ld)\n", cell_num);
+		status = pdc_pat_get_irt_size(&num_entries, cell_num);
+		DBG("get_irt_size: %ld\n", status);
 
-	case PDC_RET_OK:	/* PAT box. Proceed to get the IRT */
+		ASSERT(status == PDC_OK);
 
 		/* save the number of entries in the table */
-		num_entries = pdc_io_num.num;
 		ASSERT(0UL != num_entries);
 
 		/*
@@ -384,30 +360,27 @@
 		}
 
 		/* get PCI INT routing table */
-		status = pdc_pat_get_irt( (void *) table, cell_num);
-		DBG(KERN_DEBUG "pdc_pat_get_irt: %ld\n", status);
-		ASSERT(status == PDC_RET_OK);
-		break;
-
-	case PDC_RET_NE_PROC: /* Not a PAT platform. Try PDC_PCI extensions */
+		status = pdc_pat_get_irt(table, cell_num);
+		DBG("pdc_pat_get_irt: %ld\n", status);
+		ASSERT(status == PDC_OK);
+	} else {
 		/*
-		** C3000/J5000 (and similar) platforms with "legacy" PDC
-		** will return exactly one IRT.
+		** C3000/J5000 (and similar) platforms with Sprockets PDC
+		** will return exactly one IRT for all iosapics.
 		** So if we have one, don't need to get it again.
 		*/
 		if (NULL != irt_cell)
-			break;
+			return 0;
 
-		status = pdc_pci_irt_size( (void *)&pdc_io_num,
-				/* elroy HPA (really a NOP) */ 0);
-		DBG(KERN_WARNING "pdc_pci_irt_size: %ld\n", status);
+		/* Should be using the Elroy's HPA, but it's ignored anyway */
+		status = pdc_pci_irt_size(&num_entries, 0);
+		DBG("pdc_pci_irt_size: %ld\n", status);
 
-		if (PDC_RET_OK != status) {
+		if (PDC_OK != status) {
 			/* Not a "legacy" system with I/O SAPIC either */
 			return 0;
 		}
 
-		num_entries = pdc_io_num.num;
 		ASSERT(0UL != num_entries);
 
 		table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
@@ -416,36 +389,27 @@
 			return 0;
 		}
 
-		status = pdc_pci_irt( (void *) &pdc_io_num,
-				(void *) NULL, /* Elroy HPA - not used */
-				(void *) table);
-
-		ASSERT(PDC_RET_OK == status);
-		break;
-
-	default:
-		printk(KERN_WARNING MODULE_NAME ": PDC_PAT_IO call failed with %ld\n", status);
-		break;
+		/* HPA ignored by this call too. */
+		status = pdc_pci_irt(num_entries, 0, table);
+		ASSERT(PDC_OK == status);
 	}
 
 	/* return interrupt table address */
 	*irt = table;
 
-
 #ifdef DEBUG_IOSAPIC_IRT
-	{
+{
 	struct irt_entry *p = table;
 	int i;
 
-	printk(MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
-	printk(MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
+	printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
+	printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
 		table,
 		num_entries,
 		(int) sizeof(struct irt_entry));
 
-	for (i = 0 ; i < num_entries ; i++, p++)
-	{
-		printk(MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
+	for (i = 0 ; i < num_entries ; i++, p++) {
+		printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
 		p->entry_type, p->entry_length, p->interrupt_type,
 		p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
 		p->src_seg_id, p->dest_iosapic_intin,
@@ -453,7 +417,7 @@
 		((u32 *) p)[3]
 		);
 	}
-	}
+}
 #endif /* DEBUG_IOSAPIC_IRT */
 
 	return num_entries;
@@ -464,6 +428,8 @@
 void __init
 iosapic_init(void)
 {
+	unsigned long cell = 0;
+
 	/* init global data */
 	iosapic_lock = SPIN_LOCK_UNLOCKED;
         iosapic_list = (struct iosapic_info *) NULL;
@@ -471,22 +437,24 @@
 
 	DBG("iosapic_init()\n");
 
+#ifdef __LP64__
+	if (is_pdc_pat()) {
+		int status;
+		struct pdc_pat_cell_num cell_info;
+
+		status = pdc_pat_cell_get_number(&cell_info);
+		if (status == PDC_OK) {
+			cell = cell_info.cell_num;
+		}
+	}
+#endif
+
 	/*
 	**  get IRT for this cell.
 	*/
-	irt_num_entry =  iosapic_load_irt(0L, &irt_cell);
+	irt_num_entry =  iosapic_load_irt(cell, &irt_cell);
 	if (0 == irt_num_entry)
 		irt_cell = NULL;	/* old PDC w/o iosapic */
-
-#ifdef IOSAPIC_CALLBACK
-	/*
-	** When new I/O SAPICs are discovered, this callback
-	** will get invoked. Implies lba driver will register
-	** I/O Sapic as a device it "discovered" with faked
-	** IODC data.
-	*/
-	register_driver(iosapic_driver_for);
-#endif /* IOSAPIC_CALLBACK */
 }
 
 
@@ -546,7 +514,7 @@
 		return i;
 	}
 
-	printk(KERN_WARNING MODULE_NAME ": 0x%p : no IRT entry for slot %d, pin %d\n",
+	printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
 			isi->isi_hpa, slot, intr_pin);
 	return NULL;
 }
@@ -571,21 +539,18 @@
 {
 	u8 intr_pin, intr_slot;
 
-	(void) pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
+	pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
 
-	DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n", PCI_SLOT(pcidev->devfn), intr_pin);
+	DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n",
+		PCI_SLOT(pcidev->devfn), intr_pin);
 
-	if (0 == intr_pin)
-	{
-		/*
-		** The device does NOT support/use IRQ lines.
-		*/
+	if (0 == intr_pin) {
+		/* The device does NOT support/use IRQ lines.  */
 		return NULL;
 	}
 
 	/* Check if pcidev behind a PPB */
-	if (NULL != pcidev->bus->self)
-	{
+	if (NULL != pcidev->bus->self) {
 		/* Convert pcidev INTR_PIN into something we
 		** can lookup in the IRT.
 		*/
@@ -600,7 +565,7 @@
 		** or by some ambitous soul who wants to watch TV.
 		*/
 		if (pci_bridge_funcs->xlate_intr_line) {
-			intr_pin = (*pci_bridge_funcs->xlate_intr_line)(pcidev);
+			intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
 		}
 #else	/* PCI_BRIDGE_FUNCS */
 		struct pci_bus *p = pcidev->bus;
@@ -646,8 +611,8 @@
 	extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
 	int irq_num = vi->vi_ios->isi_region->data.irqbase + vi->vi_irqline;
 
-	DBG("iosapic_interrupt(): irq %d line %d eoi %p\n", irq, vi->vi_irqline,
-				vi->vi_eoi_addr);
+	DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
+		irq, vi->vi_irqline, vi->vi_eoi_addr);
 
 /* FIXME: Need to mask/unmask? processor IRQ is already masked... */
 	do_irq(&vi->vi_ios->isi_region->action[vi->vi_irqline], irq_num, regs);
@@ -668,12 +633,39 @@
 	struct vector_info *vi;
 	int isi_line;	/* line used by device */
 	int tmp;
+	int return_irq;
+#ifdef CONFIG_SUPERIO
+	int superio_irq = -1;
+#endif
 
 	if (NULL == isi) {
-		printk(KERN_WARNING MODULE_NAME ": 0x%p hpa not registered\n", isi->isi_hpa);
+		printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
+			pcidev->name);
 		return(-1);
 	}
 
+#ifdef CONFIG_SUPERIO
+	if (is_superio_device(pcidev)) {
+		superio_irq = superio_fixup_irq(pcidev);
+		if (superio_irq == -1)
+		    return(-1);
+
+		if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN) {
+
+			/*
+			 * SuperIO USB controller has an irt entry.
+			 * Only let the USB controller hookup the rest
+			 * of the interrupt routing when it comes through.
+			 * Note that interrupts for all three functions
+			 * actually come through the PIC's on function 1!
+			 */
+
+			pcidev->irq = superio_irq;
+			return superio_irq;
+		}
+	}
+#endif /* CONFIG_SUPERIO */
+
 	/* lookup IRT entry for isi/slot/pin set */
 	irte = iosapic_xlate_pin(isi, pcidev);
 	if (NULL == irte) {
@@ -714,22 +706,31 @@
 	vi->vi_txn_data = txn_alloc_data(vi->vi_txn_irq, 8);
         ASSERT(vi->vi_txn_data < 256);  /* matches 8 above */
 
-	tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0, "iosapic", vi);
+	tmp = request_irq(vi->vi_txn_irq, iosapic_interrupt, 0,
+						vi->vi_name, vi);
 	ASSERT(tmp == 0);
 
-	vi->vi_eoi_addr = ((void *) isi->isi_hpa) + IOSAPIC_REG_EOI;
+	vi->vi_eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
 	vi->vi_eoi_data = cpu_to_le32(vi->vi_irqline);
 
 	ASSERT(NULL != isi->isi_region);
-	/*
-	** pcidev->irq still needs to be virtualized.
-	*/
-	pcidev->irq = isi->isi_region->data.irqbase + isi_line;
+	/* pcidev->irq still needs to be virtualized.  */
+
+	return_irq = isi->isi_region->data.irqbase + isi_line;
 
-	DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n", PCI_SLOT(pcidev->devfn),
-	PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
+#ifdef CONFIG_SUPERIO
+	if (superio_irq != -1) {
+		superio_inform_irq(return_irq);
+		return_irq = superio_irq;
+	}
+#endif
+	pcidev->irq = return_irq;
+
+	DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
+		PCI_SLOT(pcidev->devfn),
+	PCI_FUNC(pcidev->devfn), pcidev->vendor, pcidev->device, isi_line, return_irq);
 
-	return(pcidev->irq);
+	return return_irq;
 }
 
 
@@ -755,7 +756,7 @@
 	struct iosapic_info *isp = vi->vi_ios;
 
 	ASSERT(NULL != isp);
-	ASSERT(NULL != isp->isi_hpa);
+	ASSERT(0 != isp->isi_hpa);
 	DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p  0x%x 0x%x\n",
 		vi->vi_irqline,
 		isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
@@ -807,16 +808,13 @@
 	** Extracting id_eid isn't a real clean way of getting it.
 	** But the encoding is the same for both PA and IA64 platforms.
 	*/
-#ifdef __LP64__
-	if (pdc_pat) {
+	if (is_pdc_pat()) {
 		/*
 		** PAT PDC just hands it to us "right".
 		** vi_txn_addr comes from cpu_data[x].txn_addr.
 		*/
 		*dp1 = (u32) (vi->vi_txn_addr);
-	} else
-#endif
-	{
+	} else {
 		/* 
 		** eg if base_addr == 0xfffa0000),
 		**    we want to get 0xa0ff0000.
@@ -886,7 +884,6 @@
 
 	/* data is initialized by fixup_irq */
 	ASSERT(0 < vi->vi_txn_irq);
-	ASSERT(0UL != vi->vi_txn_addr);
 	ASSERT(0UL != vi->vi_txn_data);
 
 	iosapic_set_irt_data(vi, &d0, &d1);
@@ -895,10 +892,10 @@
 
 #ifdef DEBUG_IOSAPIC_IRT
 {
-u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL);
-printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr);
-while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++));
-printk("\n");
+	u32 *t = (u32 *) ((ulong) vi->vi_eoi_addr & ~0xffUL);
+	printk("iosapic_enable_irq(): regs %p", vi->vi_eoi_addr);
+	while (t < vi->vi_eoi_addr) printk(" %x", READ_U32(t++));
+	printk("\n");
 }
 
 printk("iosapic_enable_irq(): sel ");
@@ -943,10 +940,10 @@
 
 
 static struct irq_region_ops iosapic_irq_ops = {
-	iosapic_disable_irq,
-	iosapic_enable_irq,
-	iosapic_mask_irq,
-	iosapic_unmask_irq
+	disable_irq:	iosapic_disable_irq,
+	enable_irq:	iosapic_enable_irq,
+	mask_irq:	iosapic_mask_irq,
+	unmask_irq:	iosapic_unmask_irq
 };
 
 
@@ -967,15 +964,9 @@
 }
 
 
-#ifndef IOSAPIC_CALLBACK
-/*
-** iosapic_register() is the alternative to iosapic_driver_for().
-** (Only one or the other should be implemented.)
-*/
-
 /*
 ** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
-** Caller must be certain they have an I/O SAPIC and know it's MMIO address.
+** Caller must be certain they have an I/O SAPIC and know its MMIO address.
 **
 **	o allocate iosapic_info and add it to the list
 **	o read iosapic version and squirrel that away
@@ -984,7 +975,7 @@
 **	o allocate isi_region (registers region handlers)
 */
 void *
-iosapic_register(void *hpa)
+iosapic_register(unsigned long hpa)
 {
 	struct iosapic_info *isi = NULL;
 	struct irt_entry *irte = irt_cell;
@@ -1021,7 +1012,7 @@
 
 	memset(isi, 0, sizeof(struct iosapic_info));
 
-	isi->isi_hpa         = (unsigned char *) hpa;
+	isi->isi_hpa         = hpa;
 	isi->isi_version     = iosapic_rd_version(isi);
 	isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
 
@@ -1034,6 +1025,7 @@
 	}
 
 	memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
+	sprintf(isi->isi_name, "IO-SAPIC%02d", iosapic_count++);
 
 	/*
 	** Initialize vector array
@@ -1041,17 +1033,16 @@
 	for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
 		vip->vi_irqline = (unsigned char) cnt;
 		vip->vi_ios = isi;
+		sprintf(vip->vi_name, "%s-L%d", isi->isi_name, cnt);
 	}
 
 	isi->isi_region = alloc_irq_region(isi->isi_num_vectors,
-				&iosapic_irq_ops, IRQ_REG_DIS|IRQ_REG_MASK,
-				"I/O Sapic", (void *) isi->isi_vector);
+				&iosapic_irq_ops, isi->isi_name,
+				(void *) isi->isi_vector);
 
 	ASSERT(NULL != isi->isi_region);
 	return ((void *) isi);
 }
-#endif /* !IOSAPIC_CALLBACK */
-
 
 
 #ifdef DEBUG_IOSAPIC
@@ -1092,8 +1083,8 @@
 {
 	ASSERT(NULL != isi);
 	printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
-	printk(KERN_DEBUG "\t\tisi_hpa: %p\n", isi->isi_hpa);
-	printk(KERN_DEBUG "\t\tisi_satus:     %x\n", isi->isi_status);
+	printk(KERN_DEBUG "\t\tisi_hpa:       %lx\n", isi->isi_hpa);
+	printk(KERN_DEBUG "\t\tisi_status:     %x\n", isi->isi_status);
 	printk(KERN_DEBUG "\t\tisi_version:   %x\n", isi->isi_version);
 	printk(KERN_DEBUG "\t\tisi_vector:    %p\n", isi->isi_vector);
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/iosapic_private.h linux/arch/parisc/kernel/iosapic_private.h
--- linux.orig/arch/parisc/kernel/iosapic_private.h	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/iosapic_private.h	2002-08-12 22:14:13.000000000 +0000
@@ -111,22 +111,25 @@
 	struct irt_entry *vi_irte;      /* IRT entry */
 	u32	*vi_eoi_addr;	/* precalculate EOI reg address */
 	u32	vi_eoi_data;	/* IA64: ?       PA: swapped txn_data */
-	u8	vi_status;	/* status/flags */
-	u8	vi_irqline;	/* INTINn(IRQ) */
 	int	vi_txn_irq;	/* virtual IRQ number for processor */
 	ulong	vi_txn_addr;    /* IA64: id_eid  PA: partial HPA */
 	ulong	vi_txn_data;    /* IA64: vector  PA: EIR bit */
+	u8	vi_status;	/* status/flags */
+	u8	vi_irqline;	/* INTINn(IRQ) */
+	char	vi_name[32];    /* user visible identity */
 };
 
 
 struct iosapic_info {
 	struct iosapic_info  *isi_next;      /* list of I/O SAPIC          */
-	volatile void        *isi_hpa;       /* physical base address      */
+	unsigned long	     isi_hpa;	     /* physical base address */
 	struct irq_region    *isi_region;    /* each I/O SAPIC is one region */
 	struct vector_info   *isi_vector;    /* IRdT (IRQ line) array  */
 	int                  isi_num_vectors; /* size of IRdT array */
 	int                  isi_status;     /* status/flags               */
 	unsigned int         isi_version;    /* DEBUG: data fr version reg */
+	/* round up to next cacheline */
+	char                 isi_name[20]; /* identify region for users */
 };
 
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/irq.c linux/arch/parisc/kernel/irq.c
--- linux.orig/arch/parisc/kernel/irq.c	2001-02-09 19:29:44.000000000 +0000
+++ linux/arch/parisc/kernel/irq.c	2002-08-12 22:14:16.000000000 +0000
@@ -1,13 +1,10 @@
-/* $Id: irq.c,v 1.8 2000/02/08 02:01:17 grundler Exp $
- *
+/* 
  * Code to handle x86 style IRQs plus some generic interrupt stuff.
  *
- * This is not in any way SMP-clean.
- *
  * Copyright (C) 1992 Linus Torvalds
  * Copyright (C) 1994, 1995, 1996, 1997, 1998 Ralf Baechle
- * Copyright (C) 1999 SuSE GmbH (Author: Philipp Rumpf, prumpf@tux.org)
- * Copyright (C) 2000 Hewlett Packard Corp (Co-Author: Grant Grundler, grundler@cup.hp.com)
+ * Copyright (C) 1999 SuSE GmbH (Philipp Rumpf, prumpf@tux.org)
+ * Copyright (C) 1999-2000 Grant Grundler
  *
  *    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
@@ -23,138 +20,167 @@
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-#include <linux/config.h>
 #include <linux/bitops.h>
 #include <asm/bitops.h>
+#include <linux/config.h>
 #include <asm/pdc.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/kernel_stat.h>
 #include <linux/signal.h>
-#include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
 #include <linux/slab.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
 #include <linux/irq.h>
+#include <linux/spinlock.h>
 
 #include <asm/cache.h>
 
 #undef DEBUG_IRQ
+#undef PARISC_IRQ_CR16_COUNTS
 
 extern void timer_interrupt(int, void *, struct pt_regs *);
 extern void ipi_interrupt(int, void *, struct pt_regs *);
 
 #ifdef DEBUG_IRQ
-#define DBG_IRQ(x...)   printk(x)
+#define DBG_IRQ(irq, x)	if ((irq) != TIMER_IRQ) printk x
 #else /* DEBUG_IRQ */
-#define DBG_IRQ(x...)
+#define DBG_IRQ(irq, x)	do { } while (0)
 #endif /* DEBUG_IRQ */
 
-#define EIEM_MASK(irq) (1L<<(MAX_CPU_IRQ-IRQ_OFFSET(irq)))
-#define CLEAR_EIEM_BIT(irq) set_eiem(get_eiem() & ~EIEM_MASK(irq))
-#define SET_EIEM_BIT(irq) set_eiem(get_eiem() | EIEM_MASK(irq))
+#define EIEM_MASK(irq)       (1UL<<(MAX_CPU_IRQ-IRQ_OFFSET(irq)))
+
+/* Bits in EIEM correlate with cpu_irq_action[].
+** Numbered *Big Endian*! (ie bit 0 is MSB)
+*/
+static unsigned long cpu_eiem = 0;
+
+static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;  /* protect IRQ regions */
+
+#ifdef CONFIG_SMP
+static void cpu_set_eiem(void *info)
+{
+	set_eiem((unsigned long) info);
+}
+#endif
 
-static void disable_cpu_irq(void *unused, int irq)
+static inline void disable_cpu_irq(void *unused, int irq)
 {
-	CLEAR_EIEM_BIT(irq);
+	unsigned long eirr_bit = EIEM_MASK(irq);
+
+	cpu_eiem &= ~eirr_bit;
+	set_eiem(cpu_eiem);
+        smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
 }
 
 static void enable_cpu_irq(void *unused, int irq)
 {
-	unsigned long mask = EIEM_MASK(irq);
+	unsigned long eirr_bit = EIEM_MASK(irq);
+
+	mtctl(eirr_bit, 23);	/* clear EIRR bit before unmasking */
+	cpu_eiem |= eirr_bit;
+        smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
+	set_eiem(cpu_eiem);
+}
+
+/* mask and disable are the same at the CPU level
+** Difference is enable clears pending interrupts
+*/
+#define mask_cpu_irq	disable_cpu_irq
 
-	mtctl(mask, 23);
-	SET_EIEM_BIT(irq);
+static inline void unmask_cpu_irq(void *unused, int irq)
+{
+	unsigned long eirr_bit = EIEM_MASK(irq);
+	cpu_eiem |= eirr_bit;
+	/* NOTE: sending an IPI will cause do_cpu_irq_mask() to
+	** handle *any* unmasked pending interrupts.
+	** ie We don't need to check for pending interrupts here.
+	*/
+        smp_call_function(cpu_set_eiem, (void *) cpu_eiem, 1, 1);
+	set_eiem(cpu_eiem);
 }
 
 static struct irqaction cpu_irq_actions[IRQ_PER_REGION] = {
-	[IRQ_OFFSET(TIMER_IRQ)] { timer_interrupt, 0, 0, "timer", NULL, NULL },
-	[IRQ_OFFSET(IPI_IRQ)]	{ ipi_interrupt, 0, 0, "IPI", NULL, NULL },
+	[IRQ_OFFSET(TIMER_IRQ)] { handler: timer_interrupt, name: "timer", },
+#ifdef CONFIG_SMP
+	[IRQ_OFFSET(IPI_IRQ)]	{ handler: ipi_interrupt,   name: "IPI", },
+#endif
 };
 
 struct irq_region cpu_irq_region = {
-	{ disable_cpu_irq, enable_cpu_irq, NULL, NULL },
-	{ &cpu_data[0], "PA-PIC", IRQ_REG_MASK|IRQ_REG_DIS, IRQ_FROM_REGION(CPU_IRQ_REGION)},
-	cpu_irq_actions
+	ops:	{ disable_cpu_irq, enable_cpu_irq, unmask_cpu_irq, unmask_cpu_irq },
+	data:	{ dev: &cpu_data[0],
+		  name: "PA-CPU-00",
+		  irqbase: IRQ_FROM_REGION(CPU_IRQ_REGION), },
+	action:	cpu_irq_actions,
 };
 
 struct irq_region *irq_region[NR_IRQ_REGS] = {
-	[ 0 ] NULL,		/* abuse will data page fault (aka code 15) */
+	[ 0 ]              NULL, /* reserved for EISA, else causes data page fault (aka code 15) */
 	[ CPU_IRQ_REGION ] &cpu_irq_region,
 };
 
 
+/*
+** Generic interfaces that device drivers can use:
+**    mask_irq()	block IRQ
+**    unmask_irq()	re-enable IRQ and trigger if IRQ is pending
+**    disable_irq()	block IRQ
+**    enable_irq()	clear pending and re-enable IRQ
+*/
 
-/* we special-case the real IRQs here, which feels right given the relatively
- * high cost of indirect calls.  If anyone is bored enough to benchmark this
- * and find out whether I am right, feel free to.   prumpf */
-
-static inline void mask_irq(int irq)
+void mask_irq(int irq)
 {
 	struct irq_region *region;
-	
-#ifdef DEBUG_IRQ
-	if (irq != TIMER_IRQ)
-#endif
-	DBG_IRQ("mask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
 
-	if(IRQ_REGION(irq) != CPU_IRQ_REGION) {
-		region = irq_region[IRQ_REGION(irq)];
-		if(region->data.flags & IRQ_REG_MASK)
-			region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq));
-	} else {
-		CLEAR_EIEM_BIT(irq);
-	}
+	DBG_IRQ(irq, ("mask_irq(%d) %d+%d eiem 0x%lx\n", irq,
+				IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem));
+	irq = irq_cannonicalize(irq);
+	region = irq_region[IRQ_REGION(irq)];
+	if (region->ops.mask_irq)
+		region->ops.mask_irq(region->data.dev, IRQ_OFFSET(irq));
 }
 
-static inline void unmask_irq(int irq)
+void unmask_irq(int irq)
 {
 	struct irq_region *region;
 
-#ifdef DEBUG_IRQ
-	if (irq != TIMER_IRQ)
-#endif
-	DBG_IRQ("unmask_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
-
-	if(IRQ_REGION(irq) != CPU_IRQ_REGION) {
-		region = irq_region[IRQ_REGION(irq)];
-		if(region->data.flags & IRQ_REG_MASK)
-			region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq));
-	} else {
-		SET_EIEM_BIT(irq);
-	}
+	DBG_IRQ(irq, ("unmask_irq(%d) %d+%d eiem 0x%lx\n", irq,
+				IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem));
+	irq = irq_cannonicalize(irq);
+	region = irq_region[IRQ_REGION(irq)];
+	if (region->ops.unmask_irq)
+		region->ops.unmask_irq(region->data.dev, IRQ_OFFSET(irq));
 }
 
 void disable_irq(int irq)
 {
 	struct irq_region *region;
 
-#ifdef DEBUG_IRQ
-	if (irq != TIMER_IRQ)
-#endif
-	DBG_IRQ("disable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+	DBG_IRQ(irq, ("disable_irq(%d) %d+%d eiem 0x%lx\n", irq,
+				IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem));
+	irq = irq_cannonicalize(irq);
 	region = irq_region[IRQ_REGION(irq)];
-
-	if(region->data.flags & IRQ_REG_DIS)
+	if (region->ops.disable_irq)
 		region->ops.disable_irq(region->data.dev, IRQ_OFFSET(irq));
 	else
 		BUG();
 }
 
-void enable_irq(int irq) 
+void enable_irq(int irq)
 {
 	struct irq_region *region;
 
-#ifdef DEBUG_IRQ
-	if (irq != TIMER_IRQ)
-#endif
-	DBG_IRQ("enable_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
+	DBG_IRQ(irq, ("enable_irq(%d) %d+%d eiem 0x%lx\n", irq,
+				IRQ_REGION(irq), IRQ_OFFSET(irq), cpu_eiem));
+	irq = irq_cannonicalize(irq);
 	region = irq_region[IRQ_REGION(irq)];
 
-	if(region->data.flags & IRQ_REG_DIS)
+	if (region->ops.enable_irq)
 		region->ops.enable_irq(region->data.dev, IRQ_OFFSET(irq));
 	else
 		BUG();
@@ -164,30 +190,40 @@
 {
 #ifdef CONFIG_PROC_FS
 	char *p = buf;
-	int i, j;
-	int regnr, irq_no;
-	struct irq_region *region;
-	struct irqaction *action, *mainaction;
+	unsigned int regnr = 0;
 
-	p += sprintf(p, "           ");
-	for (j=0; j<smp_num_cpus; j++)
-		p += sprintf(p, "CPU%d       ",j);
+	p += sprintf(p, "     ");
+#ifdef CONFIG_SMP
+	for (; regnr < smp_num_cpus; regnr++)
+#endif
+		p += sprintf(p, "      CPU%d ", regnr);
+
+#ifdef PARISC_IRQ_CR16_COUNTS
+	p += sprintf(p, "[min/avg/max] (CPU cycle counts)");
+#endif
 	*p++ = '\n';
 
+	/* We don't need *irqsave lock variants since this is
+	** only allowed to change while in the base context.
+	*/
+	spin_lock(&irq_lock);
 	for (regnr = 0; regnr < NR_IRQ_REGS; regnr++) {
-	    region = irq_region[regnr];
-	    if (!region || !region->action)
+	    unsigned int i;
+	    struct irq_region *region = irq_region[regnr];
+
+            if (!region || !region->action)
 		continue;
-	    
-	    mainaction = region->action;
 
 	    for (i = 0; i <= MAX_CPU_IRQ; i++) {
-		action = mainaction++;
-		if (!action || !action->name)
-		    continue;
-		
-		irq_no = IRQ_FROM_REGION(regnr) + i;
-		
+		struct irqaction *action = &region->action[i];
+		unsigned int irq_no = IRQ_FROM_REGION(regnr) + i;
+#ifdef CONFIG_SMP
+		unsigned int j;
+#endif
+
+		if (!action->handler)
+			continue;
+
 		p += sprintf(p, "%3d: ", irq_no);
 #ifndef CONFIG_SMP
 		p += sprintf(p, "%10u ", kstat_irqs(irq_no));
@@ -196,30 +232,48 @@
 		    p += sprintf(p, "%10u ",
 			    kstat.irqs[cpu_logical_map(j)][irq_no]);
 #endif
-		p += sprintf(p, " %14s", 
+		p += sprintf(p, " %14s",
 			    region->data.name ? region->data.name : "N/A");
+#ifndef PARISC_IRQ_CR16_COUNTS
 		p += sprintf(p, "  %s", action->name);
 
-		for (action=action->next; action; action = action->next)
-		    p += sprintf(p, ", %s", action->name);
-		*p++ = '\n';
-	    }	    	     
-	}  
+		while ((action = action->next))
+			p += sprintf(p, ", %s", action->name);
+#else
+		for ( ;action; action = action->next) {
+			unsigned int i, avg, min, max;
 
-	p += sprintf(p, "\n");
-#if CONFIG_SMP
-	p += sprintf(p, "LOC: ");
-	for (j = 0; j < smp_num_cpus; j++)
-		p += sprintf(p, "%10u ",
-			apic_timer_irqs[cpu_logical_map(j)]);
-	p += sprintf(p, "\n");
+			min = max = action->cr16_hist[0];
+
+			for (avg = i = 0; i < PARISC_CR16_HIST_SIZE; i++) {
+				int hist = action->cr16_hist[i];
+
+				if (hist) {
+					avg += hist;
+				} else
+					break;
+
+				if (hist > max) max = hist;
+				if (hist < min) min = hist;
+			}
+
+			avg /= i;
+			p += sprintf(p, " %s[%d/%d/%d]", action->name,
+					min,avg,max);
+		}
 #endif
 
+		*p++ = '\n';
+	    }
+	}
+	spin_unlock(&irq_lock);
+
+	p += sprintf(p, "\n");
 	return p - buf;
 
 #else	/* CONFIG_PROC_FS */
 
-	return 0;	
+	return 0;
 
 #endif	/* CONFIG_PROC_FS */
 }
@@ -240,8 +294,8 @@
 	int irq;
 
 	/* never return irq 0 cause that's the interval timer */
-	for(irq=1; irq<=MAX_CPU_IRQ; irq++) {
-		if(cpu_irq_region.action[irq].handler == NULL) {
+	for (irq = 1; irq <= MAX_CPU_IRQ; irq++) {
+		if (cpu_irq_region.action[irq].handler == NULL) {
 			return (IRQ_FROM_REGION(CPU_IRQ_REGION) + irq);
 		}
 	}
@@ -254,9 +308,7 @@
 txn_claim_irq(int irq)
 {
 	if (irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)].handler ==NULL)
-	{
 		return irq;
-	}
 
 	/* unlikely, but be prepared */
 	return -1;
@@ -267,10 +319,10 @@
 {
 	struct cpuinfo_parisc *dev = (struct cpuinfo_parisc *) (irq_region[IRQ_REGION(virt_irq)]->data.dev);
 
-	if (0==dev) {
+	if (!dev) {
 		printk(KERN_ERR "txn_alloc_addr(0x%x): CPU IRQ region? dev %p\n",
 			virt_irq,dev);
-		return(0UL);
+		return 0;
 	}
 	return (dev->txn_addr);
 }
@@ -283,7 +335,7 @@
 ** V-class (EPIC):          6 bits
 ** N/L-class/A500:          8 bits (iosapic)
 ** PCI 2.2 MSI:             16 bits (I think)
-** Existing PCI devices:    32-bits (NCR c720/ATM/GigE/HyperFabric)
+** Existing PCI devices:    32-bits (all Symbios SCSI/ATM/HyperFabric)
 **
 ** On the service provider side:
 ** o PA 1.1 (and PA2.0 narrow mode)     5-bits (width of EIR register)
@@ -308,117 +360,204 @@
 		panic("Sorry -- didn't allocate valid IRQ for this device\n");
 	}
 
-	return(IRQ_OFFSET(virt_irq));
+	return (IRQ_OFFSET(virt_irq));
 }
 
-
-/* FIXME: SMP, flags, bottom halves, rest */
 void do_irq(struct irqaction *action, int irq, struct pt_regs * regs)
 {
 	int cpu = smp_processor_id();
 
 	irq_enter(cpu, irq);
+	++kstat.irqs[IRQ_REGION(irq)][IRQ_OFFSET(irq)];
 
-#ifdef DEBUG_IRQ
-	if (irq != TIMER_IRQ)
+	DBG_IRQ(irq, ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq)));
+
+	for (; action; action = action->next) {
+#ifdef PARISC_IRQ_CR16_COUNTS
+		unsigned long cr_start = mfctl(16);
 #endif
-	DBG_IRQ("do_irq(%d) %d+%d\n", irq, IRQ_REGION(irq), IRQ_OFFSET(irq));
-	if (action->handler == NULL)
-		printk(KERN_ERR "No handler for interrupt %d !\n", irq);
 
-	for(; action && action->handler; action = action->next) {
+		if (action->handler == NULL) {
+			if (IRQ_REGION(irq) == EISA_IRQ_REGION && irq_region[EISA_IRQ_REGION]) {
+				/* were we called due to autodetecting (E)ISA irqs ? */
+				unsigned int *status;
+				status = &irq_region[EISA_IRQ_REGION]->data.status[IRQ_OFFSET(irq)];
+				if (*status & IRQ_AUTODETECT) {
+					*status &= ~IRQ_WAITING;
+					continue; 
+				}
+			}
+			printk(KERN_ERR "IRQ:  CPU:%d No handler for IRQ %d !\n", cpu, irq);
+			continue;
+		}
+
 		action->handler(irq, action->dev_id, regs);
+
+#ifdef PARISC_IRQ_CR16_COUNTS
+		{
+			unsigned long cr_end = mfctl(16);
+			unsigned long tmp = cr_end - cr_start;
+			/* check for roll over */
+			cr_start = (cr_end < cr_start) ?  -(tmp) : (tmp);
+		}
+		action->cr16_hist[action->cr16_idx++] = (int) cr_start;
+		action->cr16_idx &= PARISC_CR16_HIST_SIZE - 1;
+#endif
 	}
-	
+
 	irq_exit(cpu, irq);
+}
+
+
+/* ONLY called from entry.S:intr_extint() */
+void do_cpu_irq_mask(struct irq_region *region, struct pt_regs *regs)
+{
+	unsigned long eirr_val;
+	unsigned int i=3;	/* limit time in interrupt context */
+
+	/*
+	 * PSW_I or EIEM bits cannot be enabled until after the
+	 * interrupts are processed.
+	 * timer_interrupt() assumes it won't get interrupted when it
+	 * holds the xtime_lock...an unmasked interrupt source could
+	 * interrupt and deadlock by trying to grab xtime_lock too.
+	 * Keeping PSW_I and EIEM disabled avoids this.
+	 */
+	set_eiem(0UL);	/* disable all extr interrupt for now */
+
+	/* 1) only process IRQs that are enabled/unmasked (cpu_eiem)
+	 * 2) We loop here on EIRR contents in order to avoid
+	 *    nested interrupts or having to take another interupt
+	 *    when we could have just handled it right away.
+	 * 3) Limit the number of times we loop to make sure other
+	 *    processing can occur.
+	 */
+	while ((eirr_val = (mfctl(23) & cpu_eiem)) && --i) {
+		unsigned long bit = (1UL<<MAX_CPU_IRQ);
+		unsigned int irq = 0;
+
+		mtctl(eirr_val, 23); /* reset bits we are going to process */
+
+#ifdef DEBUG_IRQ
+		if (eirr_val != (1UL << MAX_CPU_IRQ))
+			printk(KERN_DEBUG "do_cpu_irq_mask  %x\n", eirr_val);
+#endif
+
+		for (; eirr_val && bit; bit>>=1, irq++)
+		{
+			unsigned int irq_num;
+			if (!(bit&eirr_val))
+				continue;
 
-	/* don't need to care about unmasking and stuff */
-	do_softirq();
+			/* clear bit in mask - can exit loop sooner */
+			eirr_val &= ~bit;
+
+			irq_num = region->data.irqbase + irq;
+			do_irq(&region->action[irq], irq_num, regs);
+		}
+	}
+	set_eiem(cpu_eiem);
 }
 
+
+/* Called from second level IRQ regions: eg dino or iosapic. */
 void do_irq_mask(unsigned long mask, struct irq_region *region, struct pt_regs *regs)
 {
 	unsigned long bit;
-	int irq;
-	int cpu = smp_processor_id();
+	unsigned int irq;
 
 #ifdef DEBUG_IRQ
-	if (mask != (1L << MAX_CPU_IRQ))
-	    printk("do_irq_mask %08lx %p %p\n", mask, region, regs);
+	if (mask != (1L<<MAX_CPU_IRQ))
+	    printk(KERN_DEBUG "do_irq_mask %08lx %p %p\n", mask, region, regs);
 #endif
 
-	for(bit=(1L<<MAX_CPU_IRQ), irq = 0; mask && bit; bit>>=1, irq++) {
-		int irq_num;
-		if(!(bit&mask))
+	for (bit = (1L<<MAX_CPU_IRQ), irq = 0; mask && bit; bit>>=1, irq++) {
+		unsigned int irq_num;
+		if (!(bit&mask))
 			continue;
 
+		mask &= ~bit;	/* clear bit in mask - can exit loop sooner */
 		irq_num = region->data.irqbase + irq;
 
-		++kstat.irqs[cpu][IRQ_FROM_REGION(CPU_IRQ_REGION) | irq];
-		if (IRQ_REGION(irq_num) != CPU_IRQ_REGION)
-		    ++kstat.irqs[cpu][irq_num];
-
 		mask_irq(irq_num);
 		do_irq(&region->action[irq], irq_num, regs);
 		unmask_irq(irq_num);
 	}
 }
 
-static inline int alloc_irqregion(void)
+
+static inline int find_free_region(void)
 {
 	int irqreg;
 
-	for(irqreg=1; irqreg<=(NR_IRQ_REGS); irqreg++) {
-		if(irq_region[irqreg] == NULL)
+	for (irqreg=1; irqreg <= (NR_IRQ_REGS); irqreg++) {
+		if (irq_region[irqreg] == NULL)
 			return irqreg;
 	}
 
 	return 0;
 }
 
-struct irq_region *alloc_irq_region(
-	int count, struct irq_region_ops *ops, unsigned long flags,
-	const char *name, void *dev)
+
+/*****
+ * alloc_irq_region - allocate/init a new IRQ region
+ * @count: number of IRQs in this region.
+ * @ops: function table with request/release/mask/unmask/etc.. entries.
+ * @name: name of region owner for /proc/interrupts output.
+ * @dev: private data to associate with the new IRQ region.
+ *
+ * Every IRQ must become a MMIO write to the CPU's EIRR in
+ * order to get CPU service. The IRQ region represents the
+ * number of unique events the region handler can (or must)
+ * identify. For PARISC CPU, that's the width of the EIR Register.
+ * IRQ regions virtualize IRQs (eg EISA or PCI host bus controllers)
+ * for line based devices.
+ */
+struct irq_region *alloc_irq_region( int count, struct irq_region_ops *ops,
+					const char *name, void *dev)
 {
 	struct irq_region *region;
 	int index;
 
-	index = alloc_irqregion();
+	index = find_free_region();
+	if (index == 0) {
+		printk(KERN_ERR "Maximum number of irq regions exceeded. Increase NR_IRQ_REGS!\n");
+		return NULL;
+	}
 
-	if((IRQ_REGION(count-1)))
+	if ((IRQ_REGION(count-1)))
 		return NULL;
-	
+
 	if (count < IRQ_PER_REGION) {
-	    DBG_IRQ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n", 
-			IRQ_PER_REGION, name, count);
+	    DBG_IRQ(0, ("alloc_irq_region() using minimum of %d irq lines for %s (%d)\n",
+			IRQ_PER_REGION, name, count));
 	    count = IRQ_PER_REGION;
 	}
 
-	if(flags & IRQ_REG_MASK)
-		if(!(ops->mask_irq && ops->unmask_irq))
-			return NULL;
-			
-	if(flags & IRQ_REG_DIS)
-		if(!(ops->disable_irq && ops->enable_irq))
+	/* if either mask *or* unmask is set, both have to be set. */
+	if((ops->mask_irq || ops->unmask_irq) &&
+		!(ops->mask_irq && ops->unmask_irq))
 			return NULL;
 
-	if((irq_region[index]))
-		return NULL;
+	/* ditto for enable/disable */
+	if( (ops->disable_irq || ops->enable_irq) &&
+		!(ops->disable_irq && ops->enable_irq) )
+			return NULL;
 
-	region = kmalloc(sizeof *region, GFP_ATOMIC);
-	if(!region)
+	region = kmalloc(sizeof(*region), GFP_ATOMIC);
+	if (!region)
 		return NULL;
+	memset(region, 0, sizeof(*region));
 
-	region->action = kmalloc(sizeof *region->action * count, GFP_ATOMIC);
-	if(!region->action) {
+	region->action = kmalloc(count * sizeof(*region->action), GFP_ATOMIC);
+	if (!region->action) {
 		kfree(region);
 		return NULL;
 	}
-	memset(region->action, 0, sizeof *region->action * count);
+	memset(region->action, 0, count * sizeof(*region->action));
 
 	region->ops = *ops;
 	region->data.irqbase = IRQ_FROM_REGION(index);
-	region->data.flags = flags;
 	region->data.name = name;
 	region->data.dev = dev;
 
@@ -426,14 +565,12 @@
 
 	return irq_region[index];
 }
-	
 
-	
 /* FIXME: SMP, flags, bottom halves, rest */
 
-int request_irq(unsigned int irq, 
+int request_irq(unsigned int irq,
 		void (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, 
+		unsigned long irqflags,
 		const char * devname,
 		void *dev_id)
 {
@@ -442,13 +579,19 @@
 #if 0
 	printk(KERN_INFO "request_irq(%d, %p, 0x%lx, %s, %p)\n",irq, handler, irqflags, devname, dev_id);
 #endif
-	if(!handler) {
+
+	irq = irq_cannonicalize(irq);
+	/* request_irq()/free_irq() may not be called from interrupt context. */
+	if (in_interrupt())
+		BUG();
+
+	if (!handler) {
 		printk(KERN_ERR "request_irq(%d,...): Augh! No handler for irq!\n",
 			irq);
 		return -EINVAL;
 	}
 
-	if ((IRQ_REGION(irq) == 0) || irq_region[IRQ_REGION(irq)] == NULL) {
+	if (irq_region[IRQ_REGION(irq)] == NULL) {
 		/*
 		** Bug catcher for drivers which use "char" or u8 for
 		** the IRQ number. They lose the region number which
@@ -459,19 +602,24 @@
 		return -EINVAL;
 	}
 
-	action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)];
+	spin_lock(&irq_lock);
+	action = &(irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)]);
 
-	if(action->handler) {
-		while(action->next)
+	/* First one is preallocated. */
+	if (action->handler) {
+		/* But it's in use...find the tail and allocate a new one */
+		while (action->next)
 			action = action->next;
 
-		action->next = kmalloc(sizeof *action, GFP_ATOMIC);
+		action->next = kmalloc(sizeof(*action), GFP_ATOMIC);
+		memset(action->next, 0, sizeof(*action));
 
 		action = action->next;
-	}			
+	}
 
-	if(!action) {
-		printk(KERN_ERR "request_irq():Augh! No action!\n") ;
+	if (!action) {
+		spin_unlock(&irq_lock);
+		printk(KERN_ERR "request_irq(): Augh! No action!\n") ;
 		return -ENOMEM;
 	}
 
@@ -481,6 +629,7 @@
 	action->name = devname;
 	action->next = NULL;
 	action->dev_id = dev_id;
+	spin_unlock(&irq_lock);
 
 	enable_irq(irq);
 	return 0;
@@ -490,14 +639,22 @@
 {
 	struct irqaction *action, **p;
 
+	/* See comments in request_irq() about interrupt context */
+	irq = irq_cannonicalize(irq);
+	
+	if (in_interrupt()) BUG();
+
+	spin_lock(&irq_lock);
 	action = &irq_region[IRQ_REGION(irq)]->action[IRQ_OFFSET(irq)];
 
-	if(action->dev_id == dev_id) {
-		if(action->next == NULL)
+	if (action->dev_id == dev_id) {
+		if (action->next == NULL) {
 			action->handler = NULL;
-		else
-			memcpy(action, action->next, sizeof *action);
+		} else {
+			memcpy(action, action->next, sizeof(*action));
+		}
 
+		spin_unlock(&irq_lock);
 		return;
 	}
 
@@ -512,27 +669,175 @@
 		*p = action->next;
 		kfree(action);
 
+		spin_unlock(&irq_lock);
 		return;
 	}
 
+	spin_unlock(&irq_lock);
 	printk(KERN_ERR "Trying to free free IRQ%d\n",irq);
 }
 
-unsigned long probe_irq_on (void)
+
+/*
+ * IRQ autodetection code..
+ *
+ * This depends on the fact that any interrupt that
+ * comes in on to an unassigned handler will get stuck
+ * with "IRQ_WAITING" cleared and the interrupt
+ * disabled.
+ */
+
+static DECLARE_MUTEX(probe_sem);
+
+/**
+ *	probe_irq_on	- begin an interrupt autodetect
+ *
+ *	Commence probing for an interrupt. The interrupts are scanned
+ *	and a mask of potential interrupt lines is returned.
+ *
+ */
+
+/* TODO: spin_lock_irq(desc->lock -> irq_lock) */
+
+unsigned long probe_irq_on(void)
 {
-	return 0;
+	unsigned int i;
+	unsigned long val;
+	unsigned long delay;
+	struct irq_region *region;
+
+	/* support for irq autoprobing is limited to EISA (irq region 0) */
+	region = irq_region[EISA_IRQ_REGION];
+	if (!EISA_bus || !region)
+		return 0;
+
+	down(&probe_sem);
+
+	/*
+	 * enable any unassigned irqs
+	 * (we must startup again here because if a longstanding irq
+	 * happened in the previous stage, it may have masked itself)
+	 */
+	for (i = EISA_MAX_IRQS-1; i > 0; i--) {
+		struct irqaction *action;
+		
+		spin_lock_irq(&irq_lock);
+		action = region->action + i;
+		if (!action->handler) {
+			region->data.status[i] |= IRQ_AUTODETECT | IRQ_WAITING;
+			region->ops.enable_irq(region->data.dev,i);
+		}
+		spin_unlock_irq(&irq_lock);
+	}
+
+	/*
+	 * Wait for spurious interrupts to trigger
+	 */
+	for (delay = jiffies + HZ/10; time_after(delay, jiffies); )
+		/* about 100ms delay */ synchronize_irq();
+
+	/*
+	 * Now filter out any obviously spurious interrupts
+	 */
+	val = 0;
+	for (i = 0; i < EISA_MAX_IRQS; i++) {
+		unsigned int status;
+
+		spin_lock_irq(&irq_lock);
+		status = region->data.status[i];
+
+		if (status & IRQ_AUTODETECT) {
+			/* It triggered already - consider it spurious. */
+			if (!(status & IRQ_WAITING)) {
+				region->data.status[i] = status & ~IRQ_AUTODETECT;
+				region->ops.disable_irq(region->data.dev,i);
+			} else
+				if (i < BITS_PER_LONG)
+					val |= (1 << i);
+		}
+		spin_unlock_irq(&irq_lock);
+	}
+
+	return val;
 }
 
-int probe_irq_off (unsigned long irqs)
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source).
+ */
+
+/**
+ *	probe_irq_off	- end an interrupt autodetect
+ *	@val: mask of potential interrupts (unused)
+ *
+ *	Scans the unused interrupt lines and returns the line which
+ *	appears to have triggered the interrupt. If no interrupt was
+ *	found then zero is returned. If more than one interrupt is
+ *	found then minus the first candidate is returned to indicate
+ *	their is doubt.
+ *
+ *	The interrupt probe logic state is returned to its previous
+ *	value.
+ *
+ *	BUGS: When used in a module (which arguably shouldnt happen)
+ *	nothing prevents two IRQ probe callers from overlapping. The
+ *	results of this are non-optimal.
+ */
+ 
+int probe_irq_off(unsigned long val)
 {
-	return 0;
+        struct irq_region *region;
+	int i, irq_found, nr_irqs;
+
+        /* support for irq autoprobing is limited to EISA (irq region 0) */
+        region = irq_region[EISA_IRQ_REGION];
+        if (!EISA_bus || !region)
+		return 0;
+
+	nr_irqs = 0;
+	irq_found = 0;
+	for (i = 0; i < EISA_MAX_IRQS; i++) {
+		unsigned int status;
+		
+		spin_lock_irq(&irq_lock);
+		status = region->data.status[i];
+
+                if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING)) {
+				if (!nr_irqs)
+					irq_found = i;
+				nr_irqs++;
+			}
+			region->ops.disable_irq(region->data.dev,i);
+			region->data.status[i] = status & ~IRQ_AUTODETECT;
+		}
+		spin_unlock_irq(&irq_lock);
+	}
+	up(&probe_sem);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
+	return irq_found;
 }
 
 
 void __init init_IRQ(void)
 {
+	local_irq_disable();	/* PARANOID - should already be disabled */
+	mtctl(-1L, 23);		/* EIRR : clear all pending external intr */
+#ifdef CONFIG_SMP
+	if (!cpu_eiem)
+		cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
+#else
+	cpu_eiem = EIEM_MASK(TIMER_IRQ);
+#endif
+        set_eiem(cpu_eiem);	/* EIEM : enable all external intr */
+
 }
 
-void init_irq_proc(void)
+#ifdef CONFIG_PROC_FS
+/* called from kernel/sysctl.c:sysctl_init() */
+void __init init_irq_proc(void)
 {
 }
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/irq_smp.c linux/arch/parisc/kernel/irq_smp.c
--- linux.orig/arch/parisc/kernel/irq_smp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/irq_smp.c	2002-08-12 22:14:11.000000000 +0000
@@ -0,0 +1,232 @@
+/*
+ *  linux/arch/parisc/kernel/irq_smp.c
+ *  (90% stolen from alpha port, 9% from ia64, rest is mine -ggg)
+ *  
+ *  Copyright (C) 2001 Hewlett-Packard Co
+ *  Copyright (C) 2001 Grant Grundler <grundler@puffin.external.hp.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/random.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+
+int global_irq_holder = NO_PROC_ID;	/* Who has global_irq_lock. */
+spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED; /* protects IRQ's. */
+
+
+/* Global IRQ locking depth. */
+static void *previous_irqholder = NULL;
+
+#define MAXCOUNT 100000000
+
+
+static void
+show(char * str, void *where)
+{
+	int cpu = smp_processor_id();
+
+	printk("\n%s, CPU %d: %p\n", str, cpu, where);
+	printk("irq:  %d [%d %d]\n",
+		irqs_running(),
+		local_irq_count(0),
+		local_irq_count(1));
+
+	printk("bh:   %d [%d %d]\n",
+		spin_is_locked(&global_bh_lock) ? 1 : 0,
+		local_bh_count(0),
+		local_bh_count(1));
+}
+
+static inline void
+wait_on_irq(int cpu, void *where)
+{
+	int count = MAXCOUNT;
+
+	for (;;) {
+
+		/*
+		 * Wait until all interrupts are gone. Wait
+		 * for bottom half handlers unless we're
+		 * already executing in one..
+		 */
+		if (!irqs_running()) {
+			if (local_bh_count(cpu)
+			    || !spin_is_locked(&global_bh_lock))
+				break;
+		}
+
+		/* Duh, we have to loop. Release the lock to avoid deadlocks */
+		spin_unlock(&global_irq_lock);
+
+		for (;;) {
+			if (!--count) {
+				show("wait_on_irq", where);
+				count = MAXCOUNT;
+			}
+			__sti();
+			udelay(1); /* make sure to run pending irqs */
+			__cli();
+
+			if (irqs_running())
+				continue;
+			if (spin_is_locked(&global_irq_lock))
+				continue;
+			if (!local_bh_count(cpu)
+			    && spin_is_locked(&global_bh_lock))
+				continue;
+			if (spin_trylock(&global_irq_lock))
+				break;
+		}
+	}
+}
+
+static inline void
+get_irqlock(int cpu, void* where)
+{
+	if (!spin_trylock(&global_irq_lock)) {
+		/* Do we already hold the lock?  */
+		if (cpu == global_irq_holder)
+			return;
+		/* Uhhuh.. Somebody else got it.  Wait.  */
+		spin_lock(&global_irq_lock);
+	}
+
+	/*
+	 * Ok, we got the lock bit.
+	 * But that's actually just the easy part.. Now
+	 * we need to make sure that nobody else is running
+	 * in an interrupt context. 
+	 */
+	wait_on_irq(cpu, where);
+
+	/*
+	 * Finally.
+	 */
+#if DEBUG_SPINLOCK
+	global_irq_lock.task = current;
+	global_irq_lock.previous = where;
+#endif
+	global_irq_holder = cpu;
+	previous_irqholder = where;
+}
+
+
+/*
+** A global "cli()" while in an interrupt context
+** turns into just a local cli(). Interrupts
+** should use spinlocks for the (very unlikely)
+** case that they ever want to protect against
+** each other.
+** 
+** If we already have local interrupts disabled,
+** this will not turn a local disable into a
+** global one (problems with spinlocks: this makes
+** save_flags+cli+sti usable inside a spinlock).
+*/
+void
+__global_cli(void)
+{
+	unsigned int flags;
+	__save_flags(flags);
+	if (flags & PSW_I) {
+		int cpu = smp_processor_id();
+		__cli(); 
+		if (!local_irq_count(cpu)) {
+			void *where = __builtin_return_address(0);
+			get_irqlock(cpu, where);
+		}
+	}
+}
+
+void
+__global_sti(void)
+{
+	int cpu = smp_processor_id();
+
+	if (!local_irq_count(cpu))
+		release_irqlock(cpu);
+	__sti();
+}
+
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
+unsigned long
+__global_save_flags(void)
+{
+	int retval;
+	int local_enabled;
+	unsigned long flags;
+	int cpu = smp_processor_id();
+
+	__save_flags(flags);
+	local_enabled = (flags & PSW_I) != 0;
+	/* default to local */
+	retval = 2 + local_enabled;
+
+	/* Check for global flags if we're not in an interrupt.  */
+	if (!local_irq_count(cpu)) {
+		if (local_enabled)
+			retval = 1;
+		if (global_irq_holder == cpu)
+			retval = 0;
+	}
+	return retval;
+}
+
+void
+__global_restore_flags(unsigned long flags)
+{
+	switch (flags) {
+	case 0:
+		__global_cli();
+		break;
+	case 1:
+		__global_sti();
+		break;
+	case 2:
+		__cli();
+		break;
+	case 3:
+		__sti();
+		break;
+	default:
+		printk(KERN_ERR "global_restore_flags: %08lx (%p)\n",
+			flags, __builtin_return_address(0));
+	}
+}
+
+/*
+ * From its use, I infer that synchronize_irq() stalls a thread until
+ * the effects of a command to an external device are known to have
+ * taken hold.  Typically, the command is to stop sending interrupts.
+ * The strategy here is wait until there is at most one processor
+ * (this one) in an irq.  The memory barrier serializes the write to
+ * the device and the subsequent accesses of global_irq_count.
+ * --jmartin
+ */
+#define DEBUG_SYNCHRONIZE_IRQ 0
+
+void
+synchronize_irq(void)
+{
+	/* Jay's version.  */
+	if (irqs_running()) {
+		cli();
+		sti();
+	}
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/keyboard.c linux/arch/parisc/kernel/keyboard.c
--- linux.orig/arch/parisc/kernel/keyboard.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/keyboard.c	2002-08-12 22:14:09.000000000 +0000
@@ -1,4 +1,12 @@
 /*
+ *  WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *  ---------------------------------------------------------------
+ *  This source file will be removed as soon as we have converted
+ *  hp_psaux.c and hp_keyb.c to the input layer !
+ *  
+ */
+
+/*
  *  linux/arch/parisc/kernel/keyboard.c
  *
  *  Alex deVries <adevries@thepuffingroup.com>
@@ -7,8 +15,10 @@
  *  Copyright 2000 Philipp Rumpf
  */
 
+#include <linux/errno.h>
 #include <linux/keyboard.h>
 #include <asm/keyboard.h>
+#include <linux/module.h>
 
 static int def_setkeycode(unsigned int x, unsigned int y)
 {
@@ -43,20 +53,29 @@
 
 static char def_sysrq_xlate[NR_KEYS];
 
-static struct kbd_ops def_kbd_ops = {
-	setkeycode:	def_setkeycode,
-	getkeycode:	def_getkeycode,
-	translate:	def_translate,
-	unexpected_up:	def_unexpected_up,
-	leds:		def_leds,
-	init_hw:	def_init_hw,
-
-	sysrq_key:	0xff,
+#define DEFAULT_KEYB_OPS \
+	setkeycode:	def_setkeycode,	\
+	getkeycode:	def_getkeycode, \
+	translate:	def_translate, \
+	unexpected_up:	def_unexpected_up, \
+	leds:		def_leds, \
+	init_hw:	def_init_hw, \
+	sysrq_key:	0xff, \
 	sysrq_xlate:	def_sysrq_xlate,
+
+static struct kbd_ops def_kbd_ops = {
+	DEFAULT_KEYB_OPS
 };
 
 struct kbd_ops *kbd_ops = &def_kbd_ops;
 
+void unregister_kbd_ops(void)
+{
+	struct kbd_ops new_kbd_ops = { DEFAULT_KEYB_OPS };
+	register_kbd_ops(&new_kbd_ops);
+}
+EXPORT_SYMBOL(unregister_kbd_ops);
+
 void register_kbd_ops(struct kbd_ops *ops)
 {
 	if(ops->setkeycode)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/lba_pci.c linux/arch/parisc/kernel/lba_pci.c
--- linux.orig/arch/parisc/kernel/lba_pci.c	2001-02-09 19:29:44.000000000 +0000
+++ linux/arch/parisc/kernel/lba_pci.c	2002-08-12 22:14:24.000000000 +0000
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>		/* for __init and __devinit */
+/* #define PCI_DEBUG	enable ASSERT */
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
@@ -42,15 +43,13 @@
 #include <asm/byteorder.h>
 #include <asm/irq.h>		/* for struct irq_region support */
 #include <asm/pdc.h>
-#include <asm/pdcpat.h>
 #include <asm/page.h>
 #include <asm/segment.h>
 #include <asm/system.h>
 
-#include <asm/hardware.h>	/* for register_driver() stuff */
+#include <asm/hardware.h>	/* for register_parisc_driver() stuff */
 #include <asm/iosapic.h>	/* for iosapic_register() */
-#include <asm/gsc.h>		/* gsc_read/write stuff */
-
+#include <asm/io.h>		/* read/write stuff */
 
 #ifndef TRUE
 #define TRUE (1 == 1)
@@ -62,6 +61,9 @@
 #undef DEBUG_LBA_CFG	/* debug Config Space Access (ie PCI Bus walk) */
 #undef DEBUG_LBA_PAT	/* debug PCI Resource Mgt code - PDC PAT only */
 
+#undef FBB_SUPPORT	/* Fast Back-Back xfers - NOT READY YET */
+
+
 #ifdef DEBUG_LBA
 #define DBG(x...)	printk(x)
 #else
@@ -102,22 +104,6 @@
 
 #define MODULE_NAME "lba"
 
-static int lba_driver_callback(struct hp_device *, struct pa_iodc_driver *);
-
-
-static struct pa_iodc_driver lba_drivers_for[]= {
-
-   {HPHW_BRIDGE, 0x782, 0x0, 0xa, 0,0,
-		DRIVER_CHECK_HVERSION + 
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "tbd", (void *) lba_driver_callback},
-
-   {0,0,0,0,0,0,
-   0,
-   (char *) NULL, (char *) NULL, (void *) NULL}
-};
-
-
 #define LBA_FUNC_ID	0x0000	/* function id */
 #define LBA_FCLASS	0x0008	/* function class, bist, header, rev... */
 #define LBA_CAPABLE	0x0030	/* capabilities register */
@@ -137,6 +123,9 @@
 #define LBA_MOD_ID	0x0100	/* Module ID. PDC_PAT_CELL reports 4 */
 
 #define LBA_STAT_CTL	0x0108	/* Status & Control */
+#define   LBA_BUS_RESET		0x01	/*  Deassert PCI Bus Reset Signal */
+#define   CLEAR_ERRLOG		0x10	/*  "Clear Error Log" cmd */
+#define   CLEAR_ERRLOG_ENABLE	0x20	/*  "Clear Error Log" Enable */
 #define   HF_ENABLE	0x40	/*    enable HF mode (default is -1 mode) */
 
 #define LBA_LMMIO_BASE	0x0200	/* < 4GB I/O address range */
@@ -162,15 +151,18 @@
 
 #define LBA_DMA_CTL	0x0278	/* firmware sets this */
 
-/* RESET: ignore DMA stuff until we can measure performance */
-#define LBA_IBASE	0x0300	/* DMA support */
+#define LBA_IBASE	0x0300	/* SBA DMA support */
 #define LBA_IMASK	0x0308
+
+/* FIXME: ignore DMA Hint stuff until we can measure performance */
 #define LBA_HINT_CFG	0x0310
 #define LBA_HINT_BASE	0x0380	/* 14 registers at every 8 bytes. */
 
 /* ERROR regs are needed for config cycle kluges */
 #define LBA_ERROR_CONFIG 0x0680
+#define     LBA_SMART_MODE 0x20
 #define LBA_ERROR_STATUS 0x0688
+#define LBA_ROPE_CTL     0x06A0
 
 #define LBA_IOSAPIC_BASE	0x800 /* Offset of IRQ logic */
 
@@ -232,19 +224,20 @@
  * BE WARNED: register writes are posted.
  *  (ie follow writes which must reach HW with a read)
  */
-#define READ_U8(addr)  gsc_readb(addr)
-#define READ_U16(addr) gsc_readw((u16 *) (addr))
-#define READ_U32(addr) gsc_readl((u32 *) (addr))
-#define WRITE_U8(value, addr) gsc_writeb(value, addr)
-#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr))
-#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
-
-#define READ_REG8(addr)  gsc_readb(addr)
-#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
-#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
-#define WRITE_REG8(value, addr) gsc_writeb(value, addr)
-#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
-#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
+#define READ_U8(addr)  __raw_readb(addr)
+#define READ_U16(addr) __raw_readw(addr)
+#define READ_U32(addr) __raw_readl(addr)
+#define WRITE_U8(value, addr)  __raw_writeb(value, addr)
+#define WRITE_U16(value, addr) __raw_writew(value, addr)
+#define WRITE_U32(value, addr) __raw_writel(value, addr)
+
+#define READ_REG8(addr)  readb(addr)
+#define READ_REG16(addr) readw(addr)
+#define READ_REG32(addr) readl(addr)
+#define READ_REG64(addr) readq(addr)
+#define WRITE_REG8(value, addr)  writeb(value, addr)
+#define WRITE_REG16(value, addr) writew(value, addr)
+#define WRITE_REG32(value, addr) writel(value, addr)
 
 
 #define LBA_CFG_TOK(bus,dfn) ((u32) ((bus)<<16 | (dfn)<<8))
@@ -253,25 +246,12 @@
 #define LBA_CFG_FUNC(tok) ((u8) ((tok)>>8 ) & 0x7)
 
 
-#ifdef DEBUG_LBA
-/* Extract LBA (Rope) number from HPA */
-#define LBA_NUM(x)    ((((uintptr_t) x) >> 13) & 0xf)
-#endif /* DEBUG_LBA */
-
-#ifdef __LP64__
-/* PDC_PAT */
-static  unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
-#endif
-
 /*
-** One time initialization to let the world know the LBA was found.
-** This is the only routine which is NOT static.
-** Must be called exactly once before pci_init().
+** Extract LBA (Rope) number from HPA
+** REVISIT: 16 ropes for Stretch/Ike?
 */
-void __init lba_init(void)
-{
-	register_driver(lba_drivers_for);
-}
+#define ROPES_PER_SBA	8
+#define LBA_NUM(x)    ((((unsigned long) x) >> 13) & (ROPES_PER_SBA-1))
 
 
 static void
@@ -282,9 +262,9 @@
 	if (NULL == r)
 		return;
 
-	printk("(%p)", r->parent);
+	printk(KERN_DEBUG "(%p)", r->parent);
 	for (i = d; i ; --i) printk(" ");
-	printk("%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags);
+	printk(KERN_DEBUG "%p [%lx,%lx]/%x\n", r, r->start, r->end, (int) r->flags);
 	lba_dump_res(r->child, d+2);
 	lba_dump_res(r->sibling, d);
 }
@@ -369,7 +349,7 @@
      * Set the smart mode bit so that master aborts don't cause		\
      * LBA to go into PCI fatal mode (required).			\
      */									\
-    WRITE_REG32(error_config | 0x20, d->hba.base_addr + LBA_ERROR_CONFIG);	\
+    WRITE_REG32(error_config | LBA_SMART_MODE, d->hba.base_addr + LBA_ERROR_CONFIG);	\
 }
 
 
@@ -414,9 +394,9 @@
  *
  *		Actually, there is still a race in which
  *		we could be clearing a fatal error.  We will
- *		live with this during our real mode bus walk
+ *		live with this during our initial bus walk
  *		until rev 4.0 (no driver activity during
- *		real mode bus walk).  The real mode bus walk
+ *		initial bus walk).  The initial bus walk
  *		has race conditions concerning the use of
  *		smart mode as well.
  */
@@ -430,7 +410,7 @@
      * Set clear enable (CE) bit. Unset by HW when new			\
      * errors are logged -- LBA HW ERS section 14.3.3).		\
      */									\
-    WRITE_REG32(status_control | 0x20, base + LBA_STAT_CTL);	\
+    WRITE_REG32(status_control | CLEAR_ERRLOG_ENABLE, base + LBA_STAT_CTL); \
     error_status = READ_REG32(base + LBA_ERROR_STATUS);		\
     if ((error_status & 0x1f) != 0) {					\
 	/*								\
@@ -442,7 +422,7 @@
 	     * Clear error status (if fatal bit not set) by setting	\
 	     * clear error log bit (CL).				\
 	     */								\
-	    WRITE_REG32(status_control | 0x10, base + LBA_STAT_CTL);	\
+	    WRITE_REG32(status_control | CLEAR_ERRLOG, base + LBA_STAT_CTL); \
 	}								\
     }									\
 }
@@ -483,7 +463,7 @@
 
 
 static unsigned int
-lba_rd_cfg( struct lba_device *d, u32 tok, u8 reg, u32 size)
+lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
 {
 	u32 data = ~0;
 	int error = 0;
@@ -525,7 +505,6 @@
 }
 
 
-
 #define LBA_CFG_RD(size, mask) \
 static int lba_cfg_read##size (struct pci_dev *dev, int pos, u##size *data) \
 { \
@@ -533,17 +512,18 @@
 	u32 local_bus = (dev->bus->parent == NULL) ? 0 : dev->bus->secondary; \
 	u32 tok = LBA_CFG_TOK(local_bus,dev->devfn); \
  \
-	if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \
+/* FIXME: B2K/C3600 workaround is always use old method... */ \
+	/* if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) */ { \
 		/* original - Generate config cycle on broken elroy \
 		  with risk we will miss PCI bus errors. */ \
 		*data = (u##size) lba_rd_cfg(d, tok, pos, sizeof(u##size)); \
-		DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \
+		DBG_CFG("%s(%s+%2x) -> 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, *data); \
 		return(*data == (u##size) -1); \
 	} \
  \
 	if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) \
 	{ \
-		DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos, *data); \
+		DBG_CFG("%s(%s+%2x) -> -1 (b)\n", __FUNCTION__, dev->slot_name, pos); \
 		/* either don't want to look or know device isn't present. */ \
 		*data = (u##size) -1; \
 		return(0); \
@@ -555,7 +535,7 @@
 	*/ \
 	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \
 	*data = READ_REG##size(d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask));\
-	DBG_CFG(KERN_DEBUG "%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\
+	DBG_CFG("%s(%s+%2x) -> 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, *data);\
 	return(*data == (u##size) -1); \
 }
 
@@ -618,19 +598,19 @@
  	ASSERT((tok & 0xff) == 0); \
 	ASSERT(pos < 0x100); \
  \
-	if ((!LBA_TR4PLUS(d)) && (!LBA_SKIP_PROBE(d))) { \
+	if (!LBA_TR4PLUS(d) && !LBA_SKIP_PROBE(d)) { \
 		/* Original Workaround */ \
 		lba_wr_cfg(d, tok, pos, (u32) data, sizeof(u##size)); \
-		DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \
+		DBG_CFG("%s(%s+%2x) = 0x%x (a)\n", __FUNCTION__, dev->slot_name, pos, data); \
 		return 0; \
 	} \
  \
 	if (LBA_SKIP_PROBE(d) && (!lba_device_present(dev->bus->secondary, dev->devfn, d))) { \
-		DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \
+		DBG_CFG("%s(%s+%2x) = 0x%x (b)\n", __FUNCTION__, dev->slot_name, pos, data); \
 		return 1; /* New Workaround */ \
 	} \
  \
-	DBG_CFG(KERN_DEBUG "%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \
+	DBG_CFG("%s(%s+%2x) = 0x%x (c)\n", __FUNCTION__, dev->slot_name, pos, data); \
 	/* Basic Algorithm */ \
 	LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); \
 	WRITE_REG##size(data, d->hba.base_addr + LBA_PCI_CFG_DATA + (pos & mask)); \
@@ -644,9 +624,12 @@
 LBA_CFG_WR(32, 0) 
 
 static struct pci_ops lba_cfg_ops = {
-        lba_cfg_read8, lba_cfg_read16, lba_cfg_read32,
-	lba_cfg_write8, lba_cfg_write16, lba_cfg_write32
-
+	read_byte:	lba_cfg_read8,
+	read_word:	lba_cfg_read16,
+	read_dword:	lba_cfg_read32,
+	write_byte:	lba_cfg_write8,
+	write_word:	lba_cfg_write16,
+	write_dword:	lba_cfg_write32
 };
 
 
@@ -654,7 +637,7 @@
 static void
 lba_bios_init(void)
 {
-	DBG(KERN_DEBUG MODULE_NAME ": lba_bios_init\n");
+	DBG(MODULE_NAME ": lba_bios_init\n");
 }
 
 
@@ -712,15 +695,15 @@
 lba_fixup_bus(struct pci_bus *bus)
 {
 	struct list_head *ln;
-        struct pci_dev *dev;
+#ifdef FBB_SUPPORT
 	u16 fbb_enable = PCI_STATUS_FAST_BACK;
 	u16 status;
-	struct lba_device *ldev = LBA_DEV(bus->sysdata);
-#ifdef __LP64__
-	int i;
 #endif
+	struct lba_device *ldev = LBA_DEV(bus->sysdata);
+	int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num);
+
 	DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
-				bus, bus->secondary, bus->sysdata);
+		bus, bus->secondary, bus->sysdata);
 
 	/*
 	** Properly Setup MMIO resources for this bus.
@@ -731,63 +714,119 @@
 
 		DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
 			ldev->hba.io_space.name,
-			ldev->hba.io_space.start,
-			ldev->hba.io_space.end,
+			ldev->hba.io_space.start, ldev->hba.io_space.end,
 			(int) ldev->hba.io_space.flags);
 		DBG("lba_fixup_bus() %s [%lx/%lx]/%x\n",
-			ldev->hba.mem_space.name,
-			ldev->hba.mem_space.start,
-			ldev->hba.mem_space.end,
-			(int) ldev->hba.mem_space.flags);
+			ldev->hba.lmmio_space.name,
+			ldev->hba.lmmio_space.start, ldev->hba.lmmio_space.end,
+			(int) ldev->hba.lmmio_space.flags);
 
 		err = request_resource(&ioport_resource, &(ldev->hba.io_space));
 		if (err < 0) {
 			BUG();
 			lba_dump_res(&ioport_resource, 2);
 		}
-		err = request_resource(&iomem_resource, &(ldev->hba.mem_space));
+		err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
 		if (err < 0) {
 			BUG();
 			lba_dump_res(&iomem_resource, 2);
 		}
 
 		bus->resource[0] = &(ldev->hba.io_space);
-		bus->resource[1] = &(ldev->hba.mem_space);
+		bus->resource[1] = &(ldev->hba.lmmio_space);
+	} else {
+		/* KLUGE ALERT!
+		** PCI-PCI Bridge resource munging.
+		** This hack should go away in the near future.
+		** It's based on the Alpha port.
+		*/
+		int i;
+		u16 cmd;
+
+		for (i = 0; i < 4; i++) {
+			bus->resource[i] =
+				&bus->self->resource[PCI_BRIDGE_RESOURCES+i];
+			bus->resource[i]->name = bus->name;
+		}
+#if 0
+		bus->resource[0]->flags |= pci_bridge_check_io(bus->self);
+#else
+		bus->resource[0]->flags |= IORESOURCE_IO;
+#endif
+		bus->resource[1]->flags |= IORESOURCE_MEM;
+		bus->resource[2]->flags = 0;	/* Don't support prefetchable */
+		bus->resource[3]->flags = 0;	/* not used */
+
+		/* 
+		** If the PPB is enabled (ie already configured) then
+		** just read those values.
+		*/
+		(void) lba_cfg_read16(bus->self, PCI_COMMAND, &cmd);
+		if (cmd & (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)) {
+			pci_read_bridge_bases(bus);
+		} else {
+			/* Not configured.
+			** For now, propogate HBA limits to the bus;
+			**	PCI will adjust them later.
+			*/
+			bus->resource[0]->end = ldev->hba.io_space.end;
+			bus->resource[1]->end = ldev->hba.lmmio_space.end;
+		}
+
+		/* Turn off downstream PF memory address range by default */
+		bus->resource[2]->start = 1024*1024;
+		bus->resource[2]->end = bus->resource[2]->start - 1;
 	}
 
-	list_for_each(ln, &bus->devices) {
 
-		dev = pci_dev_b(ln);
+	list_for_each(ln, &bus->devices) {
+		int i;
+		struct pci_dev *dev = pci_dev_b(ln);
 
-#ifdef __LP64__
-		/*
-		** 0-5 are the "standard PCI regions"
-		** (see comments near PCI_NUM_RESOURCES in include/linux/pci.h)
-		*/
-		for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
-			struct resource *res = &(dev->resource[i]);
+		DBG("lba_fixup_bus() %s\n", dev->name);
 
-			if (res->flags & IORESOURCE_MEM) {
-				/* "Globalize" PCI address */
-				res->start |= ldev->lmmio_base;
-				res->end   |= ldev->lmmio_base;
+		/* Virtualize Device/Bridge Resources. */
+		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+			struct resource *res = &dev->resource[i];
+
+			/* If resource not allocated - skip it */
+			if (!res->start)
+				continue;
+
+			if (res->flags & IORESOURCE_IO) {
+				DBG("lba_fixup_bus() I/O Ports [%lx/%lx] -> ",
+					res->start, res->end);
+				res->start |= lba_portbase;
+				res->end   |= lba_portbase;
+				DBG("[%lx/%lx]\n", res->start, res->end);
+			} else if (res->flags & IORESOURCE_MEM) {
+				/*
+				** Convert PCI (IO_VIEW) addresses to
+				** processor (PA_VIEW) addresses
+				 */
+				DBG("lba_fixup_bus() MMIO [%lx/%lx] -> ",
+					res->start, res->end);
+				res->start = PCI_HOST_ADDR(HBA_DATA(ldev), res->start);
+				res->end   = PCI_HOST_ADDR(HBA_DATA(ldev), res->end);
+				DBG("[%lx/%lx]\n", res->start, res->end);
 			}
 		}
-#endif
 
+#ifdef FBB_SUPPORT
 		/*
 		** If one device does not support FBB transfers,
 		** No one on the bus can be allowed to use them.
 		*/
 		(void) lba_cfg_read16(dev, PCI_STATUS, &status);
 		fbb_enable &= status;
+#endif
 
 #ifdef __LP64__
-		if (pdc_pat) {
+		if (is_pdc_pat()) {
 			/* Claim resources for PDC's devices */
 			lba_claim_dev_resources(dev);
 		}
-#endif	/* __LP64__ */
+#endif
 
                 /*
 		** P2PB's have no IRQs. ignore them.
@@ -796,12 +835,12 @@
 			continue;
 
 		/* Adjust INTERRUPT_LINE for this dev */
-		iosapic_fixup_irq(LBA_DEV(bus->sysdata)->iosapic_obj, dev);
+		iosapic_fixup_irq(ldev->iosapic_obj, dev);
 	}
 
-#if 0
+#ifdef FBB_SUPPORT
 /* FIXME/REVISIT - finish figuring out to set FBB on both
-** pbus_set_ranges() clobbers PCI_BRIDGE_CONTROL.
+** pci_setup_bridge() clobbers PCI_BRIDGE_CONTROL.
 ** Can't fixup here anyway....garr...
 */
 	if (fbb_enable) {
@@ -828,8 +867,8 @@
 
 
 struct pci_bios_ops lba_bios_ops = {
-	lba_bios_init,
-	lba_fixup_bus  /* void lba_fixup_bus(struct pci_bus *bus) */
+	init:		lba_bios_init,
+	fixup_bus:	lba_fixup_bus,
 };
 
 
@@ -853,8 +892,6 @@
 static u##size lba_astro_in##size (struct pci_hba_data *d, u16 addr) \
 { \
 	u##size t; \
-	ASSERT(bus != NULL); \
-	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, bus, addr); \
 	t = READ_REG##size(LBA_ASTRO_PORT_BASE + addr); \
 	DBG_PORT(" 0x%x\n", t); \
 	return (t); \
@@ -895,8 +932,8 @@
 #define LBA_PORT_OUT(size, mask) \
 static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \
 { \
-	ASSERT(bus != NULL); \
-	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
+	ASSERT(d != NULL); \
+	DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \
 	WRITE_REG##size(val, LBA_ASTRO_PORT_BASE + addr); \
 	if (LBA_DEV(d)->hw_rev < 3) \
 		lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \
@@ -908,13 +945,16 @@
 
 
 static struct pci_port_ops lba_astro_port_ops = {
-	lba_astro_in8, lba_astro_in16, lba_astro_in32,
-	lba_astro_out8, lba_astro_out16, lba_astro_out32
+	inb:	lba_astro_in8,
+	inw:	lba_astro_in16,
+	inl:	lba_astro_in32,
+	outb:	lba_astro_out8,
+	outw:	lba_astro_out16,
+	outl:	lba_astro_out32
 };
 
 
 #ifdef __LP64__
-
 #define PIOP_TO_GMMIO(lba, addr) \
 	((lba)->iop_base + (((addr)&0xFFFC)<<10) + ((addr)&3))
 
@@ -936,7 +976,7 @@
 { \
 	u##size t; \
 	ASSERT(bus != NULL); \
-	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \
+	DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \
 	t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \
 	DBG_PORT(" 0x%x\n", t); \
 	return (t); \
@@ -953,7 +993,7 @@
 { \
 	void *where = (void *) PIOP_TO_GMMIO(LBA_DEV(l), addr); \
 	ASSERT(bus != NULL); \
-	DBG_PORT(KERN_DEBUG "%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \
+	DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \
 	WRITE_REG##size(val, where); \
 	/* flush the I/O down to the elroy at least */ \
 	lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \
@@ -965,8 +1005,12 @@
 
 
 static struct pci_port_ops lba_pat_port_ops = {
-	lba_pat_in8, lba_pat_in16, lba_pat_in32,
-	lba_pat_out8, lba_pat_out16, lba_pat_out32
+	inb:	lba_pat_in8,
+	inw:	lba_pat_in16,
+	inl:	lba_pat_in32,
+	outb:	lba_pat_out8,
+	outw:	lba_pat_out16,
+	outl:	lba_pat_out32
 };
 
 
@@ -978,30 +1022,27 @@
 ** We don't have a struct pci_bus assigned to us yet.
 */
 static void
-lba_pat_resources( struct hp_device *d, struct lba_device *lba_dev)
+lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 {
+	unsigned long bytecnt;
 	pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;	/* PA_VIEW */
-#ifdef DONT_NEED_THIS_FOR_ASTRO
 	pdc_pat_cell_mod_maddr_block_t io_pdc_cell;	/* IO_VIEW */
 	long io_count;
-#endif
 	long status;	/* PDC return status */
 	long pa_count;
 	int i;
 
 	/* return cell module (IO view) */
-	status = pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,
+	status = pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index,
 				PA_VIEW, & pa_pdc_cell);
 	pa_count = pa_pdc_cell.mod[1];
 
-#ifdef DONT_NEED_THIS_FOR_ASTRO
-	status |= pdc_pat_cell_module(& pdc_result, d->pcell_loc, d->mod_index,
-				IO_VIEW, & io_pdc_cell);
+	status |= pdc_pat_cell_module(&bytecnt, pa_dev->pcell_loc, pa_dev->mod_index,
+				IO_VIEW, &io_pdc_cell);
 	io_count = io_pdc_cell.mod[1];
-#endif
 
 	/* We've already done this once for device discovery...*/
-	if (status != PDC_RET_OK) {
+	if (status != PDC_OK) {
 		panic("pdc_pat_cell_module() call failed for LBA!\n");
 	}
 
@@ -1017,10 +1058,11 @@
 			unsigned long type;
 			unsigned long start;
 			unsigned long end;	/* aka finish */
-		} *p;
+		} *p, *io;
 		struct resource *r;
 
 		p = (void *) &(pa_pdc_cell.mod[2+i*3]);
+		io = (void *) &(io_pdc_cell.mod[2+i*3]);
 
 		/* Convert the PAT range data to PCI "struct resource" */
 		switch(p->type & 0xff) {
@@ -1030,9 +1072,9 @@
 			break;
 		case PAT_LMMIO:
 			/* used to fix up pre-initialized MEM BARs */
-			lba_dev->lmmio_base = p->start;
+			lba_dev->hba.lmmio_space_offset = p->start - io->start;
 
-			r = &(lba_dev->hba.mem_space);
+			r = &(lba_dev->hba.lmmio_space);
 			r->name   = "LBA LMMIO";
 			r->start  = p->start;
 			r->end    = p->end;
@@ -1060,8 +1102,8 @@
 
 			r = &(lba_dev->hba.io_space);
 			r->name   = "LBA I/O Port";
-			r->start = lba_dev->hba.hba_num << 16;
-			r->end   = r->start + 0xffffUL;
+			r->start  = HBA_PORT_BASE(lba_dev->hba.hba_num);
+			r->end    = r->start + HBA_PORT_SPACE_SIZE - 1;
 			r->flags  = IORESOURCE_IO;
 			r->parent = r->sibling = r->child = NULL;
 			break;
@@ -1077,17 +1119,22 @@
 
 
 static void
-lba_legacy_resources( struct hp_device *d, struct lba_device *lba_dev)
+lba_legacy_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
 {
-	int lba_num;
 	struct resource *r;
+	unsigned long rsize;
+	int lba_num;
+
 #ifdef __LP64__
 	/*
-	** Used to sign extend instead BAR values are only 32-bit.
-	** 64-bit BARs have the upper 32-bit's zero'd by firmware.
-	** "Sprockets" PDC initializes for 32-bit OS.
+	** Sign extend all BAR values on "legacy" platforms.
+	** "Sprockets" PDC (Forte/Allegro) initializes everything
+	** for "legacy" 32-bit OS (HPUX 10.20).
+	** Upper 32-bits of 64-bit BAR will be zero too.
 	*/
-	lba_dev->lmmio_base = 0xffffffff00000000UL;
+	lba_dev->hba.lmmio_space_offset = 0xffffffff00000000UL;
+#else
+	lba_dev->hba.lmmio_space_offset = 0UL;
 #endif
 
 	/*
@@ -1097,7 +1144,7 @@
 	** PCI bus walk *should* end up with the same result.
 	** FIXME: But we don't have sanity checks in PCI or LBA.
 	*/
-	lba_num = READ_REG32(d->hpa + LBA_FW_SCRATCH);
+	lba_num = READ_REG32(pa_dev->hpa + LBA_FW_SCRATCH);
 	r = &(lba_dev->hba.bus_num);
 	r->name = "LBA PCI Busses";
 	r->start = lba_num & 0xff;
@@ -1106,19 +1153,67 @@
 	/* Set up local PCI Bus resources - we don't really need
 	** them for Legacy boxes but it's nice to see in /proc.
 	*/
-	r = &(lba_dev->hba.mem_space);
+	r = &(lba_dev->hba.lmmio_space);
 	r->name  = "LBA PCI LMMIO";
 	r->flags = IORESOURCE_MEM;
-	r->start = READ_REG32(d->hpa + LBA_LMMIO_BASE);
-	r->end   = r->start + ~ (READ_REG32(d->hpa + LBA_LMMIO_MASK));
+	/* Ignore "Range Enable" bit in the BASE register */
+	r->start = PCI_HOST_ADDR(HBA_DATA(lba_dev),
+		((long) READ_REG32(pa_dev->hpa + LBA_LMMIO_BASE)) & ~1UL);
+	rsize =  ~READ_REG32(pa_dev->hpa + LBA_LMMIO_MASK) + 1;
+
+	/*
+	** Each rope only gets part of the distributed range.
+	** Adjust "window" for this rope
+	*/
+	rsize /= ROPES_PER_SBA;
+	r->start += rsize * LBA_NUM(pa_dev->hpa);
+	r->end = r->start + rsize - 1 ;
+
+	/*
+	** XXX FIXME - ignore LBA_ELMMIO_BASE for now
+	** "Directed" ranges are used when the "distributed range" isn't
+	** sufficient for all devices below a given LBA.  Typically devices
+	** like graphics cards or X25 may need a directed range when the
+	** bus has multiple slots (ie multiple devices) or the device
+	** needs more than the typical 4 or 8MB a distributed range offers.
+	**
+	** The main reason for ignoring it now frigging complications.
+	** Directed ranges may overlap (and have precedence) over
+	** distributed ranges. Ie a distributed range assigned to a unused
+	** rope may be used by a directed range on a different rope.
+	** Support for graphics devices may require fixing this
+	** since they may be assigned a directed range which overlaps
+	** an existing (but unused portion of) distributed range.
+	*/
+	r = &(lba_dev->hba.elmmio_space);
+	r->name  = "extra LBA PCI LMMIO";
+	r->flags = IORESOURCE_MEM;
+	r->start = READ_REG32(pa_dev->hpa + LBA_ELMMIO_BASE);
+	r->end   = 0;
+
+	/* check Range Enable bit */
+	if (r->start & 1) {
+		/* First baby step to getting Direct Ranges listed in /proc.
+		** AFAIK, only Sprockets PDC will setup a directed Range.
+		*/
+
+		r->start &= ~1;
+		r->end    = r->start;
+		r->end   += ~READ_REG32(pa_dev->hpa + LBA_ELMMIO_MASK);
+		printk(KERN_DEBUG "WARNING: Ignoring enabled ELMMIO BASE 0x%0lx  SIZE 0x%lx\n",
+			r->start,
+			r->end + 1);
+
+	}
 
 	r = &(lba_dev->hba.io_space);
 	r->name  = "LBA PCI I/O Ports";
 	r->flags = IORESOURCE_IO;
-	r->start = READ_REG32(d->hpa + LBA_IOS_BASE);
-	r->end   = r->start + (READ_REG32(d->hpa + LBA_IOS_MASK) ^ 0xffff);
+	r->start = READ_REG32(pa_dev->hpa + LBA_IOS_BASE) & ~1L;
+	r->end   = r->start + (READ_REG32(pa_dev->hpa + LBA_IOS_MASK) ^ (HBA_PORT_SPACE_SIZE - 1));
 
-	lba_num = lba_dev->hba.hba_num << 16;
+	/* Virtualize the I/O Port space ranges */
+	lba_num = HBA_PORT_BASE(lba_dev->hba.hba_num);
 	r->start |= lba_num;
 	r->end   |= lba_num;
 }
@@ -1136,29 +1231,92 @@
 **
 **************************************************************************/
 
-static void
+static int __init
 lba_hw_init(struct lba_device *d)
 {
 	u32 stat;
+	u32 bus_reset;	/* PDC_PAT_BUG */
+
+#if 0
+	printk(KERN_DEBUG "LBA %lx  STAT_CTL %Lx  ERROR_CFG %Lx  STATUS %Lx DMA_CTL %Lx\n",
+		d->hba.base_addr,
+		READ_REG64(d->hba.base_addr + LBA_STAT_CTL),
+		READ_REG64(d->hba.base_addr + LBA_ERROR_CONFIG),
+		READ_REG64(d->hba.base_addr + LBA_ERROR_STATUS),
+		READ_REG64(d->hba.base_addr + LBA_DMA_CTL) );
+	printk(KERN_DEBUG "	ARB mask %Lx  pri %Lx  mode %Lx  mtlt %Lx\n",
+		READ_REG64(d->hba.base_addr + LBA_ARB_MASK),
+		READ_REG64(d->hba.base_addr + LBA_ARB_PRI),
+		READ_REG64(d->hba.base_addr + LBA_ARB_MODE),
+		READ_REG64(d->hba.base_addr + LBA_ARB_MTLT) );
+	printk(KERN_DEBUG "	HINT cfg 0x%Lx\n",
+		READ_REG64(d->hba.base_addr + LBA_HINT_CFG));
+	printk(KERN_DEBUG "	HINT reg ");
+	{ int i;
+	for (i=LBA_HINT_BASE; i< (14*8 + LBA_HINT_BASE); i+=8)
+		printk(" %Lx", READ_REG64(d->hba.base_addr + i));
+	}
+	printk("\n");
+#endif	/* DEBUG_LBA_PAT */
+
+#ifdef __LP64__
+#warning FIXME add support for PDC_PAT_IO "Get slot status" - OLAR support
+#endif
+
+	/* PDC_PAT_BUG: exhibited in rev 40.48  on L2000 */
+	bus_reset = READ_REG32(d->hba.base_addr + LBA_STAT_CTL + 4) & 1;
+	if (bus_reset) {
+		printk(KERN_DEBUG "NOTICE: PCI bus reset still asserted! (clearing)\n");
+	}
+
+	stat = READ_REG32(d->hba.base_addr + LBA_ERROR_CONFIG);
+	if (stat & LBA_SMART_MODE) {
+		printk(KERN_DEBUG "NOTICE: LBA in SMART mode! (cleared)\n");
+		stat &= ~LBA_SMART_MODE;
+		WRITE_REG32(stat, d->hba.base_addr + LBA_ERROR_CONFIG);
+	}
 
 	/* Set HF mode as the default (vs. -1 mode). */
         stat = READ_REG32(d->hba.base_addr + LBA_STAT_CTL);
 	WRITE_REG32(stat | HF_ENABLE, d->hba.base_addr + LBA_STAT_CTL);
 
 	/*
+	** Writing a zero to STAT_CTL.rf (bit 0) will clear reset signal
+	** if it's not already set. If we just cleared the PCI Bus Reset
+	** signal, wait a bit for the PCI devices to recover and setup.
+	*/
+	if (bus_reset)
+		mdelay(pci_post_reset_delay);
+
+	if (0 == READ_REG32(d->hba.base_addr + LBA_ARB_MASK)) {
+		/*
+		** PDC_PAT_BUG: PDC rev 40.48 on L2000.
+		** B2000/C3600/J6000 also have this problem?
+		** 
+		** Elroys with hot pluggable slots don't get configured
+		** correctly if the slot is empty.  ARB_MASK is set to 0
+		** and we can't master transactions on the bus if it's
+		** not at least one. 0x3 enables elroy and first slot.
+		*/
+		printk(KERN_DEBUG "NOTICE: Enabling PCI Arbitration\n");
+		WRITE_REG32(0x3, d->hba.base_addr + LBA_ARB_MASK);
+	}
+
+	/*
 	** FIXME: Hint registers are programmed with default hint
 	** values by firmware. Hints should be sane even if we
 	** can't reprogram them the way drivers want.
 	*/
+	return 0;
 }
 
 
 
-static void
+static void __init
 lba_common_init(struct lba_device *lba_dev)
 {
 	pci_bios = &lba_bios_ops;
-	pcibios_register_hba((struct pci_hba_data *)lba_dev);
+	pcibios_register_hba(HBA_DATA(lba_dev));
 	lba_dev->lba_lock = SPIN_LOCK_UNLOCKED;	
 
 	/*
@@ -1176,32 +1334,31 @@
 ** If so, initialize the chip and tell other partners in crime they
 ** have work to do.
 */
-static __init int
-lba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+static int __init
+lba_driver_callback(struct parisc_device *dev)
 {
 	struct lba_device *lba_dev;
 	struct pci_bus *lba_bus;
 	u32 func_class;
 	void *tmp_obj;
-
-	/* from drivers/pci/setup-bus.c */
-	extern void __init pbus_set_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
+	char *version;
 
 	/* Read HW Rev First */
-	func_class = READ_REG32(d->hpa + LBA_FCLASS);
+	func_class = READ_REG32(dev->hpa + LBA_FCLASS);
 	func_class &= 0xf;
 
 	switch (func_class) {
-	case 0:	dri->version = "TR1.0"; break;
-	case 1:	dri->version = "TR2.0"; break;
-	case 2:	dri->version = "TR2.1"; break;
-	case 3:	dri->version = "TR2.2"; break;
-	case 4:	dri->version = "TR3.0"; break;
-	case 5:	dri->version = "TR4.0"; break;
-	default: dri->version = "TR4+";
+	case 0:	version = "TR1.0"; break;
+	case 1:	version = "TR2.0"; break;
+	case 2:	version = "TR2.1"; break;
+	case 3:	version = "TR2.2"; break;
+	case 4:	version = "TR3.0"; break;
+	case 5:	version = "TR4.0"; break;
+	default: version = "TR4+";
 	}
 
-	printk("%s version %s (0x%x) found at 0x%p\n", dri->name, dri->version, func_class & 0xf, d->hpa);
+	printk(KERN_INFO "%s version %s (0x%x) found at 0x%lx\n",
+		MODULE_NAME, version, func_class & 0xf, dev->hpa);
 
 	/* Just in case we find some prototypes... */
 	if (func_class < 2) {
@@ -1212,22 +1369,16 @@
 	/*
 	** Tell I/O SAPIC driver we have a IRQ handler/region.
 	*/
-	tmp_obj = iosapic_register(d->hpa+LBA_IOSAPIC_BASE);
-	if (NULL == tmp_obj) {
-		/* iosapic may have failed. But more likely the
-		** slot isn't occupied and thus has no IRT entries.
-		** iosapic_register looks for this iosapic in the IRT
-		** before bothering to allocating data structures
-		** we don't need.
-		*/
-		DBG(KERN_WARNING MODULE_NAME ": iosapic_register says not used\n");
-		return (1);
-	}
+	tmp_obj = iosapic_register(dev->hpa + LBA_IOSAPIC_BASE);
 
+	/* NOTE: PCI devices (e.g. 103c:1005 graphics card) which don't
+	**	have an IRT entry will get NULL back from iosapic code.
+	*/
+	
 	lba_dev = kmalloc(sizeof(struct lba_device), GFP_KERNEL);
 	if (NULL == lba_dev)
 	{
-		printk("lba_init_chip - couldn't alloc lba_device\n");
+		printk(KERN_ERR "lba_init_chip - couldn't alloc lba_device\n");
 		return(1);
 	}
 
@@ -1242,48 +1393,45 @@
 	*/
 	lba_dev->hw_rev = func_class;
 
-	lba_dev->hba.base_addr = d->hpa;  /* faster access */
+	lba_dev->hba.base_addr = dev->hpa;  /* faster access */
+	lba_dev->hba.dev = dev;
 	lba_dev->iosapic_obj = tmp_obj;  /* save interrupt handle */
+	lba_dev->hba.iommu = sba_get_iommu(dev);  /* get iommu data */
 
 	/* ------------ Second : initialize common stuff ---------- */
 	lba_common_init(lba_dev);
-	lba_hw_init(lba_dev);
+
+	if (lba_hw_init(lba_dev))
+		return(1);
 
 	/* ---------- Third : setup I/O Port and MMIO resources  --------- */
-#ifdef __LP64__
 
-	if (pdc_pat) {
+#ifdef __LP64__
+	if (is_pdc_pat()) {
 		/* PDC PAT firmware uses PIOP region of GMMIO space. */
 		pci_port = &lba_pat_port_ops;
 
 		/* Go ask PDC PAT what resources this LBA has */
-		lba_pat_resources(d, lba_dev);
-
-	} else {
+		lba_pat_resources(dev, lba_dev);
+	} else
 #endif
+	{
 		/* Sprockets PDC uses NPIOP region */
 		pci_port = &lba_astro_port_ops;
 
 		/* Poke the chip a bit for /proc output */
-		lba_legacy_resources(d, lba_dev);
-#ifdef __LP64__
+		lba_legacy_resources(dev, lba_dev);
 	}
-#endif
 
 	/* 
 	** Tell PCI support another PCI bus was found.
 	** Walks PCI bus for us too.
 	*/
 	lba_bus = lba_dev->hba.hba_bus =
-		pci_scan_bus( lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev);
+		pci_scan_bus(lba_dev->hba.bus_num.start, &lba_cfg_ops, (void *) lba_dev);
 
 #ifdef __LP64__
-	if (pdc_pat) {
-
-		/* determine window sizes needed by PCI-PCI bridges */
-		DBG_PAT("LBA pcibios_size_bridge()\n");
-		pcibios_size_bridge(lba_bus, NULL);
-
+	if (is_pdc_pat()) {
 		/* assign resources to un-initialized devices */
 		DBG_PAT("LBA pcibios_assign_unassigned_resources()\n");
 		pcibios_assign_unassigned_resources(lba_bus);
@@ -1292,14 +1440,10 @@
 		DBG_PAT("\nLBA PIOP resource tree\n");
 		lba_dump_res(&lba_dev->hba.io_space, 2);
 		DBG_PAT("\nLBA LMMIO resource tree\n");
-		lba_dump_res(&lba_dev->hba.mem_space, 2);
+		lba_dump_res(&lba_dev->hba.lmmio_space, 2);
 #endif
-
-		/* program *all* PCI-PCI bridge range registers */
-		DBG_PAT("LBA pbus_set_ranges()\n");
-		pbus_set_ranges(lba_bus, NULL);
 	}
-#endif /* __LP64__ */
+#endif
 
 	/*
 	** Once PCI register ops has walked the bus, access to config
@@ -1314,33 +1458,43 @@
 	return 0;
 }
 
+static struct parisc_device_id lba_tbl[] = {
+	{ HPHW_BRIDGE, HVERSION_REV_ANY_ID, 0x782, 0xa },
+	{ 0, }
+};
+
+static struct parisc_driver lba_driver = {
+	name:		MODULE_NAME,
+	id_table:	lba_tbl,
+	probe:		lba_driver_callback
+};
+
+/*
+** One time initialization to let the world know the LBA was found.
+** Must be called exactly once before pci_init().
+*/
+void __init lba_init(void)
+{
+	register_parisc_driver(&lba_driver);
+}
 
 /*
 ** Initialize the IBASE/IMASK registers for LBA (Elroy).
-** Only called from sba_iommu.c initialization sequence.
+** Only called from sba_iommu.c in order to route ranges (MMIO vs DMA).
+** sba_iommu is responsible for locking (none needed at init time).
 */
-void lba_init_iregs(void *sba_hpa, u32 ibase, u32 imask)
+void
+lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask)
 {
-	extern struct pci_hba_data *hba_list;	/* arch/parisc/kernel/pci.c */
-	struct pci_hba_data *lba;
+	unsigned long base_addr = lba->hpa;
 
 	imask <<= 2;	/* adjust for hints - 2 more bits */
 
 	ASSERT((ibase & 0x003fffff) == 0);
 	ASSERT((imask & 0x003fffff) == 0);
 	
-	/* FIXME: sba_hpa is intended to search some table to
-	**      determine which LBA's belong to the caller's SBA.
-	** IS_ASTRO: just assume only one SBA for now.
-	*/
-	ASSERT(NULL != hba_list);
-	DBG(KERN_DEBUG "%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);
-
-	for (lba = hba_list; NULL != lba; lba = lba->next) {
-		DBG(KERN_DEBUG "%s() base_addr %p\n", __FUNCTION__, lba->base_addr);
-		WRITE_REG32( imask, lba->base_addr + LBA_IMASK);
-		WRITE_REG32( ibase, lba->base_addr + LBA_IBASE);
-	}
-	DBG(KERN_DEBUG "%s() done\n", __FUNCTION__);
+	DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask);
+	WRITE_REG32( imask, base_addr + LBA_IMASK);
+	WRITE_REG32( ibase, base_addr + LBA_IBASE);
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/led.c linux/arch/parisc/kernel/led.c
--- linux.orig/arch/parisc/kernel/led.c	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/kernel/led.c	2002-08-12 22:14:13.000000000 +0000
@@ -3,34 +3,64 @@
  *
  *      (c) Copyright 2000 Red Hat Software
  *      (c) Copyright 2000 Helge Deller <hdeller@redhat.com>
+ *      (c) Copyright 2001-2002 Helge Deller <deller@gmx.de>
+ *      (c) Copyright 2001 Randolph Chung <tausq@debian.org>
  *
  *      This program is free software; you can redistribute it and/or modify
  *      it under the terms of the GNU General Public License as published by
  *      the Free Software Foundation; either version 2 of the License, or
  *      (at your option) any later version.
  *
+ * TODO:
+ *	- speed-up calculations with inlined assembler
+ *	- interface to write to second row of LCD from /proc
  */
 
 #include <linux/config.h>
+#include <linux/module.h>
+#include <linux/stddef.h>	/* for offsetof() */
 #include <linux/init.h>
-#include <linux/kernel_stat.h>
 #include <linux/types.h>
-#include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/bitops.h>
+#include <linux/version.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/reboot.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
 #include <asm/io.h>
 #include <asm/gsc.h>
 #include <asm/processor.h>
 #include <asm/hardware.h>
 #include <asm/param.h>		/* HZ */
 #include <asm/led.h>
+#include <asm/pdc.h>
+#include <asm/uaccess.h>
 
+/* The control of the LEDs and LCDs on PARISC-machines have to be done 
+   completely in software. The necessary calculations are done in a tasklet
+   which is scheduled at every timer interrupt and since the calculations 
+   may consume relatively much CPU-time some of the calculations can be 
+   turned off with the following variables (controlled via procfs) */
+
+static int led_type = -1;
+static int led_heartbeat = 1;
+static int led_diskio = 1;
+static int led_lanrxtx = 1;
+static char lcd_text[32];
 
-/* define to disable all LED functions */
-#undef  DISABLE_LEDS
+#if 0
+#define DPRINTK(x)	printk x
+#else
+#define DPRINTK(x)
+#endif
 
 
-#define CPU_HVERSION ((boot_cpu_data.hversion >> 4) & 0x0FFF)
+#define CALC_ADD(val, comp, add) \
+ (val<=(comp/8) ? add/16 : val<=(comp/4) ? add/8 : val<=(comp/2) ? add/4 : add)
 
 
 struct lcd_block {
@@ -40,8 +70,10 @@
 };
 
 /* Structure returned by PDC_RETURN_CHASSIS_INFO */
+/* NOTE: we use unsigned long:16 two times, since the following member 
+   lcd_cmd_reg_addr needs to be 64bit aligned on 64bit PA2.0-machines */
 struct pdc_chassis_lcd_info_ret_block {
-	unsigned long model:16;		/* DISPLAY_MODEL_XXXX (see below)  */
+	unsigned long model:16;		/* DISPLAY_MODEL_XXXX */
 	unsigned long lcd_width:16;	/* width of the LCD in chars (DISPLAY_MODEL_LCD only) */
 	char *lcd_cmd_reg_addr;		/* ptr to LCD cmd-register & data ptr for LED */
 	char *lcd_data_reg_addr;	/* ptr to LCD data-register (LCD only) */
@@ -56,33 +88,23 @@
 	char _pad;
 };
 
-/* values for pdc_chassis_lcd_info_ret_block.model: */
-#define DISPLAY_MODEL_LCD  0	/* KittyHawk LED or LCD */
-#define DISPLAY_MODEL_NONE 1	/* no LED or LCD */
-#define DISPLAY_MODEL_LASI 2	/* LASI style 8 bit LED */
-#define DISPLAY_MODEL_OLD_ASP 0x7F /* faked: ASP style 8 x 1 bit LED (only very old ASP versions) */
-
 
 /* LCD_CMD and LCD_DATA for KittyHawk machines */
-#ifdef __LP64__
-#define KITTYHAWK_LCD_CMD 0xfffffffff0190000L
-#else
-#define KITTYHAWK_LCD_CMD 0xf0190000
-#endif
-#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD + 1)
+#define KITTYHAWK_LCD_CMD  (0xfffffffff0190000UL) /* 64bit-ready */
+#define KITTYHAWK_LCD_DATA (KITTYHAWK_LCD_CMD+1)
 
-
-/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's */
+/* lcd_info is pre-initialized to the values needed to program KittyHawk LCD's 
+ * HP seems to have used Sharp/Hitachi HD44780 LCDs most of the time. */
 static struct pdc_chassis_lcd_info_ret_block
 lcd_info __attribute__((aligned(8))) =
 {
-      model:DISPLAY_MODEL_LCD,
-      lcd_width:16,
-      lcd_cmd_reg_addr:(char *) KITTYHAWK_LCD_CMD,
+      model:		DISPLAY_MODEL_LCD,
+      lcd_width:	16,
+      lcd_cmd_reg_addr:	(char *) KITTYHAWK_LCD_CMD,
       lcd_data_reg_addr:(char *) KITTYHAWK_LCD_DATA,
-      min_cmd_delay:40,
-      reset_cmd1:0x80,
-      reset_cmd2:0xc0,
+      min_cmd_delay:	40,
+      reset_cmd1:	0x80,
+      reset_cmd2:	0xc0,
 };
 
 
@@ -92,7 +114,143 @@
 #define LED_DATA_REG	lcd_info.lcd_cmd_reg_addr	/* LASI & ASP only */
 
 
+/* ptr to LCD/LED-specific function */
+static void (*led_func_ptr) (unsigned char);
+
+#define LED_HASLCD 1
+#define LED_NOLCD  0
+#ifdef CONFIG_PROC_FS
+static int led_proc_read(char *page, char **start, off_t off, int count, 
+	int *eof, void *data)
+{
+	char *out = page;
+	int len;
+
+	switch ((long)data)
+	{
+	case LED_NOLCD:
+		out += sprintf(out, "Heartbeat: %d\n", led_heartbeat);
+		out += sprintf(out, "Disk IO: %d\n", led_diskio);
+		out += sprintf(out, "LAN Rx/Tx: %d\n", led_lanrxtx);
+		break;
+	case LED_HASLCD:
+		out += sprintf(out, "%s\n", lcd_text);
+		break;
+	default:
+		*eof = 1;
+		return 0;
+	}
+
+	len = out - page - off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0) return 0;
+	} else {
+		len = count;
+	}
+	*start = page + off;
+	return len;
+}
+
+static int led_proc_write(struct file *file, const char *buf, 
+	unsigned long count, void *data)
+{
+	char *cur, lbuf[count];
+	int d;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	memset(lbuf, 0, count);
+
+	copy_from_user(lbuf, buf, count);
+	cur = lbuf;
+
+	/* skip initial spaces */
+	while (*cur && isspace(*cur))
+	{
+		cur++;
+	}
+
+	switch ((long)data)
+	{
+	case LED_NOLCD:
+		d = *cur++ - '0';
+		if (d != 0 && d != 1) goto parse_error;
+		led_heartbeat = d;
+
+		if (*cur++ != ' ') goto parse_error;
+
+		d = *cur++ - '0';
+		if (d != 0 && d != 1) goto parse_error;
+		led_diskio = d;
+
+		if (*cur++ != ' ') goto parse_error;
+
+		d = *cur++ - '0';
+		if (d != 0 && d != 1) goto parse_error;
+		led_lanrxtx = d;
+
+		break;
+	case LED_HASLCD:
+		if (*cur == 0) 
+		{
+			/* reset to default */
+			lcd_print("Linux " UTS_RELEASE);
+		}
+		else
+		{
+			/* chop off trailing \n.. if the user gives multiple
+			 * \n then it's all their fault.. */
+			if (*cur && cur[strlen(cur)-1] == '\n')
+				cur[strlen(cur)-1] = 0;
+			lcd_print(cur);
+		}
+		break;
+	default:
+		return 0;
+	}
+	
+	return count;
+
+parse_error:
+	if ((long)data == LED_NOLCD)
+		printk(KERN_CRIT "Parse error: expect \"n n n\" (n == 0 or 1) for heartbeat,\ndisk io and lan tx/rx indicators\n");
+	return -EINVAL;
+}
+
+static int __init led_create_procfs(void)
+{
+	struct proc_dir_entry *proc_pdc_root = NULL;
+	struct proc_dir_entry *ent;
+
+	if (led_type == -1) return -1;
+
+	proc_pdc_root = proc_mkdir("pdc", 0);
+	if (!proc_pdc_root) return -1;
+	proc_pdc_root->owner = THIS_MODULE;
+	ent = create_proc_entry("led", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
+	if (!ent) return -1;
+	ent->nlink = 1;
+	ent->data = (void *)LED_NOLCD; /* LED */
+	ent->read_proc = led_proc_read;
+	ent->write_proc = led_proc_write;
+	ent->owner = THIS_MODULE;
+
+	if (led_type == LED_HASLCD)
+	{
+		ent = create_proc_entry("lcd", S_IFREG|S_IRUGO|S_IWUSR, proc_pdc_root);
+		if (!ent) return -1;
+		ent->nlink = 1;
+		ent->data = (void *)LED_HASLCD; /* LCD */
+		ent->read_proc = led_proc_read;
+		ent->write_proc = led_proc_write;
+		ent->owner = THIS_MODULE;
+	}
 
+	return 0;
+}
+#endif
 
 /*
    ** 
@@ -132,24 +290,20 @@
    ** 
    ** led_LCD_driver()
    ** 
-   ** The logic of the LCD driver is, that we write at every interrupt
+   ** The logic of the LCD driver is, that we write at every scheduled call
    ** only to one of LCD_CMD_REG _or_ LCD_DATA_REG - registers.
-   ** That way we don't need to let this interrupt routine busywait
-   ** the "min_cmd_delay", since idlewaiting in an interrupt-routine is
-   ** allways a BAD IDEA !
+   ** That way we don't need to let this tasklet busywait for min_cmd_delay
+   ** milliseconds.
    **
    ** TODO: check the value of "min_cmd_delay" against the value of HZ.
    **   
  */
-
 static void led_LCD_driver(unsigned char leds)
 {
 	static int last_index;	/* 0:heartbeat, 1:disk, 2:lan_in, 3:lan_out */
 	static int last_was_cmd;/* 0: CMD was written last, 1: DATA was last */
 	struct lcd_block *block_ptr;
 	int value;
-	
- 	// leds = ~leds;	/* needed ? */ 
 
 	switch (last_index) {
 	    case 0:	block_ptr = &lcd_info.heartbeat;
@@ -165,7 +319,6 @@
 			value = leds & LED_LAN_TX;
 			break;
 	    default:	/* should never happen: */
-			BUG();
 			return;
 	}
 
@@ -178,179 +331,293 @@
 	}    
 	
 	/* now update the vars for the next interrupt iteration */ 
-	if (++last_was_cmd == 2) {
+	if (++last_was_cmd == 2) { /* switch between cmd & data */
 	    last_was_cmd = 0;
-	    if (++last_index == 4)
-		last_index = 0;
+	    if (++last_index == 4) 
+		last_index = 0;	 /* switch back to heartbeat index */
 	}
 }
 
 
+/*
+   ** 
+   ** led_get_net_stats()
+   ** 
+   ** calculate the TX- & RX-troughput on the network interfaces in
+   ** the system for usage in the LED code
+   **
+   ** (analog to dev_get_info() from net/core/dev.c)
+   **   
+ */
+static unsigned long led_net_rx_counter, led_net_tx_counter;
+
+static void led_get_net_stats(int addvalue)
+{
+	static unsigned long rx_total_last, tx_total_last;
+	unsigned long rx_total, tx_total;
+	struct net_device *dev;
+	struct net_device_stats *stats;
+
+	rx_total = tx_total = 0;
+	
+	/* we are running as a tasklet, so locking dev_base 
+	 * for reading should be OK */
+	read_lock(&dev_base_lock);
+	for (dev = dev_base; dev != NULL; dev = dev->next) {
+	    if (dev->get_stats) { 
+	        stats = dev->get_stats(dev);
+		rx_total += stats->rx_packets;
+		tx_total += stats->tx_packets;
+	    }
+	}
+	read_unlock(&dev_base_lock);
 
-static char currentleds;	/* stores current value of the LEDs */
+	rx_total -= rx_total_last;
+	tx_total -= tx_total_last;
+	
+	if (rx_total)
+	    led_net_rx_counter += CALC_ADD(rx_total, tx_total, addvalue);
+
+	if (tx_total)
+	    led_net_tx_counter += CALC_ADD(tx_total, rx_total, addvalue);
+        
+	rx_total_last += rx_total;
+        tx_total_last += tx_total;
+}
 
-static void (*led_func_ptr) (unsigned char); /* ptr to LCD/LED-specific function */
 
 /*
-   ** led_interrupt_func()
    ** 
-   ** is called at every timer interrupt from time.c,
+   ** led_get_diskio_stats()
+   ** 
+   ** calculate the disk-io througput in the system
+   ** (analog to linux/fs/proc/proc_misc.c)
+   **   
+ */
+static unsigned long led_diskio_counter;
+
+static void led_get_diskio_stats(int addvalue)
+{	
+	static unsigned int diskio_total_last, diskio_max;
+	int major, disk, total;
+	
+	total = 0;
+	for (major = 0; major < DK_MAX_MAJOR; major++) {
+	    for (disk = 0; disk < DK_MAX_DISK; disk++)
+		total += kstat.dk_drive[major][disk];
+	}
+	total -= diskio_total_last;
+	
+	if (total) {
+	    if (total >= diskio_max) {
+		led_diskio_counter += addvalue;
+	        diskio_max = total; /* new maximum value found */ 
+	    } else
+		led_diskio_counter += CALC_ADD(total, diskio_max, addvalue);
+	}
+	
+	diskio_total_last += total; 
+}
+
+
+
+/*
+   ** led_tasklet_func()
+   ** 
+   ** is scheduled at every timer interrupt from time.c and
    ** updates the chassis LCD/LED 
+
+    TODO:
+    - display load average (older machines like 715/64 have 4 "free" LED's for that)
+    - optimizations
  */
 
-#define HEARTBEAT_LEN	(HZ/16)
+static unsigned char currentleds;	/* stores current value of the LEDs */
+
+#define HEARTBEAT_LEN (HZ*6/100)
+#define HEARTBEAT_2ND_RANGE_START (HZ*22/100)
+#define HEARTBEAT_2ND_RANGE_END   (HEARTBEAT_2ND_RANGE_START + HEARTBEAT_LEN)
 
-void led_interrupt_func(void)
+static void led_tasklet_func(unsigned long unused)
 {
-#ifndef DISABLE_LEDS
-	static int count;
-	static int lastleds = -1;
-	static int nr;
+	static unsigned int count, count_HZ;
+	static unsigned char lastleds;
 
-	/* exit, if not initialized */
+	/* exit if not initialized */
 	if (!led_func_ptr)
 	    return;
-	
-	/* increment the local counter */
-	if (count == (HZ-1))
-	    count = 0;
-	else
-	    count++;
 
-	/* calculate the Heartbeat */
-	if ((count % (HZ/2)) < HEARTBEAT_LEN) 
-	    currentleds |= LED_HEARTBEAT;
-	else
-	    currentleds &= ~LED_HEARTBEAT;
+	/* increment the local counters */
+	++count;
+	if (++count_HZ == HZ)
+	    count_HZ = 0;
+
+	if (led_heartbeat)
+	{
+		/* flash heartbeat-LED like a real heart (2 x short then a long delay) */
+		if (count_HZ<HEARTBEAT_LEN || 
+		    (count_HZ>=HEARTBEAT_2ND_RANGE_START && count_HZ<HEARTBEAT_2ND_RANGE_END)) 
+		    currentleds |= LED_HEARTBEAT;
+		else
+		    currentleds &= ~LED_HEARTBEAT;
+	}
+
+	/* gather network and diskio statistics and flash LEDs respectively */
+
+	if (led_lanrxtx)
+	{
+		if ((count & 31) == 0)
+			led_get_net_stats(30);
+
+		if (led_net_rx_counter) {
+			led_net_rx_counter--;
+			currentleds |= LED_LAN_RCV;
+		}
+		else    
+			currentleds &= ~LED_LAN_RCV;
+
+		if (led_net_tx_counter) {
+			led_net_tx_counter--;
+			currentleds |= LED_LAN_TX;
+		}
+		else    
+			currentleds &= ~LED_LAN_TX;
+	}
 
-	/* roll LEDs 0..2 */
-	if (count == 0) {
-	    if (nr++ >= 2) 
-		nr = 0;
-	    currentleds &= ~7;
-	    currentleds |= (1 << nr);
+	if (led_diskio)
+	{
+		/* avoid to calculate diskio-stats at same irq as netio-stats ! */
+		if ((count & 31) == 15) 
+			led_get_diskio_stats(30);
+
+		if (led_diskio_counter) {
+			led_diskio_counter--;
+			currentleds |= LED_DISK_IO;
+		}
+		else    
+			currentleds &= ~LED_DISK_IO;
 	}
 
-	/* now update the LEDs */
+	/* update the LCD/LEDs */
 	if (currentleds != lastleds) {
 	    led_func_ptr(currentleds);
 	    lastleds = currentleds;
 	}
-#endif
 }
 
+/* main led tasklet struct (scheduled from time.c) */
+DECLARE_TASKLET_DISABLED(led_tasklet, led_tasklet_func, 0);
+
+
+/*
+   ** led_halt()
+   ** 
+   ** called by the reboot notifier chain at shutdown and stops all
+   ** LED/LCD activities.
+   ** 
+ */
+
+static int led_halt(struct notifier_block *, unsigned long, void *);
+
+static struct notifier_block led_notifier = {
+	notifier_call: led_halt,
+};
+
+static int led_halt(struct notifier_block *nb, unsigned long event, void *buf) 
+{
+	char *txt;
+	
+	switch (event) {
+	case SYS_RESTART:	txt = "SYSTEM RESTART";
+				break;
+	case SYS_HALT:		txt = "SYSTEM HALT";
+				break;
+	case SYS_POWER_OFF:	txt = "SYSTEM POWER OFF";
+				break;
+	default:		return NOTIFY_DONE;
+	}
+	
+	/* completely stop the LED/LCD tasklet */
+	tasklet_disable(&led_tasklet);
+
+	if (lcd_info.model == DISPLAY_MODEL_LCD)
+		lcd_print(txt);
+	else
+		if (led_func_ptr)
+			led_func_ptr(0xff); /* turn all LEDs ON */
+	
+	unregister_reboot_notifier(&led_notifier);
+	return NOTIFY_OK;
+}
 
 /*
    ** register_led_driver()
    ** 
-   ** All information in lcd_info needs to be set up prior
-   ** calling this function. 
+   ** registers an external LED or LCD for usage by this driver.
+   ** currently only LCD-, LASI- and ASP-style LCD/LED's are supported.
+   ** 
  */
 
-static void __init register_led_driver(void)
+int __init register_led_driver(int model, char *cmd_reg, char *data_reg)
 {
-#ifndef DISABLE_LEDS
+	static int initialized;
+	
+	if (initialized || !data_reg)
+	    return 1;
+	
+	lcd_info.model = model;		/* store the values */
+	LCD_CMD_REG = (cmd_reg == LED_CMD_REG_NONE) ? NULL : cmd_reg;
+
 	switch (lcd_info.model) {
 	case DISPLAY_MODEL_LCD:
-		printk(KERN_INFO "LCD display at (%p,%p)\n",
-		  LCD_CMD_REG , LCD_DATA_REG);
+		LCD_DATA_REG = data_reg;
+		printk(KERN_INFO "LCD display at %p,%p registered\n", 
+			LCD_CMD_REG , LCD_DATA_REG);
 		led_func_ptr = led_LCD_driver;
+		lcd_print( "Linux " UTS_RELEASE );
+		led_type = LED_HASLCD;
 		break;
 
 	case DISPLAY_MODEL_LASI:
-		printk(KERN_INFO "LED display at %p\n",
-		       LED_DATA_REG);
+		LED_DATA_REG = data_reg;
 		led_func_ptr = led_LASI_driver;
+		printk(KERN_INFO "LED display at %p registered\n", LED_DATA_REG);
+		led_type = LED_NOLCD;
 		break;
 
 	case DISPLAY_MODEL_OLD_ASP:
-		printk(KERN_INFO "LED (ASP-style) display at %p\n",
-		       LED_DATA_REG);
+		LED_DATA_REG = data_reg;
 		led_func_ptr = led_ASP_driver;
+		printk(KERN_INFO "LED (ASP-style) display at %p registered\n", 
+		    LED_DATA_REG);
+		led_type = LED_NOLCD;
 		break;
 
 	default:
 		printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n",
 		       __FUNCTION__, lcd_info.model);
-		return;
+		return 1;
 	}
-#endif
-}
-
-/*
- * XXX - could this move to lasi.c ??
- */
-
-/*
-   ** lasi_led_init()
-   ** 
-   ** lasi_led_init() is called from lasi.c with the base hpa  
-   ** of the lasi controller chip. 
-   ** Since Mirage and Electra machines use a different LED
-   ** address register, we need to check for these machines 
-   ** explicitly.
- */
-
-#ifdef CONFIG_GSC_LASI
-void __init lasi_led_init(unsigned long lasi_hpa)
-{
-	if (lcd_info.model != DISPLAY_MODEL_NONE ||
-	    lasi_hpa == 0)
-		return;
-
-	printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION);
-
-	/* Mirage and Electra machines need special offsets */
-	switch (CPU_HVERSION) {
-	case 0x60A:		/* Mirage Jr (715/64) */
-	case 0x60B:		/* Mirage 100 */
-	case 0x60C:		/* Mirage 100+ */
-	case 0x60D:		/* Electra 100 */
-	case 0x60E:		/* Electra 120 */
-		LED_DATA_REG = (char *) (lasi_hpa - 0x00020000);
-		break;
-	default:
-		LED_DATA_REG = (char *) (lasi_hpa + 0x0000C000);
-		break;
-	}			/* switch() */
-
-	lcd_info.model = DISPLAY_MODEL_LASI;
-	register_led_driver();
-}
-#endif
-
-
-/*
-   ** asp_led_init()
-   ** 
-   ** asp_led_init() is called from asp.c with the ptr 
-   ** to the LED display.
- */
-
-#ifdef CONFIG_GSC_LASI
-void __init asp_led_init(unsigned long led_ptr)
-{
-	if (lcd_info.model != DISPLAY_MODEL_NONE ||
-	    led_ptr == 0)
-		return;
-
-	lcd_info.model = DISPLAY_MODEL_OLD_ASP;
-	LED_DATA_REG = (char *) led_ptr;
+	
+	/* mark the LCD/LED driver now as initialized and 
+	 * register to the reboot notifier chain */
+	initialized++;
+	register_reboot_notifier(&led_notifier);
 
-	register_led_driver();
+	/* start the led tasklet for the first time */
+	tasklet_enable(&led_tasklet);
+	
+	return 0;
 }
 
-#endif
-
-
-
 /*
    ** register_led_regions()
    ** 
-   ** Simple function, which registers the LCD/LED regions for /procfs.
+   ** register_led_regions() registers the LCD/LED regions for /procfs.
    ** At bootup - where the initialisation of the LCD/LED normally happens - 
    ** not all internal structures of request_region() are properly set up,
-   ** so that we delay the registration until busdevice.c is executed.
+   ** so that we delay the led-registration until after busdevices_init() 
+   ** has been executed.
    **
  */
 
@@ -358,17 +625,57 @@
 {
 	switch (lcd_info.model) {
 	case DISPLAY_MODEL_LCD:
-		request_region((unsigned long)LCD_CMD_REG,  1, "lcd_cmd");
-		request_region((unsigned long)LCD_DATA_REG, 1, "lcd_data");
+		request_mem_region((unsigned long)LCD_CMD_REG,  1, "lcd_cmd");
+		request_mem_region((unsigned long)LCD_DATA_REG, 1, "lcd_data");
 		break;
 	case DISPLAY_MODEL_LASI:
 	case DISPLAY_MODEL_OLD_ASP:
-		request_region((unsigned long)LED_DATA_REG, 1, "led_data");
+		request_mem_region((unsigned long)LED_DATA_REG, 1, "led_data");
 		break;
 	}
 }
 
 
+/*
+   ** 
+   ** lcd_print()
+   ** 
+   ** Displays the given string on the LCD-Display of newer machines.
+   ** lcd_print() disables the timer-based led tasklet during its 
+   ** execution and enables it afterwards again.
+   **
+ */
+int lcd_print( char *str )
+{
+	int i;
+
+	if (!led_func_ptr || lcd_info.model != DISPLAY_MODEL_LCD)
+	    return 0;
+	
+	/* temporarily disable the led tasklet */
+	tasklet_disable(&led_tasklet);
+
+	/* copy display string to buffer for procfs */
+	strncpy(lcd_text, str, sizeof(lcd_text)-1);
+	
+	/* Set LCD Cursor to 1st character */
+	gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);
+	udelay(lcd_info.min_cmd_delay);
+
+	/* Print the string */
+	for (i=0; i < lcd_info.lcd_width; i++) {
+	    if (str && *str)
+		gsc_writeb(*str++, LCD_DATA_REG);
+	    else
+		gsc_writeb(' ', LCD_DATA_REG);
+	    udelay(lcd_info.min_cmd_delay);
+	}
+	
+	/* re-enable the led tasklet */
+	tasklet_enable(&led_tasklet);
+
+	return lcd_info.lcd_width;
+}
 
 /*
    ** led_init()
@@ -384,10 +691,8 @@
 
 int __init led_init(void)
 {
-#ifndef DISABLE_LEDS
-	long pdc_result[32];
-
-	printk("%s: CPU_HVERSION %x\n", __FUNCTION__, CPU_HVERSION);
+	struct pdc_chassis_info chassis_info;
+	int ret;
 
 	/* Work around the buggy PDC of KittyHawk-machines */
 	switch (CPU_HVERSION) {
@@ -396,56 +701,74 @@
 	case 0x582:		/* KittyHawk DC3 100 (K400) */
 	case 0x583:		/* KittyHawk DC3 120 (K410) */
 	case 0x58B:		/* KittyHawk DC2 100 (K200) */
-		printk("%s: KittyHawk-Machine found !!\n", __FUNCTION__);
+		printk(KERN_INFO "%s: KittyHawk-Machine (hversion 0x%x) found, "
+				"LED detection skipped.\n", __FILE__, CPU_HVERSION);
 		goto found;	/* use the preinitialized values of lcd_info */
-
-	default:
-		break;
 	}
 
-	/* initialize pdc_result, so we can check the return values of pdc_chassis_info() */
-	pdc_result[0] = pdc_result[1] = 0;
-
-	if (pdc_chassis_info(&pdc_result, &lcd_info, sizeof(lcd_info)) == PDC_OK) {
-		printk("%s: chassis info: model %d, ret0=%d, ret1=%d\n",
-		 __FUNCTION__, lcd_info.model, pdc_result[0], pdc_result[1]);
+	/* initialize the struct, so that we can check for valid return values */
+	lcd_info.model = DISPLAY_MODEL_NONE;
+	chassis_info.actcnt = chassis_info.maxcnt = 0;
 
+	if ((ret = pdc_chassis_info(&chassis_info, &lcd_info, sizeof(lcd_info))) == PDC_OK) {
+		DPRINTK((KERN_INFO "%s: chassis info: model=%d (%s), "
+			 "lcd_width=%d, cmd_delay=%u,\n"
+			 "%s: sizecnt=%d, actcnt=%ld, maxcnt=%ld\n",
+		         __FILE__, lcd_info.model,
+			 (lcd_info.model==DISPLAY_MODEL_LCD) ? "LCD" :
+			  (lcd_info.model==DISPLAY_MODEL_LASI) ? "LED" : "unknown",
+			 lcd_info.lcd_width, lcd_info.min_cmd_delay,
+			 __FILE__, sizeof(lcd_info), 
+			 chassis_info.actcnt, chassis_info.maxcnt));
+		DPRINTK((KERN_INFO "%s: cmd=%p, data=%p, reset1=%x, reset2=%x, act_enable=%d\n",
+			__FILE__, lcd_info.lcd_cmd_reg_addr, 
+			lcd_info.lcd_data_reg_addr, lcd_info.reset_cmd1,  
+			lcd_info.reset_cmd2, lcd_info.act_enable ));
+	
 		/* check the results. Some machines have a buggy PDC */
-		if (pdc_result[0] <= 0 || pdc_result[0] != pdc_result[1])
+		if (chassis_info.actcnt <= 0 || chassis_info.actcnt != chassis_info.maxcnt)
 			goto not_found;
 
 		switch (lcd_info.model) {
-		case DISPLAY_MODEL_LCD:	/* LCD display */
-			if (pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block)
-			    && pdc_result[0] != sizeof(struct pdc_chassis_lcd_info_ret_block) - 1)
-				 goto not_found;
-			printk("%s: min_cmd_delay = %d uS\n",
-		             __FUNCTION__, lcd_info.min_cmd_delay);
+		case DISPLAY_MODEL_LCD:		/* LCD display */
+			if (chassis_info.actcnt < 
+				offsetof(struct pdc_chassis_lcd_info_ret_block, _pad)-1)
+				goto not_found;
+			if (!lcd_info.act_enable) {
+				DPRINTK((KERN_INFO "PDC prohibited usage of the LCD.\n"));
+				goto not_found;
+			}
 			break;
 
 		case DISPLAY_MODEL_NONE:	/* no LED or LCD available */
+			printk(KERN_INFO "PDC reported no LCD or LED.\n");
 			goto not_found;
 
 		case DISPLAY_MODEL_LASI:	/* Lasi style 8 bit LED display */
-			if (pdc_result[0] != 8 && pdc_result[0] != 32)
+			if (chassis_info.actcnt != 8 && chassis_info.actcnt != 32)
 				goto not_found;
 			break;
 
 		default:
-			printk(KERN_WARNING "Unknown LCD/LED model %d\n",
+			printk(KERN_WARNING "PDC reported unknown LCD/LED model %d\n",
 			       lcd_info.model);
 			goto not_found;
-		}		/* switch() */
+		} /* switch() */
 
 found:
 		/* register the LCD/LED driver */
-		register_led_driver();
+		register_led_driver(lcd_info.model, LCD_CMD_REG, LCD_DATA_REG);
 		return 0;
 
-	}			/* if() */
+	} else { /* if() */
+		DPRINTK((KERN_INFO "pdc_chassis_info call failed with retval = %d\n", ret));
+	}
 
 not_found:
 	lcd_info.model = DISPLAY_MODEL_NONE;
 	return 1;
-#endif
 }
+
+#ifdef CONFIG_PROC_FS
+module_init(led_create_procfs)
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/pa7300lc.c linux/arch/parisc/kernel/pa7300lc.c
--- linux.orig/arch/parisc/kernel/pa7300lc.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/pa7300lc.c	2002-08-12 22:14:19.000000000 +0000
@@ -4,11 +4,12 @@
  *
  *   Copyright (C) 2000 Philipp Rumpf */
 
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/kernel.h>
 #include <asm/gsc.h>
 #include <asm/ptrace.h>
 #include <asm/machdep.h>
-#include <linux/smp.h>
-#include <linux/kernel.h>
 
 /* CPU register indices */
 
@@ -19,12 +20,6 @@
 #define DIOERR		0xf0ec
 #define HIDMAMEM	0xf0f4
 
-/* read CPU Diagnose register index */
-static u32 diag_read(int index)
-{
-	return 0;
-}
-
 /* this returns the HPA of the CPU it was called on */
 static u32 cpu_hpa(void)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/pacache.S linux/arch/parisc/kernel/pacache.S
--- linux.orig/arch/parisc/kernel/pacache.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/pacache.S	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,908 @@
+/*
+ *  Parisc tlb and cache flushing support
+ *  Copyright (C) 2000 Hewlett-Packard (John Marvin)
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * NOTE: fdc,fic, and pdc instructions that use base register modification
+ *       should only use index and base registers that are not shadowed,
+ *       so that the fast path emulation in the non access miss handler
+ *       can be used.
+ */
+
+#ifdef __LP64__
+#define ADDIB   addib,*
+#define CMPB    cmpb,*
+#define ANDCM   andcm,*
+
+	.level 2.0w
+#else
+#define ADDIB   addib,
+#define CMPB    cmpb,
+#define ANDCM   andcm
+
+	.level 2.0
+#endif
+
+#include <asm/assembly.h>
+#include <asm/psw.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+
+	.text
+	.align 128
+
+	.export flush_tlb_all_local,code
+
+flush_tlb_all_local:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	/*
+	 * The pitlbe and pdtlbe instructions should only be used to
+	 * flush the entire tlb. Also, there needs to be no intervening
+	 * tlb operations, e.g. tlb misses, so the operation needs
+	 * to happen in real mode with all interruptions disabled.
+	 */
+
+	/*
+	 * Once again, we do the rfi dance ... some day we need examine
+	 * all of our uses of this type of code and see what can be
+	 * consolidated.
+	 */
+
+	rsm     PSW_SM_I,%r19      /* relied upon translation! */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	
+	rsm     PSW_SM_Q,%r0       /* Turn off Q bit to load iia queue */
+	ldil    L%REAL_MODE_PSW, %r1
+	ldo     R%REAL_MODE_PSW(%r1), %r1
+	mtctl	%r1, %cr22
+	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17
+	ldil    L%PA(1f),%r1
+	ldo     R%PA(1f)(%r1),%r1
+	mtctl	%r1, %cr18
+	ldo	4(%r1), %r1
+	mtctl	%r1, %cr18
+	rfi
+	nop
+
+1:      ldil            L%PA(cache_info),%r1
+	ldo             R%PA(cache_info)(%r1),%r1
+
+	/* Flush Instruction Tlb */
+
+	LDREG           ITLB_SID_BASE(%r1),%r20
+	LDREG           ITLB_SID_STRIDE(%r1),%r21
+	LDREG           ITLB_SID_COUNT(%r1),%r22
+	LDREG           ITLB_OFF_BASE(%r1),%arg0
+	LDREG           ITLB_OFF_STRIDE(%r1),%arg1
+	LDREG           ITLB_OFF_COUNT(%r1),%arg2
+	LDREG           ITLB_LOOP(%r1),%arg3
+
+	ADDIB=          -1,%arg3,fitoneloop     /* Preadjust and test */
+	movb,<,n        %arg3,%r31,fitdone      /* If loop < 0, skip */
+	copy            %arg0,%r28              /* Init base addr */
+
+fitmanyloop:                                    /* Loop if LOOP >= 2 */
+	mtsp            %r20,%sr1
+	add             %r21,%r20,%r20          /* increment space */
+	copy            %arg2,%r29              /* Init middle loop count */
+
+fitmanymiddle:                                  /* Loop if LOOP >= 2 */
+	ADDIB>          -1,%r31,fitmanymiddle   /* Adjusted inner loop decr */
+	pitlbe          0(%sr1,%r28)
+	pitlbe,m        %arg1(%sr1,%r28)        /* Last pitlbe and addr adjust */
+	ADDIB>          -1,%r29,fitmanymiddle   /* Middle loop decr */
+	copy            %arg3,%r31              /* Re-init inner loop count */
+
+	movb,tr         %arg0,%r28,fitmanyloop  /* Re-init base addr */
+	ADDIB<=,n       -1,%r22,fitdone         /* Outer loop count decr */
+
+fitoneloop:                                     /* Loop if LOOP = 1 */
+	mtsp            %r20,%sr1
+	copy            %arg0,%r28              /* init base addr */
+	copy            %arg2,%r29              /* init middle loop count */
+
+fitonemiddle:                                   /* Loop if LOOP = 1 */
+	ADDIB>          -1,%r29,fitonemiddle    /* Middle loop count decr */
+	pitlbe,m        %arg1(%sr1,%r28)        /* pitlbe for one loop */
+
+	ADDIB>          -1,%r22,fitoneloop      /* Outer loop count decr */
+	add             %r21,%r20,%r20          /* increment space */
+
+fitdone:
+
+	/* Flush Data Tlb */
+
+	LDREG           DTLB_SID_BASE(%r1),%r20
+	LDREG           DTLB_SID_STRIDE(%r1),%r21
+	LDREG           DTLB_SID_COUNT(%r1),%r22
+	LDREG           DTLB_OFF_BASE(%r1),%arg0
+	LDREG           DTLB_OFF_STRIDE(%r1),%arg1
+	LDREG           DTLB_OFF_COUNT(%r1),%arg2
+	LDREG           DTLB_LOOP(%r1),%arg3
+
+	ADDIB=          -1,%arg3,fdtoneloop     /* Preadjust and test */
+	movb,<,n        %arg3,%r31,fdtdone      /* If loop < 0, skip */
+	copy            %arg0,%r28              /* Init base addr */
+
+fdtmanyloop:                                    /* Loop if LOOP >= 2 */
+	mtsp            %r20,%sr1
+	add             %r21,%r20,%r20          /* increment space */
+	copy            %arg2,%r29              /* Init middle loop count */
+
+fdtmanymiddle:                                  /* Loop if LOOP >= 2 */
+	ADDIB>          -1,%r31,fdtmanymiddle   /* Adjusted inner loop decr */
+	pdtlbe          0(%sr1,%r28)
+	pdtlbe,m        %arg1(%sr1,%r28)        /* Last pdtlbe and addr adjust */
+	ADDIB>          -1,%r29,fdtmanymiddle   /* Middle loop decr */
+	copy            %arg3,%r31              /* Re-init inner loop count */
+
+	movb,tr         %arg0,%r28,fdtmanyloop  /* Re-init base addr */
+	ADDIB<=,n       -1,%r22,fdtdone         /* Outer loop count decr */
+
+fdtoneloop:                                     /* Loop if LOOP = 1 */
+	mtsp            %r20,%sr1
+	copy            %arg0,%r28              /* init base addr */
+	copy            %arg2,%r29              /* init middle loop count */
+
+fdtonemiddle:                                   /* Loop if LOOP = 1 */
+	ADDIB>          -1,%r29,fdtonemiddle    /* Middle loop count decr */
+	pdtlbe,m        %arg1(%sr1,%r28)        /* pdtlbe for one loop */
+
+	ADDIB>          -1,%r22,fdtoneloop      /* Outer loop count decr */
+	add             %r21,%r20,%r20          /* increment space */
+
+fdtdone:
+
+	/* Switch back to virtual mode */
+
+	rsm     PSW_SM_Q,%r0       /* clear Q bit to load iia queue */
+	ldil	L%KERNEL_PSW, %r1
+	ldo	R%KERNEL_PSW(%r1), %r1
+	or      %r1,%r19,%r1    /* Set I bit if set on entry */
+	mtctl	%r1, %cr22
+	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17
+	ldil    L%(2f), %r1
+	ldo     R%(2f)(%r1), %r1
+	mtctl	%r1, %cr18
+	ldo	4(%r1), %r1
+	mtctl	%r1, %cr18
+	rfi
+	nop
+
+2:      bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_instruction_cache_local,code
+	.import cache_info,data
+
+flush_instruction_cache_local:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	mtsp            %r0,%sr1
+	ldil            L%cache_info,%r1
+	ldo             R%cache_info(%r1),%r1
+
+	/* Flush Instruction Cache */
+
+	LDREG           ICACHE_BASE(%r1),%arg0
+	LDREG           ICACHE_STRIDE(%r1),%arg1
+	LDREG           ICACHE_COUNT(%r1),%arg2
+	LDREG           ICACHE_LOOP(%r1),%arg3
+	ADDIB=          -1,%arg3,fioneloop      /* Preadjust and test */
+	movb,<,n        %arg3,%r31,fisync       /* If loop < 0, do sync */
+
+fimanyloop:                                     /* Loop if LOOP >= 2 */
+	ADDIB>          -1,%r31,fimanyloop      /* Adjusted inner loop decr */
+	fice            0(%sr1,%arg0)
+	fice,m          %arg1(%sr1,%arg0)       /* Last fice and addr adjust */
+	movb,tr         %arg3,%r31,fimanyloop   /* Re-init inner loop count */
+	ADDIB<=,n       -1,%arg2,fisync         /* Outer loop decr */
+
+fioneloop:                                      /* Loop if LOOP = 1 */
+	ADDIB>          -1,%arg2,fioneloop      /* Outer loop count decr */
+	fice,m          %arg1(%sr1,%arg0)       /* Fice for one loop */
+
+fisync:
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_data_cache_local,code
+	.import cache_info,data
+
+flush_data_cache_local:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	mtsp            %r0,%sr1
+	ldil            L%cache_info,%r1
+	ldo             R%cache_info(%r1),%r1
+
+	/* Flush Data Cache */
+
+	LDREG           DCACHE_BASE(%r1),%arg0
+	LDREG           DCACHE_STRIDE(%r1),%arg1
+	LDREG           DCACHE_COUNT(%r1),%arg2
+	LDREG           DCACHE_LOOP(%r1),%arg3
+	rsm             PSW_SM_I,%r22
+	ADDIB=          -1,%arg3,fdoneloop      /* Preadjust and test */
+	movb,<,n        %arg3,%r31,fdsync       /* If loop < 0, do sync */
+
+fdmanyloop:                                     /* Loop if LOOP >= 2 */
+	ADDIB>          -1,%r31,fdmanyloop      /* Adjusted inner loop decr */
+	fdce            0(%sr1,%arg0)
+	fdce,m          %arg1(%sr1,%arg0)       /* Last fdce and addr adjust */
+	movb,tr         %arg3,%r31,fdmanyloop   /* Re-init inner loop count */
+	ADDIB<=,n       -1,%arg2,fdsync         /* Outer loop decr */
+
+fdoneloop:                                      /* Loop if LOOP = 1 */
+	ADDIB>          -1,%arg2,fdoneloop      /* Outer loop count decr */
+	fdce,m          %arg1(%sr1,%arg0)       /* Fdce for one loop */
+
+fdsync:
+	syncdma
+	sync
+	mtsm    %r22
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export copy_user_page_asm,code
+
+copy_user_page_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldi 64,%r1
+
+	/*
+	 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
+	 * bundles (very restricted rules for bundling). It probably
+	 * does OK on PCXU and better, but we could do better with
+	 * ldd/std instructions. Note that until (if) we start saving
+	 * the full 64 bit register values on interrupt, we can't
+	 * use ldd/std on a 32 bit kernel.
+	 */
+
+
+1:
+	ldw 0(%r25),%r19
+	ldw 4(%r25),%r20
+	ldw 8(%r25),%r21
+	ldw 12(%r25),%r22
+	stw %r19,0(%r26)
+	stw %r20,4(%r26)
+	stw %r21,8(%r26)
+	stw %r22,12(%r26)
+	ldw 16(%r25),%r19
+	ldw 20(%r25),%r20
+	ldw 24(%r25),%r21
+	ldw 28(%r25),%r22
+	stw %r19,16(%r26)
+	stw %r20,20(%r26)
+	stw %r21,24(%r26)
+	stw %r22,28(%r26)
+	ldw 32(%r25),%r19
+	ldw 36(%r25),%r20
+	ldw 40(%r25),%r21
+	ldw 44(%r25),%r22
+	stw %r19,32(%r26)
+	stw %r20,36(%r26)
+	stw %r21,40(%r26)
+	stw %r22,44(%r26)
+	ldw 48(%r25),%r19
+	ldw 52(%r25),%r20
+	ldw 56(%r25),%r21
+	ldw 60(%r25),%r22
+	stw %r19,48(%r26)
+	stw %r20,52(%r26)
+	stw %r21,56(%r26)
+	stw %r22,60(%r26)
+	ldo 64(%r26),%r26
+	ADDIB>  -1,%r1,1b
+	ldo 64(%r25),%r25
+
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+#if (TMPALIAS_MAP_START >= 0x80000000UL)
+Warning TMPALIAS_MAP_START changed. If > 2 Gb, code in pacache.S is bogus
+#endif
+
+/*
+ * NOTE: Code in clear_user_page has a hard coded dependency on the
+ *       maximum alias boundary being 4 Mb. We've been assured by the
+ *       parisc chip designers that there will not ever be a parisc
+ *       chip with a larger alias boundary (Never say never :-) ).
+ *
+ *       Subtle: the dtlb miss handlers support the temp alias region by
+ *       "knowing" that if a dtlb miss happens within the temp alias
+ *       region it must have occurred while in clear_user_page. Since
+ *       this routine makes use of processor local translations, we
+ *       don't want to insert them into the kernel page table. Instead,
+ *       we load up some general registers (they need to be registers
+ *       which aren't shadowed) with the physical page numbers (preshifted
+ *       for tlb insertion) needed to insert the translations. When we
+ *       miss on the translation, the dtlb miss handler inserts the
+ *       translation into the tlb using these values:
+ *
+ *          %r26 physical page (shifted for tlb insert) of "to" translation
+ *          %r23 physical page (shifted for tlb insert) of "from" translation
+ */
+
+#if 0
+
+	/*
+	 * We can't do this since copy_user_page is used to bring in
+	 * file data that might have instructions. Since the data would
+	 * then need to be flushed out so the i-fetch can see it, it
+	 * makes more sense to just copy through the kernel translation
+	 * and flush it.
+	 *
+	 * I'm still keeping this around because it may be possible to
+	 * use it if more information is passed into copy_user_page().
+	 * Have to do some measurements to see if it is worthwhile to
+	 * lobby for such a change.
+	 */
+
+	.export copy_user_page_asm,code
+
+copy_user_page_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%(__PAGE_OFFSET),%r1
+	sub     %r26,%r1,%r26
+	sub     %r25,%r1,%r23  /* move physical addr into non shadowed reg */
+
+	ldil    L%(TMPALIAS_MAP_START),%r28
+#ifdef __LP64__
+	extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
+	extrd,u %r23,56,32,%r23 /* convert phys addr to tlb insert format */
+	depd    %r24,63,22,%r28 /* Form aliased virtual address 'to' */
+	depdi   0,63,12,%r28    /* Clear any offset bits */
+	copy    %r28,%r29
+	depdi   1,41,1,%r29     /* Form aliased virtual address 'from' */
+#else
+	extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
+	extrw,u %r23,24,25,%r23 /* convert phys addr to tlb insert format */
+	depw    %r24,31,22,%r28 /* Form aliased virtual address 'to' */
+	depwi   0,31,12,%r28    /* Clear any offset bits */
+	copy    %r28,%r29
+	depwi   1,9,1,%r29      /* Form aliased virtual address 'from' */
+#endif
+
+	/* Purge any old translations */
+
+	pdtlb   0(%r28)
+	pdtlb   0(%r29)
+
+	ldi 64,%r1
+
+	/*
+	 * This loop is optimized for PCXL/PCXL2 ldw/ldw and stw/stw
+	 * bundles (very restricted rules for bundling). It probably
+	 * does OK on PCXU and better, but we could do better with
+	 * ldd/std instructions. Note that until (if) we start saving
+	 * the full 64 bit register values on interrupt, we can't
+	 * use ldd/std on a 32 bit kernel.
+	 */
+
+
+1:
+	ldw 0(%r29),%r19
+	ldw 4(%r29),%r20
+	ldw 8(%r29),%r21
+	ldw 12(%r29),%r22
+	stw %r19,0(%r28)
+	stw %r20,4(%r28)
+	stw %r21,8(%r28)
+	stw %r22,12(%r28)
+	ldw 16(%r29),%r19
+	ldw 20(%r29),%r20
+	ldw 24(%r29),%r21
+	ldw 28(%r29),%r22
+	stw %r19,16(%r28)
+	stw %r20,20(%r28)
+	stw %r21,24(%r28)
+	stw %r22,28(%r28)
+	ldw 32(%r29),%r19
+	ldw 36(%r29),%r20
+	ldw 40(%r29),%r21
+	ldw 44(%r29),%r22
+	stw %r19,32(%r28)
+	stw %r20,36(%r28)
+	stw %r21,40(%r28)
+	stw %r22,44(%r28)
+	ldw 48(%r29),%r19
+	ldw 52(%r29),%r20
+	ldw 56(%r29),%r21
+	ldw 60(%r29),%r22
+	stw %r19,48(%r28)
+	stw %r20,52(%r28)
+	stw %r21,56(%r28)
+	stw %r22,60(%r28)
+	ldo 64(%r28),%r28
+	ADDIB>  -1,%r1,1b
+	ldo 64(%r29),%r29
+
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+#endif
+
+	.export clear_user_page_asm,code
+
+clear_user_page_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	tophys_r1 %r26
+
+	ldil    L%(TMPALIAS_MAP_START),%r28
+#ifdef __LP64__
+	extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
+	depd    %r25,63,22,%r28 /* Form aliased virtual address 'to' */
+	depdi   0,63,12,%r28    /* Clear any offset bits */
+#else
+	extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
+	depw    %r25,31,22,%r28 /* Form aliased virtual address 'to' */
+	depwi   0,31,12,%r28    /* Clear any offset bits */
+#endif
+
+	/* Purge any old translation */
+
+	pdtlb   0(%r28)
+
+	ldi 64,%r1
+
+1:
+	stw %r0,0(%r28)
+	stw %r0,4(%r28)
+	stw %r0,8(%r28)
+	stw %r0,12(%r28)
+	stw %r0,16(%r28)
+	stw %r0,20(%r28)
+	stw %r0,24(%r28)
+	stw %r0,28(%r28)
+	stw %r0,32(%r28)
+	stw %r0,36(%r28)
+	stw %r0,40(%r28)
+	stw %r0,44(%r28)
+	stw %r0,48(%r28)
+	stw %r0,52(%r28)
+	stw %r0,56(%r28)
+	stw %r0,60(%r28)
+	ADDIB>  -1,%r1,1b
+	ldo 64(%r28),%r28
+
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_kernel_dcache_page
+
+flush_kernel_dcache_page:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%dcache_stride,%r1
+	ldw     R%dcache_stride(%r1),%r23
+
+#ifdef __LP64__
+	depdi,z 1,63-PAGE_SHIFT,1,%r25
+#else
+	depwi,z 1,31-PAGE_SHIFT,1,%r25
+#endif
+	add     %r26,%r25,%r25
+	sub     %r25,%r23,%r25
+
+
+1:      fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	fdc,m   %r23(%r26)
+	CMPB<<  %r26,%r25,1b
+	fdc,m   %r23(%r26)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export purge_kernel_dcache_page
+
+purge_kernel_dcache_page:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%dcache_stride,%r1
+	ldw     R%dcache_stride(%r1),%r23
+
+#ifdef __LP64__
+	depdi,z 1,63-PAGE_SHIFT,1,%r25
+#else
+	depwi,z 1,31-PAGE_SHIFT,1,%r25
+#endif
+	add      %r26,%r25,%r25
+	sub      %r25,%r23,%r25
+
+1:      pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	pdc,m   %r23(%r26)
+	CMPB<<  %r26,%r25,1b
+	pdc,m   %r23(%r26)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+#if 0
+	/* Currently not used, but it still is a possible alternate
+	 * solution.
+	 */
+
+	.export flush_alias_page
+
+flush_alias_page:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	tophys_r1 %r26
+
+	ldil    L%(TMPALIAS_MAP_START),%r28
+#ifdef __LP64__
+	extrd,u %r26,56,32,%r26 /* convert phys addr to tlb insert format */
+	depd    %r25,63,22,%r28 /* Form aliased virtual address 'to' */
+	depdi   0,63,12,%r28    /* Clear any offset bits */
+#else
+	extrw,u %r26,24,25,%r26 /* convert phys addr to tlb insert format */
+	depw    %r25,31,22,%r28 /* Form aliased virtual address 'to' */
+	depwi   0,31,12,%r28    /* Clear any offset bits */
+#endif
+
+	/* Purge any old translation */
+
+	pdtlb   0(%r28)
+
+	ldil    L%dcache_stride,%r1
+	ldw     R%dcache_stride(%r1),%r23
+
+#ifdef __LP64__
+	depdi,z 1,63-PAGE_SHIFT,1,%r29
+#else
+	depwi,z 1,31-PAGE_SHIFT,1,%r29
+#endif
+	add      %r28,%r29,%r29
+	sub      %r29,%r23,%r29
+
+1:      fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	fdc,m   %r23(%r28)
+	CMPB<<  %r28,%r29,1b
+	fdc,m   %r23(%r28)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+#endif
+
+	.export flush_user_dcache_range_asm
+
+flush_user_dcache_range_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%dcache_stride,%r1
+	ldw     R%dcache_stride(%r1),%r23
+	ldo     -1(%r23),%r21
+	ANDCM   %r26,%r21,%r26
+
+1:      CMPB<<,n %r26,%r25,1b
+	fdc,m   %r23(%sr3,%r26)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_kernel_dcache_range_asm
+
+flush_kernel_dcache_range_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%dcache_stride,%r1
+	ldw     R%dcache_stride(%r1),%r23
+	ldo     -1(%r23),%r21
+	ANDCM   %r26,%r21,%r26
+
+1:      CMPB<<,n %r26,%r25,1b
+	fdc,m   %r23(%r26)
+
+	sync
+	syncdma
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_user_icache_range_asm
+
+flush_user_icache_range_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%icache_stride,%r1
+	ldw     R%icache_stride(%r1),%r23
+	ldo     -1(%r23),%r21
+	ANDCM   %r26,%r21,%r26
+
+1:      CMPB<<,n %r26,%r25,1b
+	fic,m   %r23(%sr3,%r26)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_kernel_icache_page
+
+flush_kernel_icache_page:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%icache_stride,%r1
+	ldw     R%icache_stride(%r1),%r23
+
+#ifdef __LP64__
+	depdi,z 1,63-PAGE_SHIFT,1,%r25
+#else
+	depwi,z 1,31-PAGE_SHIFT,1,%r25
+#endif
+	add     %r26,%r25,%r25
+	sub     %r25,%r23,%r25
+
+
+1:      fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	fic,m   %r23(%r26)
+	CMPB<<  %r26,%r25,1b
+	fic,m   %r23(%r26)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.export flush_kernel_icache_range_asm
+
+flush_kernel_icache_range_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	ldil    L%icache_stride,%r1
+	ldw     R%icache_stride(%r1),%r23
+	ldo     -1(%r23),%r21
+	ANDCM   %r26,%r21,%r26
+
+1:      CMPB<<,n %r26,%r25,1b
+	fic,m   %r23(%r26)
+
+	sync
+	bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.align 128
+
+	.export disable_sr_hashing_asm,code
+
+disable_sr_hashing_asm:
+	.proc
+	.callinfo NO_CALLS
+	.entry
+
+	/* Switch to real mode */
+
+	ssm     0,%r0           /* relied upon translation! */
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	
+	rsm     (PSW_SM_Q|PSW_SM_I),%r0 /* disable Q&I to load the iia queue */
+	ldil    L%REAL_MODE_PSW, %r1
+	ldo     R%REAL_MODE_PSW(%r1), %r1
+	mtctl	%r1, %cr22
+	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17
+	ldil    L%PA(1f),%r1
+	ldo     R%PA(1f)(%r1),%r1
+	mtctl	%r1, %cr18
+	ldo	4(%r1), %r1
+	mtctl	%r1, %cr18
+	rfi
+	nop
+
+1:      cmpib,=,n SRHASH_PCXST,%r26,srdis_pcxs
+	cmpib,=,n SRHASH_PCXL,%r26,srdis_pcxl
+	cmpib,=,n SRHASH_PA20,%r26,srdis_pa20
+	b,n       srdis_done
+
+srdis_pcxs:
+
+	/* Disable Space Register Hashing for PCXS,PCXT,PCXT' */
+
+	.word           0x141c1a00  /* mfdiag %dr0,%r28 */
+	.word           0x141c1a00  /* must issue twice */
+	depwi           0,18,1,%r28 /* Clear DHE (dcache hash enable) */
+	depwi           0,20,1,%r28 /* Clear IHE (icache hash enable) */
+	.word           0x141c1600  /* mtdiag %r28,%dr0 */
+	.word           0x141c1600  /* must issue twice */
+	b,n             srdis_done
+
+srdis_pcxl:
+
+	/* Disable Space Register Hashing for PCXL */
+
+	.word           0x141c0600  /* mfdiag %dr0,%r28 */
+	depwi           0,28,2,%r28 /* Clear DHASH_EN & IHASH_EN */
+	.word           0x141c0240  /* mtdiag %r28,%dr0 */
+	b,n             srdis_done
+
+srdis_pa20:
+
+	/* Disable Space Register Hashing for PCXU,PCXU+,PCXW,PCXW+ */
+
+	.word           0x144008bc  /* mfdiag %dr2,%r28 */
+	depdi           0,54,1,%r28 /* clear DIAG_SPHASH_ENAB (bit 54) */
+	.word           0x145c1840  /* mtdiag %r28,%dr2 */
+
+srdis_done:
+
+	/* Switch back to virtual mode */
+
+	rsm     PSW_SM_Q,%r0           /* clear Q bit to load iia queue */
+	ldil	L%KERNEL_PSW, %r1
+	ldo	R%KERNEL_PSW(%r1), %r1
+	mtctl	%r1, %cr22
+	mtctl	%r0, %cr17
+	mtctl	%r0, %cr17
+	ldil    L%(2f), %r1
+	ldo     R%(2f)(%r1), %r1
+	mtctl	%r1, %cr18
+	ldo	4(%r1), %r1
+	mtctl	%r1, %cr18
+	rfi
+	nop
+
+2:      bv      %r0(%r2)
+	nop
+	.exit
+
+	.procend
+
+	.end
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/parisc_ksyms.c linux/arch/parisc/kernel/parisc_ksyms.c
--- linux.orig/arch/parisc/kernel/parisc_ksyms.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/parisc_ksyms.c	2002-08-12 22:14:27.000000000 +0000
@@ -14,17 +14,29 @@
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strrchr);
 EXPORT_SYMBOL(strcmp);
 EXPORT_SYMBOL(strcpy);
 EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strncat);
 EXPORT_SYMBOL(strncmp);
 EXPORT_SYMBOL(strncpy);
 EXPORT_SYMBOL(strtok);
+EXPORT_SYMBOL(strstr);
 
+#include <asm/hardware.h>	/* struct parisc_device for asm/pci.h */
 #include <linux/pci.h>
 EXPORT_SYMBOL(hppa_dma_ops);
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+EXPORT_SYMBOL(get_pci_node_path);
+#endif
+
+#ifdef CONFIG_IOMMU_CCIO
+EXPORT_SYMBOL(ccio_get_fake);
+#endif
 
+#include <linux/sched.h>
 #include <asm/irq.h>
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
@@ -32,6 +44,13 @@
 #include <asm/processor.h>
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(boot_cpu_data);
+EXPORT_SYMBOL(map_hpux_gateway_page);
+#ifdef CONFIG_EISA
+EXPORT_SYMBOL(EISA_bus);
+#endif
+
+#include <linux/pm.h>
+EXPORT_SYMBOL(pm_power_off);
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(synchronize_irq);
@@ -39,35 +58,100 @@
 #include <asm/smplock.h>
 EXPORT_SYMBOL(kernel_flag);
 
+/* from asm/system.h */
 #include <asm/system.h>
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_save_flags);
 EXPORT_SYMBOL(__global_restore_flags);
 
+#include <linux/smp.h>
+EXPORT_SYMBOL(smp_num_cpus);
+#endif /* CONFIG_SMP */
+
+#include <asm/atomic.h>
+EXPORT_SYMBOL(__xchg8);
+EXPORT_SYMBOL(__xchg32);
+EXPORT_SYMBOL(__cmpxchg_u32);
+#ifdef CONFIG_SMP
+EXPORT_SYMBOL(__atomic_hash);
+#endif
+#ifdef __LP64__
+EXPORT_SYMBOL(__xchg64);
+EXPORT_SYMBOL(__cmpxchg_u64);
 #endif
 
 #include <asm/uaccess.h>
 EXPORT_SYMBOL(lcopy_to_user);
 EXPORT_SYMBOL(lcopy_from_user);
+EXPORT_SYMBOL(lstrnlen_user);
+EXPORT_SYMBOL(lclear_user);
 
+#ifndef __LP64__
 /* Needed so insmod can set dp value */
-
-extern int data_start;
-
-EXPORT_SYMBOL_NOVERS(data_start);
+extern int $global$;
+EXPORT_SYMBOL_NOVERS($global$);
+#endif
 
 #include <asm/gsc.h>
-EXPORT_SYMBOL(_gsc_writeb);
-EXPORT_SYMBOL(_gsc_writew);
-EXPORT_SYMBOL(_gsc_writel);
-EXPORT_SYMBOL(_gsc_readb);
-EXPORT_SYMBOL(_gsc_readw);
-EXPORT_SYMBOL(_gsc_readl);
-EXPORT_SYMBOL(busdevice_alloc_irq);
-EXPORT_SYMBOL(register_driver);
-EXPORT_SYMBOL(gsc_alloc_irq);
+EXPORT_SYMBOL(register_parisc_driver);
+EXPORT_SYMBOL(unregister_parisc_driver);
 EXPORT_SYMBOL(pdc_iodc_read);
+#ifdef CONFIG_GSC
+EXPORT_SYMBOL(gsc_alloc_irq);
+#endif
+
+#include <asm/io.h>
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(memcpy_toio);
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memset_io);
+
+#if defined(CONFIG_PCI) || defined(CONFIG_ISA)
+EXPORT_SYMBOL(inb);
+EXPORT_SYMBOL(inw);
+EXPORT_SYMBOL(inl);
+EXPORT_SYMBOL(outb);
+EXPORT_SYMBOL(outw);
+EXPORT_SYMBOL(outl);
+
+EXPORT_SYMBOL(insb);
+EXPORT_SYMBOL(insw);
+EXPORT_SYMBOL(insl);
+EXPORT_SYMBOL(outsb);
+EXPORT_SYMBOL(outsw);
+EXPORT_SYMBOL(outsl);
+#endif
+
+#include <asm/cache.h>
+EXPORT_SYMBOL(flush_kernel_dcache_range_asm);
+EXPORT_SYMBOL(flush_kernel_dcache_page);
+EXPORT_SYMBOL(flush_all_caches);
+
+#include <asm/unistd.h>
+extern long sys_open(const char *, int, int);
+extern off_t sys_lseek(int, off_t, int);
+extern int sys_read(int, char *, int);
+extern int sys_write(int, const char *, int);
+EXPORT_SYMBOL(sys_open);
+EXPORT_SYMBOL(sys_lseek);
+EXPORT_SYMBOL(sys_read);
+EXPORT_SYMBOL(sys_write);
+
+#include <asm/semaphore.h>
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down);
+
+#include <linux/in6.h>
+#include <asm/checksum.h>
+EXPORT_SYMBOL(csum_partial_copy);
+
+#include <asm/pdc.h>
+EXPORT_SYMBOL(pdc_add_valid);
+EXPORT_SYMBOL(pdc_lan_station_id);
+EXPORT_SYMBOL(pdc_get_initiator);
 
 extern void $$divI(void);
 extern void $$divU(void);
@@ -99,7 +183,9 @@
 EXPORT_SYMBOL_NOVERS($$remI);
 EXPORT_SYMBOL_NOVERS($$remU);
 EXPORT_SYMBOL_NOVERS($$mulI);
+#ifndef __LP64__
 EXPORT_SYMBOL_NOVERS($$mulU);
+#endif
 EXPORT_SYMBOL_NOVERS($$divU_3);
 EXPORT_SYMBOL_NOVERS($$divU_5);
 EXPORT_SYMBOL_NOVERS($$divU_6);
@@ -120,15 +206,25 @@
 EXPORT_SYMBOL_NOVERS($$divI_15);
 
 extern void __ashrdi3(void);
+extern void __ashldi3(void);
+extern void __lshrdi3(void);
+extern void __muldi3(void);
 
 EXPORT_SYMBOL_NOVERS(__ashrdi3);
+EXPORT_SYMBOL_NOVERS(__ashldi3);
+EXPORT_SYMBOL_NOVERS(__lshrdi3);
+EXPORT_SYMBOL_NOVERS(__muldi3);
 
 #ifdef __LP64__
 extern void __divdi3(void);
 extern void __udivdi3(void);
+extern void __umoddi3(void);
+extern void __moddi3(void);
 
 EXPORT_SYMBOL_NOVERS(__divdi3);
 EXPORT_SYMBOL_NOVERS(__udivdi3);
+EXPORT_SYMBOL_NOVERS(__umoddi3);
+EXPORT_SYMBOL_NOVERS(__moddi3);
 #endif
 
 #ifndef __LP64__
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/pci-dma.c linux/arch/parisc/kernel/pci-dma.c
--- linux.orig/arch/parisc/kernel/pci-dma.c	2001-10-12 22:35:53.000000000 +0000
+++ linux/arch/parisc/kernel/pci-dma.c	2002-08-12 22:14:25.000000000 +0000
@@ -1,5 +1,7 @@
 /*
-** Dynamic DMA mapping support.
+** PARISC 1.1 Dynamic DMA mapping support.
+** This implementation is for PA-RISC platforms that do not support
+** I/O TLBs (aka DMA address translation hardware).
 ** See Documentation/DMA-mapping.txt for interface definitions.
 **
 **      (c) Copyright 1999,2000 Hewlett-Packard Company
@@ -7,15 +9,10 @@
 **	(c) Copyright 2000 Philipp Rumpf <prumpf@tux.org>
 **      (c) Copyright 2000 John Marvin
 **
-** This implementation is for PA-RISC platforms that do not support
-** I/O TLBs (aka DMA address translation hardware).
-**
 ** "leveraged" from 2.3.47: arch/ia64/kernel/pci-dma.c.
 ** (I assume it's from David Mosberger-Tang but there was no Copyright)
 **
 ** AFAIK, all PA7100LC and PA7300LC platforms can use this code.
-** All PA2.0 machines but V-class can alias xxx_alloc_consistent()
-** to use regular cacheable memory.
 **
 ** - ggg
 */
@@ -117,7 +114,7 @@
 	if (end > PGDIR_SIZE)
 		end = PGDIR_SIZE;
 	do {
-		pte_t * pte = pte_alloc_kernel(pmd, vaddr);
+		pte_t * pte = pte_alloc(NULL, pmd, vaddr);
 		if (!pte)
 			return -ENOMEM;
 		if (map_pte_uncached(pte, orig_vaddr, end - vaddr, paddr_ptr))
@@ -139,7 +136,7 @@
 	do {
 		pmd_t *pmd;
 		
-		pmd = pmd_alloc_kernel(dir, vaddr);
+		pmd = pmd_alloc(NULL, dir, vaddr);
 		if (!pmd)
 			return -ENOMEM;
 		if (map_pmd_uncached(pmd, vaddr, end - vaddr, &paddr))
@@ -510,7 +507,6 @@
 	pa11_dma_sync_sg			/* dma_sync_sg */
 };
 
-struct pci_dma_ops *hppa_dma_ops;
 
 static int pcxl_proc_info(char *buf, char **start, off_t offset, int len)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/pci.c linux/arch/parisc/kernel/pci.c
--- linux.orig/arch/parisc/kernel/pci.c	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/kernel/pci.c	2002-08-12 22:13:59.000000000 +0000
@@ -6,25 +6,32 @@
  *
  * Copyright (C) 1997, 1998 Ralf Baechle
  * Copyright (C) 1999 SuSE GmbH
- * Copyright (C) 1999 Hewlett-Packard Company
- * Copyright (C) 1999, 2000 Grant Grundler
+ * Copyright (C) 1999-2001 Hewlett-Packard Company
+ * Copyright (C) 1999-2001 Grant Grundler
  */
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/init.h>		/* for __init and __devinit */
 #include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/string.h>	/* for memcpy() */
+#include <linux/slab.h>
 
+#include <asm/io.h>
 #include <asm/system.h>
+#include <asm/cache.h>		/* for L1_CACHE_BYTES */
 
-#ifdef CONFIG_PCI
+#define DEBUG_RESOURCES 0
+#define DEBUG_CONFIG 0
+
+#if DEBUG_CONFIG
+# define DBGC(x...)     printk(KERN_DEBUG x)
+#else
+# define DBGC(x...)
+#endif
 
-#undef DEBUG_RESOURCES
 
-#ifdef DEBUG_RESOURCES
-#define DBG_RES(x...)	printk(x)
+#if DEBUG_RESOURCES
+#define DBG_RES(x...)	printk(KERN_DEBUG x)
 #else
 #define DBG_RES(x...)
 #endif
@@ -42,14 +49,13 @@
 struct pci_port_ops *pci_port;
 struct pci_bios_ops *pci_bios;
 
-struct pci_hba_data *hba_list = NULL;
-int hba_count = 0;
+int pci_hba_count = 0;
 
 /*
 ** parisc_pci_hba used by pci_port->in/out() ops to lookup bus data.
 */
 #define PCI_HBA_MAX 32
-static struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
+struct pci_hba_data *parisc_pci_hba[PCI_HBA_MAX];
 
 
 /********************************************************************
@@ -58,24 +64,31 @@
 **
 *********************************************************************/
 
-#define PCI_PORT_HBA(a) ((a)>>16)
-#define PCI_PORT_ADDR(a) ((a) & 0xffffUL)
+/* EISA port numbers and PCI port numbers share the same interface.  Some
+ * machines have both EISA and PCI adapters installed.  Rather than turn
+ * pci_port into an array, we reserve bus 0 for EISA and call the EISA
+ * routines if the access is to a port on bus 0.  We don't want to fix
+ * EISA and ISA drivers which assume port space is <= 0xffff.
+ */
 
-/* KLUGE : inb needs to be defined differently for PCI devices than
-** for other bus interfaces. Doing this at runtime sucks but is the
-** only way one driver binary can support devices on different bus types.
-**
-*/
+#ifdef CONFIG_EISA
+#define EISA_IN(size) if (EISA_bus && (b == 0)) return eisa_in##size(addr)
+#define EISA_OUT(size) if (EISA_bus && (b == 0)) return eisa_out##size(d, addr)
+#else
+#define EISA_IN(size)
+#define EISA_OUT(size)
+#endif
 
 #define PCI_PORT_IN(type, size) \
 u##size in##type (int addr) \
 { \
 	int b = PCI_PORT_HBA(addr); \
 	u##size d = (u##size) -1; \
+	EISA_IN(size); \
 	ASSERT(pci_port); /* make sure services are defined */ \
 	ASSERT(parisc_pci_hba[b]); /* make sure ioaddr are "fixed up" */ \
 	if (parisc_pci_hba[b] == NULL) { \
-		printk(KERN_WARNING "\nPCI Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \
+		printk(KERN_WARNING "\nPCI or EISA Host Bus Adapter %d not registered. in" #size "(0x%x) returning -1\n", b, addr); \
 	} else { \
 		d = pci_port->in##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr)); \
 	} \
@@ -91,6 +104,7 @@
 void out##type (u##size d, int addr) \
 { \
 	int b = PCI_PORT_HBA(addr); \
+	EISA_OUT(size); \
 	ASSERT(pci_port); \
 	pci_port->out##type(parisc_pci_hba[b], PCI_PORT_ADDR(addr), d); \
 }
@@ -106,15 +120,13 @@
  */
 void pcibios_init(void)
 {
-	ASSERT(pci_bios != NULL);
+	if (!pci_bios)
+		return;
 
-	if (pci_bios)
-	{
-		if (pci_bios->init) {
-			(*pci_bios->init)();
-		} else {
-			printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
-		}
+	if (pci_bios->init) {
+		pci_bios->init();
+	} else {
+		printk(KERN_WARNING "pci_bios != NULL but init() is!\n");
 	}
 }
 
@@ -124,17 +136,10 @@
 {
 	ASSERT(pci_bios != NULL);
 
-        /* If this is a bridge, get the current bases */
-	if (bus->self) {
-		pci_read_bridge_bases(bus);
-	}
-
-	if (pci_bios) {
-		if (pci_bios->fixup_bus) {
-			(*pci_bios->fixup_bus)(bus);
-		} else {
-			printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
-		}
+	if (pci_bios->fixup_bus) {
+		pci_bios->fixup_bus(bus);
+	} else {
+		printk(KERN_WARNING "pci_bios != NULL but fixup_bus() is!\n");
 	}
 }
 
@@ -144,14 +149,6 @@
 	return str;
 }
 
-#endif /* defined(CONFIG_PCI) */
-
-
-
-/* -------------------------------------------------------------------
-** linux-2.4: NEW STUFF 
-** --------------------
-*/
 
 /*
 ** Used in drivers/pci/quirks.c
@@ -201,19 +198,11 @@
 ** ------------------------------------
 ** PAT PDC systems need this routine. PA legacy PDC does not.
 **
-** Used by alpha/arm: 
-** alpha/kernel/pci.c:common_init_pci()
-** (or arm/kernel/pci.c:pcibios_init())
-**    drivers/pci/setup.c:pci_assign_unassigned_resources()
-**        drivers/pci/setup.c:pdev_assign_unassigned_resources()
-**            arch/<foo>/kernel/pci.c:pcibios_update_resource()
-**
-** When BAR's are configured by linux, this routine
-** will update configuration space with the "normalized"
-** address. "root" indicates where the range starts and res
-** is some portion of that range.
+** When BAR's are configured by linux, this routine will update
+** configuration space with the "normalized" address. "root" indicates
+** where the range starts and res is some portion of that range.
 **
-** For all PA-RISC systems except V-class, root->start would be zero.
+** VCLASS: For all PA-RISC systems except V-class, root->start would be zero.
 **
 ** PAT PDC can tell us which MMIO ranges are available or already in use.
 ** I/O port space and such are not memory mapped anyway for PA-Risc.
@@ -234,7 +223,7 @@
 		barnum, res->start, res->end, (int) res->flags);
 
 	if (barnum >= PCI_BRIDGE_RESOURCES) {
-		/* handled in pbus_set_ranges_data() */
+		/* handled in PCI-PCI bridge specific support */
 		return;
 	}
 
@@ -248,8 +237,7 @@
 	if (res->flags & IORESOURCE_IO) {
 		barval = PCI_PORT_ADDR(res->start);
 	} else if (res->flags & IORESOURCE_MEM) {
-		/* This should work for VCLASS too */
-		barval = res->start & 0xffffffffUL;
+		barval = PCI_BUS_ADDR(HBA_DATA(dev->bus->sysdata), res->start);
 	} else {
 		panic("pcibios_update_resource() WTF? flags not IO or MEM");
 	}
@@ -267,7 +255,7 @@
 	    == (PCI_BASE_ADDRESS_SPACE_MEMORY
 		| PCI_BASE_ADDRESS_MEM_TYPE_64)) {
 		pci_write_config_dword(dev, where+4, 0);
-		printk(KERN_WARNING "PCI: dev %s type 64-bit\n", dev->name);
+		DBGC("PCIBIOS: dev %s type 64-bit\n", dev->name);
 	}
 }
 
@@ -290,25 +278,78 @@
 pcibios_set_master(struct pci_dev *dev)
 {
 	u8 lat;
+
+	/* If someone already mucked with this, don't touch it. */
 	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
 	if (lat >= 16) return;
 
 	/*
 	** HP generally has fewer devices on the bus than other architectures.
+	** upper byte is PCI_LATENCY_TIMER.
 	*/
-	printk("PCIBIOS: Setting latency timer of %s to 128\n", dev->slot_name);
-	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x80);
+        pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
+				(0x80 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
+}
+
+
+void __init
+pcibios_init_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev = bus->self;
+
+	/* We deal only with pci controllers and pci-pci bridges. */
+	if (dev && (dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+		return;
+	
+	if (dev) {
+		/* PCI-PCI bridge - set the cache line and default latency
+		   (32) for primary and secondary buses. */
+		pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);
+
+		/* Read bridge control */
+		pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bus->bridge_ctl);
+	}
+
+	/* Set FBB bit for now. Disable ISA IO forwarding. Enable PERR/SERR */
+	bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK | 
+			   PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
 }
 
 
 /*
-** called by drivers/pci/setup-res.c:pbus_set_ranges().
+** KLUGE: Link the child and parent resources - generic PCI didn't
+*/
+static void
+pcibios_link_hba_resources( struct resource *hba_res, struct resource *r)
+{
+	if (!r->parent) {
+		r->parent = hba_res;
+
+		/* reverse link is harder *sigh*  */
+		if (r->parent->child) {
+			if (r->parent->sibling) {
+				struct resource *next = r->parent->sibling;
+				while (next->sibling)
+					 next = next->sibling;
+				next->sibling = r;
+			} else {
+				r->parent->sibling = r;
+			}
+		} else
+			r->parent->child = r;
+	}
+}
+
+/*
+** called by drivers/pci/setup-res.c:pci_setup_bridge().
 */
 void pcibios_fixup_pbus_ranges(
 	struct pci_bus *bus,
 	struct pbus_set_ranges_data *ranges
 	)
 {
+	struct pci_hba_data *hba = HBA_DATA(bus->sysdata);
+
 	/*
 	** I/O space may see busnumbers here. Something
 	** in the form of 0xbbxxxx where bb is the bus num
@@ -319,9 +360,20 @@
 	ranges->io_start = PCI_PORT_ADDR(ranges->io_start);
 	ranges->io_end   = PCI_PORT_ADDR(ranges->io_end);
 
+	/* Convert MMIO addr to PCI addr (undo global virtualization) */
+	ranges->mem_start = PCI_BUS_ADDR(hba, ranges->mem_start);
+	ranges->mem_end   = PCI_BUS_ADDR(hba, ranges->mem_end);
+
 	DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number,
 		ranges->io_start, ranges->io_end,
 		ranges->mem_start, ranges->mem_end);
+
+	/* KLUGE ALERT
+	** if this resource isn't linked to a "parent", then it seems
+	** to be a child of the HBA - lets link it in.
+	*/
+	pcibios_link_hba_resources(&hba->io_space, bus->resource[0]);
+	pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
 }
 
 #define MAX(val1, val2)   ((val1) > (val2) ? (val1) : (val2))
@@ -360,107 +412,15 @@
 	/*
 	** WARNING : caller is expected to update "end" field.
 	** We can't since it might really represent the *size*.
-	** The difference is "end = start + size" vs "end += size".
+	** The difference is "end = start + size" vs "end += start".
 	*/
 }
 
 
-#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
-
-void __devinit
-pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
-{
-	struct pbus_set_ranges_data inner;
-	struct pci_dev *dev;
-	struct pci_dev *bridge = bus->self;
-	struct list_head *ln;
-
-	/* set reasonable default "window" for pcibios_align_resource */
-	inner.io_start  = inner.io_end  = 0;
-	inner.mem_start = inner.mem_end = 0;
-
-	/* Collect information about how our direct children are layed out. */
-	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-		int i;
-		dev = pci_dev_b(ln);
-
-		/* Skip bridges here - we'll catch them below */
-		if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)
-			continue;
-
-		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-			struct resource res;
-			unsigned long size;
-
-			if (dev->resource[i].flags == 0)
-				continue;
-
-			memcpy(&res, &dev->resource[i], sizeof(res));
-			size = res.end - res.start + 1;
-
-			if (res.flags & IORESOURCE_IO) {
-				res.start = inner.io_end;
-				pcibios_align_resource(dev, &res, size);
-				inner.io_end += res.start + size;
-			} else if (res.flags & IORESOURCE_MEM) {
-				res.start = inner.mem_end;
-				pcibios_align_resource(dev, &res, size);
-				inner.mem_end = res.start + size;
-			}
-
-		DBG_RES("    %s  inner size %lx/%x IO %lx MEM %lx\n",
-			dev->slot_name,
-			size, res.flags, inner.io_end, inner.mem_end);
-		}
-	}
-
-	/* And for all of the subordinate busses. */
-	for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
-		pcibios_size_bridge(pci_bus_b(ln), &inner);
-
-	/* turn the ending locations into sizes (subtract start) */
-	inner.io_end -= inner.io_start - 1;
-	inner.mem_end -= inner.mem_start - 1;
-
-	/* Align the sizes up by bridge rules */
-	inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1;
-	inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1;
-
-	/* PPB - PCI bridge Device will normaller also have "outer" != NULL. */
-	if (bridge) {
-		/* Adjust the bus' allocation requirements */
-		/* PPB's pci device Bridge resources */
-
-		bus->resource[0] = &bridge->resource[PCI_BRIDGE_RESOURCES];
-		bus->resource[1] = &bridge->resource[PCI_BRIDGE_RESOURCES + 1];
-		
-		bus->resource[0]->start = bus->resource[1]->start  = 0;
-		bus->resource[0]->parent= bus->resource[1]->parent = NULL;
-
-		bus->resource[0]->end    = inner.io_end;
-		bus->resource[0]->flags  = IORESOURCE_IO;
-
-		bus->resource[1]->end    = inner.mem_end;
-		bus->resource[1]->flags  = IORESOURCE_MEM;
-	}
-
-	/* adjust parent's resource requirements */
-	if (outer) {
-		outer->io_end = ROUND_UP(outer->io_end, 4*1024);
-		outer->io_end += inner.io_end;
-
-		outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
-		outer->mem_end += inner.mem_end;
-	}
-}
-
-#undef ROUND_UP
-
-
 int __devinit
 pcibios_enable_device(struct pci_dev *dev)
 {
-	u16 cmd, old_cmd;
+	u16 cmd;
 	int idx;
 
 	/*
@@ -468,12 +428,13 @@
 	** enable all the same bits. We just make sure they are here.
 	*/
 	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
 
 	/*
 	** See if any resources have been allocated
+	** While "regular" PCI devices only use 0-5, Bridges use a few
+	** beyond that for window registers.
 	*/
-        for (idx=0; idx<6; idx++) {
+        for (idx=0; idx<DEVICE_COUNT_RESOURCE; idx++) {
 		struct resource *r = &dev->resource[idx];
 		if (r->flags & IORESOURCE_IO)
 			cmd |= PCI_COMMAND_IO;
@@ -482,7 +443,7 @@
 	}
 
 	/*
-	** System error and Parity Error reporting are enabled by default.
+	** Enable System error and Parity Error reporting by default.
 	** Devices that do NOT want those behaviors should clear them
 	** (eg PCI graphics, possibly networking).
 	** Interfaces like SCSI certainly should not. We want the
@@ -491,30 +452,48 @@
 	*/
 	cmd |= (PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
 
-	if (cmd != old_cmd) {
-		printk("PCIBIOS: Enabling device %s (%04x -> %04x)\n",
-			dev->slot_name, old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
+	/* If bridge/bus controller has FBB enabled, child must too. */
+	if (dev->bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
+		cmd |= PCI_COMMAND_FAST_BACK;
 
+	DBGC("PCIBIOS: Enabling device %s cmd 0x%04x\n", dev->slot_name, cmd);
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
 	return 0;
 }
 
-
-void __devinit
-pcibios_assign_unassigned_resources(struct pci_bus *bus)
+void __init
+pcibios_setup_host_bridge(struct pci_bus *bus)
 {
-	struct list_head *ln;
+	ASSERT(pci_bios != NULL);
 
-        for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next)
+#if 0
+	if (pci_bios)
 	{
-		pdev_assign_unassigned_resources(pci_dev_b(ln));
+		if (pci_bios->setup_host_bridge) {
+			(*pci_bios->setup_host_bridge)(bus);
+		}
 	}
+#endif
+}
 
-        /* And for all of the sub-busses.  */
-	for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
-		pcibios_assign_unassigned_resources(pci_bus_b(ln));
 
+/*
+** Mostly copied from drivers/pci/setup-bus.c:pci_assign_unassigned_resources()
+*/
+void __devinit
+pcibios_assign_unassigned_resources(struct pci_bus *bus)
+{
+	/* from drivers/pci/setup-bus.c */
+	extern void pbus_assign_resources(struct pci_bus *bus, struct pbus_set_ranges_data *ranges);
+
+	struct pbus_set_ranges_data ranges;
+
+	ranges.io_end = ranges.io_start
+				= bus->resource[0]->start + PCIBIOS_MIN_IO;
+	ranges.mem_end = ranges.mem_start
+				= bus->resource[1]->start + PCIBIOS_MIN_MEM;
+	ranges.found_vga = 0;
+	pbus_assign_resources(bus, &ranges);
 }
 
 /*
@@ -522,14 +501,9 @@
 */
 void pcibios_register_hba(struct pci_hba_data *hba)
 {
-	hba->next = hba_list;
-	hba_list = hba;
-
-	ASSERT(hba_count < PCI_HBA_MAX);
+	ASSERT(pci_hba_count < PCI_HBA_MAX);
 
-	/*
-	** pci_port->in/out() uses parisc_pci_hba to lookup parameter.
-	*/
-	parisc_pci_hba[hba_count] = hba;
-	hba->hba_num = hba_count++;
+	/* pci_port->in/out() uses parisc_pci_hba to lookup parameter. */
+	parisc_pci_hba[pci_hba_count] = hba;
+	hba->hba_num = pci_hba_count++;
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/pdc.c linux/arch/parisc/kernel/pdc.c
--- linux.orig/arch/parisc/kernel/pdc.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/pdc.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,217 +0,0 @@
-/* arch/parisc/kernel/pdc.c  - safe pdc access routines
- *
- * Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
- * portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
- *
- * only these routines should be used out of the real kernel (i.e. everything
- * using virtual addresses) for obvious reasons */
-
-/*	I think it would be in everyone's best interest to follow this
- *	guidelines when writing PDC wrappers:
- *
- *	 - the name of the pdc wrapper should match one of the macros
- *	   used for the first two arguments
- *	 - don't use caps for random parts of the name
- *	 - use ASSERT_ALIGN to ensure the aligment of the arguments is
- *	   correct
- *	 - use __pa() to convert virtual (kernel) pointers to physical
- *	   ones.
- *	 - the name of the struct used for pdc return values should equal
- *	   one of the macros used for the first two arguments to the
- *	   corresponding PDC call
- *	 - keep the order of arguments
- *	 - don't be smart (setting trailing NUL bytes for strings, return
- *	   something useful even if the call failed) unless you are sure
- *	   it's not going to affect functionality or performance
- *
- *	Example:
- *	int pdc_cache_info(struct pdc_cache_info *cache_info )
- *	{
- *		ASSERT_ALIGN(cache_info, 8);
- *	
- *		return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
- *	}
- *					prumpf	991016	
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-
-#include <asm/page.h>
-#include <asm/pdc.h>
-#include <asm/real.h>
-#include <asm/system.h>
-
-
-#define ASSERT_ALIGN(ptr, align)					\
-	do { if(((unsigned long)(ptr)) & (align-1)) {			\
-		printk("PDC: %s:%d  %s() called with "	\
-			"unaligned argument from %p", __FILE__, __LINE__, \
-			__FUNCTION__, __builtin_return_address(0));	\
-									\
-		return -1;						\
-	} } while(0)
-	
-/* verify address can be accessed without an HPMC */
-int pdc_add_valid(void *address)
-{
-	ASSERT_ALIGN(address, 4);
-
-	return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address);
-}
-
-#if 0
-int pdc_chassis_warn(struct pdc_chassis_warn *address)
-{
-	ASSERT_ALIGN(address, 4);
-
-	return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0);
-}
-#endif
-
-int pdc_chassis_disp(unsigned long disp)
-{
-	return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
-}
-
-int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len)
-{
-	ASSERT_ALIGN(pdc_result, 4);
-	ASSERT_ALIGN(chassis_info, 4);
-	return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO, 
-	        __pa(pdc_result), __pa(chassis_info), len);
-}
-
-int pdc_hpa_processor(void *address)
-{
-	/* We're using 0 for the last parameter just to make sure.
-	   It's actually HVERSION dependant.  And remember, life is
-	   hard without a backspace. */
-	ASSERT_ALIGN(address, 4);
-
-	return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0);
-}
-
-#if 0
-int pdc_hpa_modules(void *address)
-{
-	return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address);
-}
-#endif
-
-int pdc_iodc_read(void *address, void * hpa, unsigned int index,
-	void * iodc_data, unsigned int iodc_data_size)
-{
-	ASSERT_ALIGN(address, 4);
-	ASSERT_ALIGN(iodc_data, 8);
-	return mem_pdc_call(PDC_IODC, PDC_IODC_READ, 
-		__pa(address), hpa, index, __pa(iodc_data), iodc_data_size);
-}
-
-
-int pdc_system_map_find_mods(void *pdc_mod_info, 
-	void *mod_path, int index)
-{
-	return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE,
-		__pa(pdc_mod_info), __pa(mod_path), (long)index);
-}
-
-
-int pdc_model_info(struct pdc_model *model) {
-	ASSERT_ALIGN(model, 8);
-	return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0);
-}
-
-/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */ 
-int pdc_model_sysmodel(char * name)
-{
-	struct pdc_model_sysmodel sys_model;
-	int retval;
-	
-	ASSERT_ALIGN(&sys_model, 8);
-	ASSERT_ALIGN(name, 4);
-
-	sys_model.mod_len = 0;
-	retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model),
-		    OS_ID_HPUX,__pa(name));
-	
-	if (retval == PDC_RET_OK) 
-	    name[sys_model.mod_len] = '\0'; /* add trailing '\0' */
-	else
-	    name[0] = 0;
-	
-	return retval;
-}
-
-/* id: 0 = cpu revision, 1 = boot-rom-version */
-int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) {
-	return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id);
-}
-
-int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) {
-	cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */
-	return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0);  /* 6="return CPU ID" */
-}
-
-int pdc_cache_info(struct pdc_cache_info *cache_info) {
-	ASSERT_ALIGN(cache_info, 8);
-
-	return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
-}
-
-#ifndef __LP64__
-int pdc_btlb_info( struct pdc_btlb_info *btlb ) {
-	int status;
-	status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0);
-	if (status<0) btlb->max_size = 0;
-	return status;
-}
-
-int pdc_mem_map_hpa(void *r_addr, void *mod_path) {
-	return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA,
-		__pa(r_addr),__pa(mod_path));
-}
-
-int pdc_lan_station_id(char *lan_addr, void *net_hpa) {
-	struct pdc_lan_station_id id;
-	unsigned char *addr;
-	
-	if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
-			__pa(&id), net_hpa) < 0)
-		addr = 0;	/* FIXME: else read MAC from NVRAM */
-	    else
-		addr = id.addr;
-	if (addr)
-		memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE);
-	    else
-		memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
-	return (addr != 0);
-}
-#endif
-
-
-/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */
-int pdc_pci_irt_size(void *r_addr, void *hpa)
-{
-	return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
-		__pa(r_addr), hpa);
-
-}
-
-int pdc_pci_irt(void *r_addr, void *hpa, void *tbl)
-{
-	return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
-		__pa(r_addr), hpa, __pa(tbl));
-}
-
-/* access the TOD clock */
-int pdc_tod_read(struct pdc_tod *tod)
-{
-	ASSERT_ALIGN(tod, 8);
-	return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0);
-}
-
-int pdc_tod_set(unsigned long sec, unsigned long usec)
-{
-	return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/pdc_cons.c linux/arch/parisc/kernel/pdc_cons.c
--- linux.orig/arch/parisc/kernel/pdc_cons.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/parisc/kernel/pdc_cons.c	2002-08-12 22:14:09.000000000 +0000
@@ -1,100 +1,49 @@
+/*
+ *  linux/arch/parisc/kernel/pdc_console.c
+ *
+ *  The PDC console is a simple console, which can be used for debugging 
+ *  boot related problems on HP PA-RISC machines.
+ *
+ *  This code uses the ROM (=PDC) based functions to read and write characters
+ *  from and to PDC's boot path.
+ *  Since all character read from that path must be polled, this code never
+ *  can or will be a fully functional linux console.
+ */
+
+/* Define EARLY_BOOTUP_DEBUG to debug kernel related boot problems. 
+ * On production kernels EARLY_BOOTUP_DEBUG should be undefined. */
+#undef EARLY_BOOTUP_DEBUG
+
+
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <asm/page.h>
 #include <asm/types.h>
 #include <asm/system.h>
-#include <asm/pdc.h>	/* for iodc_call() proto and friends */
-#include <asm/real.h>
+#include <asm/pdc.h>		/* for iodc_call() proto and friends */
 
-static int __attribute__((aligned(8)))   iodc_retbuf[32];
-static char __attribute__((aligned(64))) iodc_dbuf[4096];
-
-/*
- * pdc_putc:
- * Console character print using IODC.
- *
- * Note that only these special chars are architected for console IODC io:
- * BEL, BS, CR, and LF. Others are passed through.
- * Since the HP console requires CR+LF to perform a 'newline', we translate
- * "\n" to "\r\n".
- */
-
-static int posx;	/* for simple TAB-Simulation... */
-
-/* XXX Should we spinlock posx usage */
-
-void pdc_putc(unsigned char c)
-{
-	unsigned int n;
-	unsigned long flags;
-
-	switch (c) {
-	case '\n':
-		iodc_dbuf[0] = '\r'; 
-		iodc_dbuf[1] = '\n';
-               	n = 2;
-               	posx = 0;
-		break;
-	case '\t':
-		pdc_putc(' ');
-		while (posx & 7) 	/* expand TAB */
-			pdc_putc(' ');
-		return;		/* return since IODC can't handle this */
-	case '\b':
-		posx-=2;		/* BS */
-	default:
-		iodc_dbuf[0] = c;
-		n = 1;
-		posx++;
-		break;
-	}
-	{
-		real32_call(PAGE0->mem_cons.iodc_io,
-			(unsigned long)PAGE0->mem_cons.hpa, ENTRY_IO_COUT,
-			PAGE0->mem_cons.spa, __pa(PAGE0->mem_cons.dp.layers),
-			__pa(iodc_retbuf), 0, __pa(iodc_dbuf), n, 0);
-	}
-}
 
 static void pdc_console_write(struct console *co, const char *s, unsigned count)
 {
 	while(count--)
-		pdc_putc(*s++);
+		pdc_iodc_putc(*s++);
 }
 
-int pdc_console_wait_key(struct console *co)
+void pdc_outc(unsigned char c)
 {
-	int ch = 'X';
-	int status;
-
-	/* Bail if no console input device. */
-	if (!PAGE0->mem_kbd.iodc_io)
-		return 0;
-	
-	/* wait for a keyboard (rs232)-input */
-	do {
-		unsigned long flags;
-
-		save_flags(flags);
-		cli();
-		status = real32_call(PAGE0->mem_kbd.iodc_io,
-			(unsigned long)PAGE0->mem_kbd.hpa, ENTRY_IO_CIN,
-			PAGE0->mem_kbd.spa, __pa(PAGE0->mem_kbd.dp.layers),
-			__pa(iodc_retbuf), 0, __pa(iodc_dbuf), 1, 0);
-		restore_flags(flags);
-		ch = *iodc_dbuf;	/* save the character directly to ch */
-	} while (*iodc_retbuf == 0);	/* wait for a key */
-	return ch;
+	pdc_iodc_outc(c);
 }
 
-int pdc_getc(void)
+
+int pdc_console_poll_key(struct console *co)
 {
-	return pdc_console_wait_key(NULL);
+	return pdc_iodc_getc();
 }
 
 static int pdc_console_setup(struct console *co, char *options)
@@ -102,17 +51,34 @@
 	return 0;
 }
 
+#ifdef CONFIG_PDC_CONSOLE
+static kdev_t pdc_console_device (struct console *c)
+{
+        return MKDEV(PDCCONS_MAJOR, 0);
+}
+#endif
+
+#ifdef CONFIG_PDC_CONSOLE
+#define PDC_CONSOLE_DEVICE pdc_console_device
+#else
+#define PDC_CONSOLE_DEVICE NULL
+#endif
+
 static struct console pdc_cons = {
 	name:		"ttyB",
 	write:		pdc_console_write,
+ 	device:		PDC_CONSOLE_DEVICE,
 	setup:		pdc_console_setup,
-	flags:		CON_PRINTBUFFER|CON_ENABLED,  // |CON_CONSDEV,
+	flags:		CON_BOOT|CON_PRINTBUFFER|CON_ENABLED,
 	index:		-1,
 };
 
 static int pdc_console_initialized;
 
-void pdc_console_init(void)
+extern unsigned long con_start;	/* kernel/printk.c */
+extern unsigned long log_end;	/* kernel/printk.c */
+  
+static void pdc_console_init_force(void)
 {
 	if (pdc_console_initialized)
 		return;
@@ -122,23 +88,32 @@
 	if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
 		memcpy(&PAGE0->mem_kbd, &PAGE0->mem_cons, sizeof(PAGE0->mem_cons));
 
-	pdc_console_write(0, "PDC Console Initialized\n", 24);
 	/* register the pdc console */
 	register_console(&pdc_cons);
 }
 
+void pdc_console_init(void)
+{
+#if defined(EARLY_BOOTUP_DEBUG) || defined(CONFIG_PDC_CONSOLE)
+	pdc_console_init_force();
+#endif
+#ifdef EARLY_BOOTUP_DEBUG
+	printk(KERN_INFO "Initialized PDC Console for debugging.\n");
+#endif
+}
+
 
 /* Unregister the pdc console with the printk console layer */
 void pdc_console_die(void)
 {
-	printk("Switching from PDC console\n");
 	if (!pdc_console_initialized)
 		return;
 	--pdc_console_initialized;
-	
-#ifdef CONFIG_VT_CONSOLE
-	schedule_console_callback();
-#endif
+
+	printk(KERN_INFO "Switching from PDC console\n");
+
+	/* Don't repeat what we've already printed */
+	con_start = log_end;
 
 	unregister_console(&pdc_cons);
 }
@@ -155,17 +130,17 @@
 void pdc_console_restart(void)
 {
 	struct console *console;
-	extern int log_size;
 
 	if (pdc_console_initialized)
 		return;
 
-	while ((console = console_drivers) != (struct console *)0)
+	while ((console = console_drivers) != NULL)
 		unregister_console(console_drivers);
 
-	log_size = 0;
-	pdc_console_init();
-	printk("Switched to PDC console\n");
-	return;
+	/* Don't repeat what we've already printed */
+	con_start = log_end;
+	
+	/* force registering the pdc console */
+	pdc_console_init_force();
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/perf.c linux/arch/parisc/kernel/perf.c
--- linux.orig/arch/parisc/kernel/perf.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/perf.c	2002-08-12 22:14:00.000000000 +0000
@@ -0,0 +1,838 @@
+/*
+ *  Parisc performance counters
+ *  Copyright (C) 2001 Randolph Chung <tausq@debian.org>
+ *
+ *  This code is derived, with permission, from HP/UX sources.
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *  Edited comment from original sources:
+ *
+ *  This driver programs the PCX-U/PCX-W performance counters
+ *  on the PA-RISC 2.0 chips.  The driver keeps all images now
+ *  internally to the kernel to hopefully eliminate the possiblity
+ *  of a bad image halting the CPU.  Also, there are different
+ *  images for the PCX-W and later chips vs the PCX-U chips.
+ *
+ *  Only 1 process is allowed to access the driver at any time,
+ *  so the only protection that is needed is at open and close.
+ *  A variable "perf_enabled" is used to hold the state of the
+ *  driver.  The spinlock "perf_lock" is used to protect the
+ *  modification of the state during open/close operations so
+ *  multiple processes don't get into the driver simultaneously.
+ *
+ *  This driver accesses the processor directly vs going through
+ *  the PDC INTRIGUE calls.  This is done to eliminate bugs introduced
+ *  in various PDC revisions.  The code is much more maintainable
+ *  and reliable this way vs having to debug on every version of PDC
+ *  on every box. 
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+
+#include <asm/gsc.h>
+#include <asm/uaccess.h>
+#include <asm/perf.h>
+#include <asm/processor.h>
+
+#include "perf_images.h"
+
+#define MAX_RDR_WORDS	24
+#define PERF_VERSION	2	/* derived from hpux's PI v2 interface */
+
+/* definition of RDR regs */
+struct rdr_tbl_ent {
+	uint16_t	width;
+	uint8_t		num_words;
+	uint8_t		write_control;
+};
+
+static int perf_processor_interface = UNKNOWN_INTF;
+static int perf_enabled = 0;
+static spinlock_t perf_lock;
+struct parisc_device *cpu_device = NULL;
+
+/* RDRs to write for PCX-W */
+static int perf_rdrs_W[] = 
+	{ 0, 1, 4, 5, 6, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
+
+/* RDRs to write for PCX-U */
+static int perf_rdrs_U[] =
+	{ 0, 1, 4, 5, 6, 7, 16, 17, 18, 20, 21, 22, 23, 24, 25, -1 };
+
+/* RDR register descriptions for PCX-W */
+static struct rdr_tbl_ent perf_rdr_tbl_W[] = {
+	{ 19,	1,	8 },   /* RDR 0 */
+	{ 16,	1,	16 },  /* RDR 1 */
+	{ 72,	2,	0 },   /* RDR 2 */
+	{ 81,	2,	0 },   /* RDR 3 */
+	{ 328,	6,	0 },   /* RDR 4 */
+	{ 160,	3,	0 },   /* RDR 5 */
+	{ 336,	6,	0 },   /* RDR 6 */
+	{ 164,	3,	0 },   /* RDR 7 */
+	{ 0,	0,	0 },   /* RDR 8 */
+	{ 35,	1,	0 },   /* RDR 9 */
+	{ 6,	1,	0 },   /* RDR 10 */
+	{ 18,	1,	0 },   /* RDR 11 */
+	{ 13,	1,	0 },   /* RDR 12 */
+	{ 8,	1,	0 },   /* RDR 13 */
+	{ 8,	1,	0 },   /* RDR 14 */
+	{ 8,	1,	0 },   /* RDR 15 */
+	{ 1530,	24,	0 },   /* RDR 16 */
+	{ 16,	1,	0 },   /* RDR 17 */
+	{ 4,	1,	0 },   /* RDR 18 */
+	{ 0,	0,	0 },   /* RDR 19 */
+	{ 152,	3,	24 },  /* RDR 20 */
+	{ 152,	3,	24 },  /* RDR 21 */
+	{ 233,	4,	48 },  /* RDR 22 */
+	{ 233,	4,	48 },  /* RDR 23 */
+	{ 71,	2,	0 },   /* RDR 24 */
+	{ 71,	2,	0 },   /* RDR 25 */
+	{ 11,	1,	0 },   /* RDR 26 */
+	{ 18,	1,	0 },   /* RDR 27 */
+	{ 128,	2,	0 },   /* RDR 28 */
+	{ 0,	0,	0 },   /* RDR 29 */
+	{ 16,	1,	0 },   /* RDR 30 */
+	{ 16,	1,	0 },   /* RDR 31 */
+};
+
+/* RDR register descriptions for PCX-U */
+static struct rdr_tbl_ent perf_rdr_tbl_U[] = {
+	{ 19,	1,	8 },              /* RDR 0 */
+	{ 32,	1,	16 },             /* RDR 1 */
+	{ 20,	1,	0 },              /* RDR 2 */
+	{ 0,	0,	0 },              /* RDR 3 */
+	{ 344,	6,	0 },              /* RDR 4 */
+	{ 176,	3,	0 },              /* RDR 5 */
+	{ 336,	6,	0 },              /* RDR 6 */
+	{ 0,	0,	0 },              /* RDR 7 */
+	{ 0,	0,	0 },              /* RDR 8 */
+	{ 0,	0,	0 },              /* RDR 9 */
+	{ 28,	1,	0 },              /* RDR 10 */
+	{ 33,	1,	0 },              /* RDR 11 */
+	{ 0,	0,	0 },              /* RDR 12 */
+	{ 230,	4,	0 },              /* RDR 13 */
+	{ 32,	1,	0 },              /* RDR 14 */
+	{ 128,	2,	0 },              /* RDR 15 */
+	{ 1494,	24,	0 },              /* RDR 16 */
+	{ 18,	1,	0 },              /* RDR 17 */
+	{ 4,	1,	0 },              /* RDR 18 */
+	{ 0,	0,	0 },              /* RDR 19 */
+	{ 158,	3,	24 },             /* RDR 20 */
+	{ 158,	3,	24 },             /* RDR 21 */
+	{ 194,	4,	48 },             /* RDR 22 */
+	{ 194,	4,	48 },             /* RDR 23 */
+	{ 71,	2,	0 },              /* RDR 24 */
+	{ 71,	2,	0 },              /* RDR 25 */
+	{ 28,	1,	0 },              /* RDR 26 */
+	{ 33,	1,	0 },              /* RDR 27 */
+	{ 88,	2,	0 },              /* RDR 28 */
+	{ 32,	1,	0 },              /* RDR 29 */
+	{ 24,	1,	0 },              /* RDR 30 */
+	{ 16,	1,	0 },              /* RDR 31 */
+};
+
+/*
+ * A non-zero write_control in the above tables is a byte offset into
+ * this array.
+ */
+static uint64_t perf_bitmasks[] = {
+	0x0000000000000000,     /* first dbl word must be zero */
+	0xfdffe00000000000,     /* RDR0 bitmask */
+	0x003f000000000000,     /* RDR1 bitmask */
+	0x00ffffffffffffff,     /* RDR20-RDR21 bitmask (152 bits) */
+	0xffffffffffffffff,
+	0xfffffffc00000000,
+	0xffffffffffffffff,     /* RDR22-RDR23 bitmask (233 bits) */
+	0xffffffffffffffff,
+	0xfffffffffffffffc,
+	0xff00000000000000
+};
+
+/*
+ * Write control bitmasks for Pa-8700 processor given
+ * somethings have changed slightly.
+ */
+static uint64_t perf_bitmasks_piranha[] = {
+	0x0000000000000000,     /* first dbl word must be zero */
+	0xfdffe00000000000,     /* RDR0 bitmask */
+	0x003f000000000000,     /* RDR1 bitmask */
+	0x00ffffffffffffff,     /* RDR20-RDR21 bitmask (158 bits) */
+	0xffffffffffffffff,
+	0xfffffffc00000000,
+	0xffffffffffffffff,     /* RDR22-RDR23 bitmask (210 bits) */
+	0xffffffffffffffff,
+	0xffffffffffffffff,
+	0xfffc000000000000
+};
+
+static uint64_t *bitmask_array;   /* array of bitmasks to use */
+
+/******************************************************************************
+ * Function Prototypes
+ *****************************************************************************/
+static int perf_config(uint32_t *image_ptr);
+static int perf_release(struct inode *inode, struct file *file);
+static int perf_open(struct inode *inode, struct file *file);
+static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos);
+static ssize_t perf_write(struct file *file, const char *buf, size_t count, 
+	loff_t *ppos);
+static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	unsigned long arg);
+static void perf_start_counters(void);
+static int perf_stop_counters(uint32_t *raddr);
+static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num);
+static int perf_rdr_read_ubuf(uint32_t	rdr_num, uint64_t *buffer);
+static int perf_rdr_clear(uint32_t rdr_num);
+static int perf_write_image(uint64_t *memaddr);
+static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer);
+
+/* External Assembly Routines */
+extern uint64_t perf_rdr_shift_in_W (uint32_t rdr_num, uint16_t width);
+extern uint64_t perf_rdr_shift_in_U (uint32_t rdr_num, uint16_t width);
+extern void perf_rdr_shift_out_W (uint32_t rdr_num, uint64_t buffer);
+extern void perf_rdr_shift_out_U (uint32_t rdr_num, uint64_t buffer);
+extern void perf_intrigue_enable_perf_counters (void);
+extern void perf_intrigue_disable_perf_counters (void);
+
+/******************************************************************************
+ * Function Definitions
+ *****************************************************************************/
+
+
+/*
+ * configure:
+ *
+ * Configure the cpu with a given data image.  First turn off the counters, 
+ * then download the image, then turn the counters back on.
+ */
+static int perf_config(uint32_t *image_ptr)
+{
+	long error;
+	uint32_t raddr[4];
+
+	/* Stop the counters*/
+	error = perf_stop_counters(raddr);
+	if (error != 0) {
+		printk("perf_config: perf_stop_counters = %ld\n", error);
+		return -EINVAL; 
+	}
+
+printk("Preparing to write image\n");
+	/* Write the image to the chip */
+	error = perf_write_image((uint64_t *)image_ptr);
+	if (error != 0) {
+		printk("perf_config: DOWNLOAD = %ld\n", error);
+		return -EINVAL; 
+	}
+
+printk("Preparing to start counters\n");
+
+	/* Start the counters */
+	perf_start_counters();
+
+	return sizeof(uint32_t);
+}
+
+/*
+ * Open the device and initialize all of it's memory.  The device is only 
+ * opened once, but can be "queried" by multiple processes that know its
+ * file descriptor.
+ */
+static int perf_open(struct inode *inode, struct file *file)
+{
+	spin_lock(&perf_lock);
+	if (perf_enabled) {
+		spin_unlock(&perf_lock);
+		return -EBUSY;
+	}
+	perf_enabled = 1;
+ 	spin_unlock(&perf_lock);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Close the device.
+ */
+static int perf_release(struct inode *inode, struct file *file)
+{
+	spin_lock(&perf_lock);
+	perf_enabled = 0;
+	spin_unlock(&perf_lock);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Read does nothing for this driver
+ */
+static ssize_t perf_read(struct file *file, char *buf, size_t cnt, loff_t *ppos)
+{
+	return 0;
+}
+
+/*
+ * write:
+ *
+ * This routine downloads the image to the chip.  It must be
+ * called on the processor that the download should happen
+ * on.
+ */
+static ssize_t perf_write(struct file *file, const char *buf, size_t count, 
+	loff_t *ppos)
+{
+	int err;
+	size_t image_size;
+	uint32_t image_type;
+	uint32_t interface_type;
+	uint32_t test;
+
+	if (perf_processor_interface == ONYX_INTF) 
+		image_size = PCXU_IMAGE_SIZE;
+	else if (perf_processor_interface == CUDA_INTF) 
+		image_size = PCXW_IMAGE_SIZE;
+	else 
+		return -EFAULT;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (count != sizeof(uint32_t))
+		return -EIO;
+
+	if ((err = copy_from_user(&image_type, buf, sizeof(uint32_t))) != 0) 
+		return err;
+
+	/* Get the interface type and test type */
+   	interface_type = (image_type >> 16) & 0xffff;
+	test           = (image_type & 0xffff);
+
+	/* Make sure everything makes sense */
+
+	/* First check the machine type is correct for
+	   the requested image */
+        if (((perf_processor_interface == CUDA_INTF) &&
+		       (interface_type != CUDA_INTF)) ||
+	    ((perf_processor_interface == ONYX_INTF) &&
+	               (interface_type != ONYX_INTF))) 
+		return -EINVAL;
+
+	/* Next check to make sure the requested image
+	   is valid */
+	if (((interface_type == CUDA_INTF) && 
+		       (test >= MAX_CUDA_IMAGES)) ||
+	    ((interface_type == ONYX_INTF) && 
+		       (test >= MAX_ONYX_IMAGES))) 
+		return -EINVAL;
+
+	/* Copy the image into the processor */
+	if (interface_type == CUDA_INTF) 
+		return perf_config(cuda_images[test]);
+	else
+		return perf_config(onyx_images[test]);
+
+	return count;
+}
+
+/*
+ * Patch the images that need to know the IVA addresses.
+ */
+static void perf_patch_images(void)
+{
+#if 0 /* FIXME!! */
+/* 
+ * NOTE:  this routine is VERY specific to the current TLB image.
+ * If the image is changed, this routine might also need to be changed.
+ */
+	extern void $i_itlb_miss_2_0();
+	extern void $i_dtlb_miss_2_0();
+	extern void PA2_0_iva();
+
+	/* 
+	 * We can only use the lower 32-bits, the upper 32-bits should be 0
+	 * anyway given this is in the kernel 
+	 */
+	uint32_t itlb_addr  = (uint32_t)&($i_itlb_miss_2_0);
+	uint32_t dtlb_addr  = (uint32_t)&($i_dtlb_miss_2_0);
+	uint32_t IVAaddress = (uint32_t)&PA2_0_iva;
+
+	if (perf_processor_interface == ONYX_INTF) {
+		/* clear last 2 bytes */
+		onyx_images[TLBMISS][15] &= 0xffffff00;  
+		/* set 2 bytes */
+		onyx_images[TLBMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
+		onyx_images[TLBMISS][16] = (dtlb_addr << 8)&0xffffff00;
+		onyx_images[TLBMISS][17] = itlb_addr;
+
+		/* clear last 2 bytes */
+		onyx_images[TLBHANDMISS][15] &= 0xffffff00;  
+		/* set 2 bytes */
+		onyx_images[TLBHANDMISS][15] |= (0x000000ff&((dtlb_addr) >> 24));
+		onyx_images[TLBHANDMISS][16] = (dtlb_addr << 8)&0xffffff00;
+		onyx_images[TLBHANDMISS][17] = itlb_addr;
+
+		/* clear last 2 bytes */
+		onyx_images[BIG_CPI][15] &= 0xffffff00;  
+		/* set 2 bytes */
+		onyx_images[BIG_CPI][15] |= (0x000000ff&((dtlb_addr) >> 24));
+		onyx_images[BIG_CPI][16] = (dtlb_addr << 8)&0xffffff00;
+		onyx_images[BIG_CPI][17] = itlb_addr;
+
+	    onyx_images[PANIC][15] &= 0xffffff00;  /* clear last 2 bytes */
+	 	onyx_images[PANIC][15] |= (0x000000ff&((IVAaddress) >> 24)); /* set 2 bytes */
+		onyx_images[PANIC][16] = (IVAaddress << 8)&0xffffff00;
+
+
+	} else if (perf_processor_interface == CUDA_INTF) {
+		/* Cuda interface */
+		cuda_images[TLBMISS][16] =  
+			(cuda_images[TLBMISS][16]&0xffff0000) |
+			((dtlb_addr >> 8)&0x0000ffff);
+		cuda_images[TLBMISS][17] = 
+			((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
+		cuda_images[TLBMISS][18] = (itlb_addr << 16)&0xffff0000;
+
+		cuda_images[TLBHANDMISS][16] = 
+			(cuda_images[TLBHANDMISS][16]&0xffff0000) |
+			((dtlb_addr >> 8)&0x0000ffff);
+		cuda_images[TLBHANDMISS][17] = 
+			((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
+		cuda_images[TLBHANDMISS][18] = (itlb_addr << 16)&0xffff0000;
+
+		cuda_images[BIG_CPI][16] = 
+			(cuda_images[BIG_CPI][16]&0xffff0000) |
+			((dtlb_addr >> 8)&0x0000ffff);
+		cuda_images[BIG_CPI][17] = 
+			((dtlb_addr << 24)&0xff000000) | ((itlb_addr >> 16)&0x000000ff);
+		cuda_images[BIG_CPI][18] = (itlb_addr << 16)&0xffff0000;
+	} else {
+		/* Unknown type */
+	}
+#endif
+}
+
+
+/*
+ * ioctl routine
+ * All routines effect the processor that they are executed on.  Thus you 
+ * must be running on the processor that you wish to change.
+ */
+
+static int perf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	long error_start;
+	uint32_t raddr[4];	
+
+	switch (cmd) {
+
+	    case PA_PERF_ON:
+			/* Start the counters */
+			perf_start_counters();
+			return 0;
+
+	    case PA_PERF_OFF:
+			error_start = perf_stop_counters(raddr);
+			if (error_start != 0) {
+				printk(KERN_ERR "perf_off: perf_stop_counters = %ld\n", error_start);
+				return -EFAULT;	
+			}
+
+			/* copy out the Counters */
+			if (copy_to_user((void *)arg, raddr, 
+					sizeof (raddr)) != 0) {
+				return -EFAULT;
+			}
+			return 0;
+
+	    case PA_PERF_VERSION:
+  	  		/* Return the version # */
+			return put_user(PERF_VERSION, (int *)arg);
+
+	    default:
+  	 		break;
+	}
+	return -ENOTTY;
+}
+
+static struct file_operations perf_fops = {
+	llseek: no_llseek,
+	read: perf_read,
+	write: perf_write,
+	ioctl: perf_ioctl,
+	open: perf_open,
+	release: perf_release
+};
+	
+static struct miscdevice perf_dev = {
+	MISC_DYNAMIC_MINOR,
+	PA_PERF_DEV,
+	&perf_fops
+};
+
+/*
+ * Initialize the module
+ */
+static int __init perf_init(void)
+{
+	/* Determine correct processor interface to use */
+	bitmask_array = perf_bitmasks;
+
+	if (boot_cpu_data.cpu_type == pcxu ||
+	    boot_cpu_data.cpu_type == pcxu_) {
+		perf_processor_interface = ONYX_INTF;
+	} else if (boot_cpu_data.cpu_type == pcxw ||
+		 boot_cpu_data.cpu_type == pcxw_ ||
+		 boot_cpu_data.cpu_type == pcxw2) {
+		perf_processor_interface = CUDA_INTF;
+		if (boot_cpu_data.cpu_type == pcxw2) 
+			bitmask_array = perf_bitmasks_piranha;
+	} else {
+		perf_processor_interface = UNKNOWN_INTF;
+		printk("Performance monitoring counters not supported on this processor\n");
+		return -ENODEV;
+	}
+
+	/* Patch the images to match the system */
+    	perf_patch_images();
+
+	spin_lock_init(&perf_lock);
+	misc_register(&perf_dev);
+
+	/* TODO: this only lets us access the first cpu.. what to do for SMP? */
+	cpu_device = cpu_data[0].dev;
+	printk("Performance monitoring counters enabled for %s\n",
+		cpu_data[0].dev->name);
+
+	return 0;
+}
+
+/*
+ * perf_start_counters(void)
+ *
+ * Start the counters.
+ */
+static void perf_start_counters(void)
+{
+	/* Enable performance monitor counters */
+	perf_intrigue_enable_perf_counters();
+}
+
+/*
+ * perf_stop_counters
+ *
+ * Stop the performance counters and save counts
+ * in a per_processor array.
+ */
+static int perf_stop_counters(uint32_t *raddr)
+{
+	uint64_t userbuf[MAX_RDR_WORDS];
+
+	/* Disable performance counters */
+	perf_intrigue_disable_perf_counters();
+
+	if (perf_processor_interface == ONYX_INTF) {
+		uint64_t tmp64;
+		/*
+		 * Read the counters
+		 */
+		if (!perf_rdr_read_ubuf(16, userbuf))
+			return -13;
+
+		/* Counter0 is bits 1398 thru 1429 */
+		tmp64 =  (userbuf[21] << 22) & 0x00000000ffc00000;
+		tmp64 |= (userbuf[22] >> 42) & 0x00000000003fffff;
+		/* OR sticky0 (bit 1430) to counter0 bit 32 */
+		tmp64 |= (userbuf[22] >> 10) & 0x0000000080000000;
+		raddr[0] = (uint32_t)tmp64;
+
+		/* Counter1 is bits 1431 thru 1462 */
+		tmp64 =  (userbuf[22] >> 9) & 0x00000000ffffffff;
+		/* OR sticky1 (bit 1463) to counter1 bit 32 */
+		tmp64 |= (userbuf[22] << 23) & 0x0000000080000000;
+		raddr[1] = (uint32_t)tmp64;
+
+		/* Counter2 is bits 1464 thru 1495 */
+		tmp64 =  (userbuf[22] << 24) & 0x00000000ff000000;
+		tmp64 |= (userbuf[23] >> 40) & 0x0000000000ffffff;
+		/* OR sticky2 (bit 1496) to counter2 bit 32 */
+		tmp64 |= (userbuf[23] >> 8) & 0x0000000080000000;
+		raddr[2] = (uint32_t)tmp64;
+		
+		/* Counter3 is bits 1497 thru 1528 */
+		tmp64 =  (userbuf[23] >> 7) & 0x00000000ffffffff;
+		/* OR sticky3 (bit 1529) to counter3 bit 32 */
+		tmp64 |= (userbuf[23] << 25) & 0x0000000080000000;
+		raddr[3] = (uint32_t)tmp64;
+
+		/*
+		 * Zero out the counters
+		 */
+
+		/*
+		 * The counters and sticky-bits comprise the last 132 bits
+		 * (1398 - 1529) of RDR16 on a U chip.  We'll zero these
+		 * out the easy way: zero out last 10 bits of dword 21,
+		 * all of dword 22 and 58 bits (plus 6 don't care bits) of
+		 * dword 23.
+		 */
+		userbuf[21] &= 0xfffffffffffffc00;	/* 0 to last 10 bits */
+		userbuf[22] = 0;
+		userbuf[23] = 0;
+
+		/* 
+		 * Write back the zero'ed bytes + the image given
+		 * the read was destructive.
+		 */
+		perf_rdr_write(16, userbuf);
+	} else {
+
+		/*
+		 * Read RDR-15 which contains the counters and sticky bits 
+		 */
+		if (!perf_rdr_read_ubuf(15, userbuf)) {
+			return -13;
+		}
+
+		/* 
+		 * Clear out the counters
+		 */
+		perf_rdr_clear(15);
+
+		/*
+		 * Copy the counters 
+		 */
+		raddr[0] = (uint32_t)((userbuf[0] >> 32) & 0x00000000ffffffffUL);
+		raddr[1] = (uint32_t)(userbuf[0] & 0x00000000ffffffffUL);
+		raddr[2] = (uint32_t)((userbuf[1] >> 32) & 0x00000000ffffffffUL);
+		raddr[3] = (uint32_t)(userbuf[1] & 0x00000000ffffffffUL);
+	}
+ 
+	return 0;
+}
+
+/*
+ * perf_rdr_get_entry
+ *
+ * Retrieve a pointer to the description of what this
+ * RDR contains.
+ */
+static struct rdr_tbl_ent * perf_rdr_get_entry(uint32_t rdr_num)
+{
+	if (perf_processor_interface == ONYX_INTF) {
+		return &perf_rdr_tbl_U[rdr_num];
+	} else {
+		return &perf_rdr_tbl_W[rdr_num];
+	}
+}
+
+/*
+ * perf_rdr_read_ubuf
+ *
+ * Read the RDR value into the buffer specified.
+ */
+static int perf_rdr_read_ubuf(uint32_t	rdr_num, uint64_t *buffer)
+{
+	uint64_t	data, data_mask = 0;
+	uint32_t	width, xbits, i;
+	struct rdr_tbl_ent *tentry;
+
+	tentry = perf_rdr_get_entry(rdr_num);
+	if ((width = tentry->width) == 0)
+		return 0;
+
+	/* Clear out buffer */
+	i = tentry->num_words;
+	while (i--) {
+		buffer[i] = 0;
+	}	
+
+	/* Check for bits an even number of 64 */
+	if ((xbits = width & 0x03f) != 0) {
+		data_mask = 1;
+		data_mask <<= (64 - xbits);
+		data_mask--;
+	}
+
+	/* Grab all of the data */
+	i = tentry->num_words;
+	while (i--) {
+
+		if (perf_processor_interface == ONYX_INTF) {
+			data = perf_rdr_shift_in_U(rdr_num, width);
+		} else {
+			data = perf_rdr_shift_in_W(rdr_num, width);
+		}
+		if (xbits) {
+			buffer[i] |= (data << (64 - xbits));
+			if (i) {
+				buffer[i-1] |= ((data >> xbits) & data_mask);
+			}
+		} else {
+			buffer[i] = data;
+		}
+	}
+
+	return 1;
+}
+
+/*
+ * perf_rdr_clear
+ *
+ * Zero out the given RDR register
+ */
+static int perf_rdr_clear(uint32_t	rdr_num)
+{
+	struct rdr_tbl_ent *tentry;
+	int32_t		i;
+
+	tentry = perf_rdr_get_entry(rdr_num);
+
+	if (tentry->width == 0) {
+		return -1;
+	}
+
+	i = tentry->num_words;
+	while (i--) {
+		if (perf_processor_interface == ONYX_INTF) {
+			perf_rdr_shift_out_U(rdr_num, 0UL);
+		} else {
+			perf_rdr_shift_out_W(rdr_num, 0UL);
+		}
+	}
+
+	return 0;
+}
+
+
+/*
+ * perf_write_image
+ *
+ * Write the given image out to the processor
+ */
+static int perf_write_image(uint64_t *memaddr)
+{
+	uint64_t buffer[MAX_RDR_WORDS];
+	uint64_t *bptr;
+	uint32_t dwords;
+	uint32_t *intrigue_rdr;
+	uint64_t *intrigue_bitmask, tmp64, proc_hpa, *ptr64;
+	struct rdr_tbl_ent *tentry;
+	int i;
+
+	/* Clear out counters */
+	if (perf_processor_interface == ONYX_INTF) {
+
+		perf_rdr_clear(16);
+
+		/* Toggle performance monitor */
+		perf_intrigue_enable_perf_counters();
+		perf_intrigue_disable_perf_counters();
+
+		intrigue_rdr = perf_rdrs_U;
+	} else {
+		perf_rdr_clear(15);
+		intrigue_rdr = perf_rdrs_W;
+	}
+
+	/* Write all RDRs */
+	while (*intrigue_rdr != -1) {
+		tentry = perf_rdr_get_entry(*intrigue_rdr);
+		perf_rdr_read_ubuf(*intrigue_rdr, buffer);
+		bptr   = &buffer[0];
+		dwords = tentry->num_words;
+		if (tentry->write_control) {
+			intrigue_bitmask = &bitmask_array[tentry->write_control >> 3];
+			while (dwords--) {
+				tmp64 = *intrigue_bitmask & *memaddr++;
+				tmp64 |= (~(*intrigue_bitmask++)) & *bptr;
+				*bptr++ = tmp64;
+			}
+		} else {
+			while (dwords--) {
+				*bptr++ = *memaddr++;
+			}
+		}
+
+		perf_rdr_write(*intrigue_rdr, buffer);
+		intrigue_rdr++;
+	}
+
+	/*
+	 * Now copy out the Runway stuff which is not in RDRs
+	 */
+
+	if (cpu_device == NULL)
+	{
+		printk(KERN_ERR "write_image: cpu_device not yet initialized!\n");
+		return -1;
+	}
+
+	proc_hpa = cpu_device->hpa;
+
+	/* Merge intrigue bits into Runway STATUS 0 */
+	ptr64 = (uint64_t *)(proc_hpa + 0x10); /* Runway STATUS 0 */
+	tmp64 = __raw_readq((u64 *)ptr64) & 0xffecffffffffffff;
+	__raw_writeq(tmp64 | (*memaddr++ & 0x0013000000000000), (u64 *)ptr64);
+	
+	/* Write RUNWAY DEBUG registers */
+	ptr64 = (uint64_t *)(proc_hpa + 0x40); /* Runway DEBUG 0 */
+	for (i = 0; i < 8; i++) {
+		__raw_writeq(*memaddr++, (u64 *)ptr64);
+		ptr64++;
+	}
+
+	return 0; 
+}
+
+/*
+ * perf_rdr_write
+ *
+ * Write the given RDR register with the contents
+ * of the given buffer.
+ */
+static void perf_rdr_write(uint32_t rdr_num, uint64_t *buffer)
+{
+	struct rdr_tbl_ent *tentry;
+	int32_t		i;
+
+printk("perf_rdr_write\n");
+	tentry = perf_rdr_get_entry(rdr_num);
+	if (tentry->width == 0) { return; }
+
+	i = tentry->num_words;
+	while (i--) {
+		if (perf_processor_interface == ONYX_INTF) {
+			perf_rdr_shift_out_U(rdr_num, buffer[i]);
+		} else {
+			perf_rdr_shift_out_W(rdr_num, buffer[i]);
+		}	
+	}
+printk("perf_rdr_write done\n");
+}
+
+module_init(perf_init);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/perf_asm.S linux/arch/parisc/kernel/perf_asm.S
--- linux.orig/arch/parisc/kernel/perf_asm.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/perf_asm.S	2002-08-12 22:14:10.000000000 +0000
@@ -0,0 +1,1679 @@
+; 
+;   Purpose:
+;	This file has the overall purpose of suppyling low-level
+;   assembly to program the intrigue portion of the cpu.
+; 
+
+#include <linux/config.h>
+#include <asm/assembly.h>
+
+#ifdef __LP64__
+	.level		2.0w
+#endif /* __LP64__ */
+
+#define MTDIAG_1(gr)    .word 0x14201840 + gr*0x10000
+#define MTDIAG_2(gr)    .word 0x14401840 + gr*0x10000
+#define MFDIAG_1(gr)    .word 0x142008A0 + gr
+#define MFDIAG_2(gr)    .word 0x144008A0 + gr
+#define STDIAG(dr)      .word 0x14000AA0 + dr*0x200000
+#define SFDIAG(dr)      .word 0x14000BA0 + dr*0x200000
+#define DR2_SLOW_RET    53
+
+
+;
+; Enable the performance counters
+;
+; The coprocessor only needs to be enabled when
+; starting/stopping the coprocessor with the pmenb/pmdis.
+;
+	.text
+	.align 32
+
+	.export perf_intrigue_enable_perf_counters,code
+perf_intrigue_enable_perf_counters:
+	.proc
+	.callinfo  frame=0,NO_CALLS
+	.entry
+	
+	ldi     0x20,%r25                ; load up perfmon bit
+	mfctl   ccr,%r26                 ; get coprocessor register
+	or      %r25,%r26,%r26             ; set bit
+	mtctl   %r26,ccr                 ; turn on performance coprocessor
+	pmenb                           ; enable performance monitor
+	ssm     0,0                     ; dummy op to ensure completion
+	sync                            ; follow ERS
+	andcm   %r26,%r25,%r26             ; clear bit now 
+	mtctl   %r26,ccr                 ; turn off performance coprocessor
+	nop                             ; NOPs as specified in ERS
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	bve    (%r2)
+	nop
+	.exit
+	.procend
+
+	.export perf_intrigue_disable_perf_counters,code
+perf_intrigue_disable_perf_counters:
+	.proc
+	.callinfo  frame=0,NO_CALLS
+	.entry
+	ldi     0x20,%r25                ; load up perfmon bit
+	mfctl   ccr,%r26                 ; get coprocessor register
+	or      %r25,%r26,%r26             ; set bit
+	mtctl   %r26,ccr                 ; turn on performance coprocessor
+	pmdis                           ; disable performance monitor
+	ssm     0,0                     ; dummy op to ensure completion
+	andcm   %r26,%r25,%r26             ; clear bit now 
+	bve    (%r2)
+	mtctl   %r26,ccr                 ; turn off performance coprocessor
+	.exit
+	.procend
+
+;************************************************************************
+;*																		*
+;* Name: perf_rdr_shift_in_W												*
+;*																		*
+;* Description:															*
+;*	This routine shifts data in from the RDR in arg0 and returns		*
+;*	the result in ret0.  If the RDR is <= 64 bits in length, it			*
+;*	is shifted shifted backup immediately.  This is to compensate		*
+;*	for RDR10 which has bits that preclude PDC stack operations			*
+;*	when they are in the wrong state.									*
+;*																		*
+;* Arguments:															*
+;*	arg0 : rdr to be read												*
+;*	arg1 : bit length of rdr											*
+;*																		*
+;* Returns:																*
+;*	ret0 = next 64 bits of rdr data from staging register				*
+;*																		*
+;* Register usage:														*
+;*	arg0 : rdr to be read												*
+;*	arg1 : bit length of rdr											*
+;*	%r24  - original DR2 value											*
+;*	%r1   - scratch														*
+;*  %r29  - scratch														*
+;*																		*
+;* Returns:																*
+;*	ret0 = RDR data (right justified)									*
+;*																		*
+;************************************************************************
+
+	.export perf_rdr_shift_in_W,code
+perf_rdr_shift_in_W:
+	.proc
+	.callinfo frame=0,NO_CALLS
+	.entry
+;
+; read(shift in) the RDR.
+;
+
+; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, remote diagnose registers.
+;
+
+	depdi,z		1,DR2_SLOW_RET,1,%r29
+	MFDIAG_2	(24)
+	or		    %r24,%r29,%r29
+	MTDIAG_2	(29)			; set DR2_SLOW_RET
+
+	nop
+	nop
+	nop
+	nop	
+
+;
+; Cacheline start (32-byte cacheline)
+;
+	nop
+	nop
+	nop
+	extrd,u		arg1,63,6,%r1    ; setup shift amount based on bits to move 
+
+	mtsar		%r1
+	shladd		arg0,2,%r0,%r1	; %r1 = 4 * RDR number
+	blr  		%r1,%r0		    ; branch to 8-instruction sequence
+	nop
+
+;
+; Cacheline start (32-byte cacheline)
+;
+
+	;
+	; RDR 0 sequence
+	;
+	SFDIAG		(0)		
+	ssm		    0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)					; mtdiag %dr1, %r1 
+	STDIAG		(0)
+	ssm		    0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 1 sequence
+	;
+	sync			
+	ssm		    0,0
+	SFDIAG		(1)
+	ssm		    0,0
+	MFDIAG_1	(28)
+	ssm		    0,0
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	
+	;
+	; RDR 2 read sequence
+	;
+	SFDIAG		(2)		
+	ssm		    0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(2)
+	ssm		    0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 3 read sequence
+	;
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	;
+	; RDR 4 read sequence
+	;
+	sync				
+	ssm			0,0
+	SFDIAG		(4)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	; 
+	; RDR 5 read sequence
+	;
+	sync	
+	ssm			0,0
+	SFDIAG		(5)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 6 read sequence
+	;
+	sync	
+	ssm			0,0
+	SFDIAG		(6)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 7 read sequence
+	;
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	;
+	; RDR 8 read sequence
+	;
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	;
+	; RDR 9 read sequence
+	;
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	;
+	; RDR 10 read sequence
+	;
+	SFDIAG		(10)
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(10)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 11 read sequence
+	;
+	SFDIAG		(11)
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(11)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 12 read sequence
+	;
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	;
+	; RDR 13 read sequence
+	;
+	sync
+	ssm			0,0
+	SFDIAG		(13)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 14 read sequence
+	;
+	SFDIAG		(14)	
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(14)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 15 read sequence
+	;
+	sync				; RDR 15 read sequence
+	ssm			0,0
+	SFDIAG		(15)
+	ssm			0,0
+	MFDIAG_1	(28)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	
+	;
+	; RDR 16 read sequence
+	;
+	sync				; RDR 16 read sequence
+	ssm			0,0
+	SFDIAG		(16)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 17 read sequence
+	;
+	SFDIAG		(17)	
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(17)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 18 read sequence
+	;
+	SFDIAG		(18)	
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(18)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+;
+; RDR 19 read sequence
+;
+	b,n         perf_rdr_shift_in_W_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	;
+	; RDR 20 read sequence
+	;
+	sync
+	ssm			0,0
+	SFDIAG		(20)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 21 read sequence
+	;
+	sync
+	ssm			0,0
+	SFDIAG		(21)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 22 read sequence
+	;
+	sync
+	ssm			0,0
+	SFDIAG		(22)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 23 read sequence
+	;
+	sync		
+	ssm			0,0
+	SFDIAG		(23)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 24 read sequence
+	;
+	sync	
+	ssm			0,0
+	SFDIAG		(24)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 25 read sequence
+	;
+	sync
+	ssm			0,0
+	SFDIAG		(25)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 26 read sequence
+	;
+	SFDIAG		(26)		
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(26)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 27 read sequence
+	;
+	SFDIAG		(27)
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(27)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 28 read sequence
+	;
+	sync				
+	ssm			0,0
+	SFDIAG		(28)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 29 read sequence
+	;
+	sync		
+	ssm			0,0
+	SFDIAG		(29)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_W_leave
+	ssm			0,0
+	nop
+	
+	;
+	; RDR 30 read sequence
+	;
+	SFDIAG		(30)
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(30)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_W_leave
+	
+	;
+	; RDR 31 read sequence
+	;
+	sync		
+	ssm			0,0
+	SFDIAG		(31)
+	ssm			0,0
+	MFDIAG_1	(28)
+	nop
+	ssm			0,0
+	nop
+
+	;
+	; Fallthrough
+	;
+
+perf_rdr_shift_in_W_leave:
+	bve		    (%r2)
+	.exit
+	MTDIAG_2	(24)			; restore DR2
+	.procend
+
+
+;************************************************************************
+;*																		*
+;* Name: perf_rdr_shift_out_W												*
+;*																		*
+;* Description:															*
+;*	This routine moves data to the RDR's.  The double-word that			*
+;*	arg1 points to is loaded and moved into the staging register.		*
+;*	Then the STDIAG instruction for the RDR # in arg0 is called			*
+;*	to move the data to the RDR.										*
+;*																		*
+;* Arguments:															*
+;*	arg0 = rdr number													*
+;*	arg1 = 64-bit value to write										*
+;*	%r24 - DR2 | DR2_SLOW_RET											*
+;*	%r23 - original DR2 value											*
+;*																		*
+;* Returns:																*
+;*	None																*
+;*																		*
+;* Register usage:														*
+;*																		*
+;************************************************************************
+
+	.export perf_rdr_shift_out_W,code
+perf_rdr_shift_out_W:
+	.proc
+	.callinfo frame=0,NO_CALLS
+	.entry
+;
+; NOTE: The PCX-W ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, the remote diagnose registers.
+;
+
+	depdi,z		1,DR2_SLOW_RET,1,%r24
+	MFDIAG_2	(23)
+	or		     %r24,%r23,%r24
+	MTDIAG_2	(24)			; set DR2_SLOW_RET
+
+	MTDIAG_1	(25)			; data to the staging register
+	shladd		arg0,2,%r0,%r1	; %r1 = 4 * RDR number
+	blr		    %r1,%r0		    ; branch to 8-instruction sequence
+	nop
+
+	;
+	; RDR 0 write sequence
+	;
+	sync				; RDR 0 write sequence
+	ssm			0,0
+	STDIAG		(0)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm			0,0
+	nop
+
+	;
+	; RDR 1 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(1)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 2 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(2)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 3 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(3)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 4 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(4)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 5 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(5)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 6 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(6)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 7 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(7)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 8 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(8)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 9 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(9)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 10 write sequence
+	;
+	sync	
+	ssm		0,0
+	STDIAG		(10)
+	STDIAG		(26)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	ssm		0,0
+	nop
+
+	;
+	; RDR 11 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(11)
+	STDIAG		(27)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	ssm		0,0
+	nop
+
+	;
+	; RDR 12 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(12)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 13 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(13)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 14 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(14)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 15 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(15)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 16 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(16)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 17 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(17)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 18 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(18)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 19 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(19)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 20 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(20)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 21 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(21)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 22 write sequence
+	;
+	sync	
+	ssm		0,0
+	STDIAG		(22)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 23 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(23)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 24 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(24)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 25 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(25)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 26 write sequence
+	;
+	sync	
+	ssm		0,0
+	STDIAG		(10)
+	STDIAG		(26)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	ssm		0,0
+	nop
+
+	;
+	; RDR 27 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(11)
+	STDIAG		(27)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	ssm		0,0
+	nop
+
+	;
+	; RDR 28 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(28)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 29 write sequence
+	;
+	sync
+	ssm		0,0
+	STDIAG		(29)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 30 write sequence
+	;
+	sync	
+	ssm		0,0
+	STDIAG		(30)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+	;
+	; RDR 31 write sequence
+	;
+	sync				
+	ssm		0,0
+	STDIAG		(31)
+	ssm		0,0
+	b,n         perf_rdr_shift_out_W_leave
+	nop
+	ssm		0,0
+	nop
+
+perf_rdr_shift_out_W_leave:
+	bve		(%r2)
+	.exit
+	MTDIAG_2	(23)			; restore DR2
+	.procend
+
+
+;**************************** CHRIS ***********************************
+
+;************************************************************************
+;*																		*
+;* Name: rdr_shift_in_U													*
+;*																		*
+;* Description:															*
+;*	This routine shifts data in from the RDR in arg0 and returns		*
+;*	the result in ret0.  If the RDR is <= 64 bits in length, it			*
+;*	is shifted shifted backup immediately.  This is to compensate		*
+;*	for RDR10 which has bits that preclude PDC stack operations			*
+;*	when they are in the wrong state.									*
+;*																		*
+;* Arguments:															*
+;*	arg0 : rdr to be read												*
+;*	arg1 : bit length of rdr											*
+;*																		*
+;* Returns:																*
+;*	ret0 = next 64 bits of rdr data from staging register				*
+;*																		*
+;* Register usage:														*
+;*	arg0 : rdr to be read						                        *
+;*	arg1 : bit length of rdr					                        *
+;*	%r24 - original DR2 value											*
+;*	%r23 - DR2 | DR2_SLOW_RET											*
+;*	%r1  - scratch														*
+;*																		*
+;************************************************************************
+
+	.export perf_rdr_shift_in_U,code
+perf_rdr_shift_in_U:
+	.proc
+	.callinfo frame=0,NO_CALLS
+	.entry
+
+; read(shift in) the RDR.
+;
+; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, remote diagnose registers.
+
+	depdi,z		1,DR2_SLOW_RET,1,%r29
+	MFDIAG_2	(24)
+	or			%r24,%r29,%r29
+	MTDIAG_2	(29)			; set DR2_SLOW_RET
+
+	nop
+	nop
+	nop
+	nop
+
+;
+; Start of next 32-byte cacheline
+;
+	nop
+	nop
+	nop
+	extrd,u		arg1,63,6,%r1
+
+	mtsar		%r1
+	shladd		arg0,2,%r0,%r1	; %r1 = 4 * RDR number
+	blr 		%r1,%r0		; branch to 8-instruction sequence
+	nop
+
+;
+; Start of next 32-byte cacheline
+;
+	SFDIAG		(0)		; RDR 0 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(0)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(1)		; RDR 1 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(1)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	sync				; RDR 2 read sequence
+	ssm			0,0
+	SFDIAG		(4)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 3 read sequence
+	ssm			0,0
+	SFDIAG		(3)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+
+	sync				; RDR 4 read sequence
+	ssm			0,0
+	SFDIAG		(4)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 5 read sequence
+	ssm			0,0
+	SFDIAG		(5)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 6 read sequence
+	ssm			0,0
+	SFDIAG		(6)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 7 read sequence
+	ssm			0,0
+	SFDIAG		(7)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+
+	b,n         perf_rdr_shift_in_U_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	SFDIAG		(9)		; RDR 9 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(9)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+
+	SFDIAG		(10)		; RDR 10 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(10)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(11)		; RDR 11 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(11)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(12)		; RDR 12 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(12)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+
+	SFDIAG		(13)		; RDR 13 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(13)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(14)		; RDR 14 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(14)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(15)		; RDR 15 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(15)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	sync				; RDR 16 read sequence
+	ssm			0,0
+	SFDIAG		(16)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	SFDIAG		(17)		; RDR 17 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(17)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(18)		; RDR 18 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(18)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	b,n         perf_rdr_shift_in_U_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	sync				; RDR 20 read sequence
+	ssm			0,0
+	SFDIAG		(20)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 21 read sequence
+	ssm			0,0
+	SFDIAG		(21)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 22 read sequence
+	ssm			0,0
+	SFDIAG		(22)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 23 read sequence
+	ssm			0,0
+	SFDIAG		(23)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 24 read sequence
+	ssm			0,0
+	SFDIAG		(24)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	sync				; RDR 25 read sequence
+	ssm			0,0
+	SFDIAG		(25)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	SFDIAG		(26)		; RDR 26 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(26)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(27)		; RDR 27 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(27)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	sync				; RDR 28 read sequence
+	ssm			0,0
+	SFDIAG		(28)
+	ssm			0,0
+	MFDIAG_1	(28)
+	b,n         perf_rdr_shift_in_U_leave
+	ssm			0,0
+	nop
+	
+	b,n         perf_rdr_shift_in_U_leave
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	
+	SFDIAG		(30)		; RDR 30 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(30)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	
+	SFDIAG		(31)		; RDR 31 read sequence
+	ssm			0,0
+	MFDIAG_1	(28)
+	shrpd		ret0,%r0,%sar,%r1
+	MTDIAG_1	(1)
+	STDIAG		(31)
+	ssm			0,0
+	b,n         perf_rdr_shift_in_U_leave
+	nop
+
+perf_rdr_shift_in_U_leave:
+	bve		    (%r2)
+	.exit
+	MTDIAG_2	(24)			; restore DR2
+	.procend
+
+;************************************************************************
+;*																		*
+;* Name: rdr_shift_out_U												*
+;*																		*
+;* Description:															*
+;*	This routine moves data to the RDR's.  The double-word that			*
+;*	arg1 points to is loaded and moved into the staging register.		*
+;*	Then the STDIAG instruction for the RDR # in arg0 is called			*
+;*	to move the data to the RDR.										*
+;*																		*
+;* Arguments:															*
+;*	arg0 = rdr target													*
+;*	arg1 = buffer pointer												*
+;*																		*
+;* Returns:																*
+;*	None																*
+;*																		*
+;* Register usage:														*
+;*	arg0 = rdr target													*
+;*	arg1 = buffer pointer												*
+;*	%r24 - DR2 | DR2_SLOW_RET											*
+;*	%r23 - original DR2 value											*
+;*																		*
+;************************************************************************
+
+	.export perf_rdr_shift_out_U,code
+perf_rdr_shift_out_U:
+	.proc
+	.callinfo frame=0,NO_CALLS
+	.entry
+
+;
+; NOTE: The PCX-U ERS states that DR2_SLOW_RET must be set before any
+; shifting is done, from or to, the remote diagnose registers.
+;
+
+	depdi,z		1,DR2_SLOW_RET,1,%r24
+	MFDIAG_2	(23)
+	or		%r24,%r23,%r24
+	MTDIAG_2	(24)			; set DR2_SLOW_RET
+
+	MTDIAG_1	(25)			; data to the staging register
+	shladd		 arg0,2,%r0,%r1	; %r1 = 4 * RDR number
+	blr		    %r1,%r0		    ; branch to 8-instruction sequence
+	nop
+
+;
+; 32-byte cachline aligned
+;
+
+	sync				; RDR 0 write sequence
+	ssm			0,0
+	STDIAG		(0)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 1 write sequence
+	ssm			0,0
+	STDIAG		(1)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 2 write sequence
+	ssm			0,0
+	STDIAG		(2)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 3 write sequence
+	ssm			0,0
+	STDIAG		(3)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 4 write sequence
+	ssm			0,0
+	STDIAG		(4)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 5 write sequence
+	ssm			0,0
+	STDIAG		(5)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 6 write sequence
+	ssm			0,0
+	STDIAG		(6)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 7 write sequence
+	ssm			0,0
+	STDIAG		(7)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 8 write sequence
+	ssm			0,0
+	STDIAG		(8)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 9 write sequence
+	ssm			0,0
+	STDIAG		(9)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 10 write sequence
+	ssm			0,0
+	STDIAG		(10)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 11 write sequence
+	ssm			0,0
+	STDIAG		(11)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 12 write sequence
+	ssm			0,0
+	STDIAG		(12)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 13 write sequence
+	ssm			0,0
+	STDIAG		(13)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 14 write sequence
+	ssm			0,0
+	STDIAG		(14)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 15 write sequence
+	ssm			0,0
+	STDIAG		(15)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 16 write sequence
+	ssm			0,0
+	STDIAG		(16)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 17 write sequence
+	ssm			0,0
+	STDIAG		(17)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 18 write sequence
+	ssm			0,0
+	STDIAG		(18)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 19 write sequence
+	ssm			0,0
+	STDIAG		(19)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 20 write sequence
+	ssm			0,0
+	STDIAG		(20)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 21 write sequence
+	ssm			0,0
+	STDIAG		(21)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 22 write sequence
+	ssm			0,0
+	STDIAG		(22)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 23 write sequence
+	ssm			0,0
+	STDIAG		(23)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 24 write sequence
+	ssm			0,0
+	STDIAG		(24)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 25 write sequence
+	ssm			0,0
+	STDIAG		(25)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 26 write sequence
+	ssm			0,0
+	STDIAG		(26)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 27 write sequence
+	ssm			0,0
+	STDIAG		(27)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 28 write sequence
+	ssm			0,0
+	STDIAG		(28)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 29 write sequence
+	ssm			0,0
+	STDIAG		(29)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 30 write sequence
+	ssm			0,0
+	STDIAG		(30)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+	sync				; RDR 31 write sequence
+	ssm			0,0
+	STDIAG		(31)
+	ssm			0,0
+	b,n         perf_rdr_shift_out_U_leave
+	nop
+	ssm			0,0
+	nop
+
+perf_rdr_shift_out_U_leave:
+	bve		(%r2)
+	.exit
+	MTDIAG_2	(23)			; restore DR2
+	.procend
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/perf_images.h linux/arch/parisc/kernel/perf_images.h
--- linux.orig/arch/parisc/kernel/perf_images.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/perf_images.h	2002-08-12 22:14:00.000000000 +0000
@@ -0,0 +1,3122 @@
+#ifndef PERF_IMAGES_H
+#define PERF_IMAGES_H
+
+/* Magic numbers taken without modification from HPUX stuff */
+
+/*
+ * Imagine for use with the Onyx cpu interface
+ */
+
+#define PCXU_IMAGE_SIZE 584
+
+static uint32_t onyx_images[][PCXU_IMAGE_SIZE/sizeof(uint32_t)] = {
+/*
+ * CPI:
+ *
+ * Counts the following:
+ *
+ * ctr0 : total cycles
+ * ctr1 : total cycles where nothing retired
+ * ctr2 : total instructions retired, including nullified
+ * ctr3 : total instructions retired, less nullified instructions
+ */
+         {
+         0x4c00c000, 0x00000000, 0x00060000, 0x00000000,
+         0xe0e0e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
+         0x0101ffff, 0xfffff104, 0xe000c07f, 0xfffffffc,
+         0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+         0x00000fff, 0xff00000f, 0xffff0000, 0x0fffff00,
+         0x000fffff, 0x00000000, 0x00000000, 0x00ffffff,
+         0xfffff000, 0x0000000f, 0xffffffff, 0xff000000,
+         0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+         0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+         0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000,
+         0xf0000030, 0x00003c00, 0x067f080c, 0x02019fc0,
+         0x02804067, 0xf0009030, 0x19fc002c, 0x40067f08,
+         0x0c12019f, 0xc0028440, 0x67f00091, 0x3019fc00,
+         0x2fc007ff, 0xf800f001, 0xfffe003c, 0x007fff80,
+         0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00,
+         0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800,
+         0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
+         0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
+         0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
+         0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
+         0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
+         0x00000000, 0x00000000, 0x00000000, 0x00000000,
+         0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff},
+
+/* Bus utilization image (bus_util)
+ *
+ * ctr0 : counts address valid cycles
+ * ctr1 : counts data valid cycles
+ * ctr2 : counts overflow from counter 0
+ * ctr3 : counts overflow from counter 1
+ */
+         {
+         0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+         0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+         0x0000000c, 0x00003c00, 0x07930000, 0x0041e4c0,
+         0x01002079, 0x3000800c, 0x1e4c0030, 0x00279300,
+         0x010049e4, 0xc0014022, 0x79300090, 0x0c9e4c00,
+         0x34004793, 0x00020051, 0xe4c00180, 0x24793000,
+         0xa00d1e4c, 0x00380067, 0x93000300, 0x59e4c001,
+         0xc0267930, 0x00b00d9e, 0x4c003fff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
+         0x00000000, 0x00000000, 0x00000000, 0x00000000,
+         0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+         0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0x00100000, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff },
+
+/*
+ * TLB counts (same as tlbStats image):
+ *
+ * Counts the following:
+ *
+ * ctr0: DTLB misses
+ * ctr1: ITLB misses
+ * ctr2: total cycles in the miss handlers
+ * ctr3: total cycles
+ */
+
+         {
+         0x0c00c000, 0x00000000, 0x00060000, 0x00000000,
+         0xe7e7e0e0, 0x004e0004, 0x07ffffff, 0xffc01380,
+         0x0101ffff, 0xfffff104, 0xe000c06a, 0xafffc85c,
+         0x01380010, 0x1fffffff, 0xff000000, 0x00000000,
+         0x01b9e000, 0x0001b8c0, 0x00000000, 0x0fffff00,
+         0x000fffff, 0x00000000, 0x00000000, 0x00400000,
+         0x00001000, 0x00000004, 0x00000000, 0x01000000,
+         0x0000ffff, 0xfffffff0, 0x00000000, 0x0fffffff,
+         0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+         0xfff55ff5, 0xffffffff, 0xffffffff, 0xf0000000,
+         0xf0000000, 0x00003c00, 0x01ff0001, 0x08007fc2,
+         0x02c1001f, 0xf0807100, 0x1bfc200c, 0x4806ff00,
+         0x03f001ff, 0xfe003c00, 0x7fff800f, 0x001fffe0,
+         0x03c007ff, 0xf800f001, 0xfffe003c, 0x007fff80,
+         0x0f001fff, 0xe003c007, 0xfff800f0, 0x01fffe00,
+         0x3c007fff, 0x800f001f, 0xffe003c0, 0x07fff800,
+         0xf001fffe, 0x003c007f, 0xff800f00, 0x1fffe003,
+         0xc007fff8, 0x00f001ff, 0xfe003c00, 0x7fff800f,
+         0x001fffe0, 0x03c007ff, 0xf800f001, 0xfffe003c,
+         0x007fff80, 0x0f001fff, 0xe003c007, 0xfff800f0,
+         0x01fffe00, 0x3c007fff, 0x800f001f, 0xffe00000,
+         0x00000000, 0x00000000, 0x00000000, 0x00000000,
+         0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff },
+
+/* tlbHandMiss
+ *
+ * ctr0: counts TLB misses 
+ * ctr1: counts dmisses inside tlb miss handlers 
+ * ctr2: counts cycles in the tlb miss handlers 
+ * ctr3: counts overflows of ctr2 
+ */
+{
+0x1c00c000,00000000,0x00060000,00000000,
+0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380,
+0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c,
+0x01380010,0x1fffffff,0xff000000,00000000,
+0x01b9e000,0x0001b8c0,00000000,0x0fffff00,
+0x000fffff,00000000,00000000,0x00400000,
+0x00001000,0x00000004,00000000,0x01000000,
+0x0000ffff,0xfffffff0,00000000,0x0fffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff55ff5,0xffffffff,0xffffffff,0xf0000000,
+0xf0000000,0x00003c00,0x01fd0000,0x08007f42,
+0x0281001f,0xd080a100,0x19f42008,0x44067d08,
+0x0612019f,0x400084c0,0x67d00060,0x0047f400,
+0x042011fd,0x080b0404,0x7f4202c4,0x0167d080,
+0x311059f4,0x201c4816,0x7d000313,0x059f4001,
+0xfc007fff,0x800f001f,0xffe003c0,0x07fff800,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x6fff0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* branch_taken image (ptkn image)
+ *
+ * ctr0: overflow for ctr1
+ * ctr1: predicted taken branches, actually taken
+ * ctr2: all predicted taken branches (nullfied or not)
+ * ctr3: overflow for ctr2
+ */
+
+        {
+        0xcc01e000, 0x00000000, 0x00060000, 0x00000000,
+        0xa08080a0, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffff0000, 0x00000000, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+        0xf0000000, 0x00003c00, 0x04f90000, 0x02013e40,
+        0x0081004f, 0x90004060, 0x13e40018, 0x0024f900,
+        0x0802093e, 0x40028102, 0x4f9000c0, 0x6093e400,
+        0x380014f9, 0x00010205, 0x3e4000c1, 0x014f9000,
+        0x506053e4, 0x001c0034, 0xf9000902, 0x0d3e4002,
+        0xc1034f90, 0x00d060d3, 0xe4003fff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xfffffc00,
+        0x00000000, 0x00000000, 0x00000000, 0x00000000,
+        0xffff0000, 0x00000000, 0xf0000000, 0x00000000,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+        0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+        0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+        0xffffffff, 0xffffffff, 0xf3ffffff, 0xffffffff,
+        0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+        0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+        0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+        0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+        0xffffffff, 0xffffffff },
+
+/* branch_nottaken (pntkn image)
+ *
+ * ctr0: overflow for ctr1
+ * ctr1: counts branches predicted not-taken, but actually taken
+ * ctr2: counts all predictable branches predicted not-taken
+ * ctr3: overflow for ctr2
+ */
+{
+0xcc01e000,00000000,0x00060000,00000000,
+0xc0c0c0e0,0xffb1fffb,0xfff7ffff,0xffffffff,
+0xffffffff,0xfffffffb,0x1fffbfff,0x7fffffff,
+0xfcc7ffff,0xffdffffa,0x5f000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+
+/* imiss image
+ *
+ * ctr0 : counts imiss aligned on 0
+ * ctr1 : counts imiss aligned on 4
+ * ctr2 : counts imiss aligned on 8
+ * ctr3 : counts imiss aligned on C
+ */
+         {
+         0x0c00c000, 0x00000000, 0x00010000, 0x00000000,
+         0xe7ebedee, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+         0xfff55fff, 0xffffffff, 0xffffffff, 0xf0000000,
+         0xf0000000, 0x00003c00, 0x007f0000, 0x01001fc0,
+         0x00408007, 0xf0002030, 0x01fc000c, 0x10007f00,
+         0x0405001f, 0xc0014180, 0x07f00060, 0x7001fc00,
+         0x1c20007f, 0x00080900, 0x1fc00242, 0x8007f000,
+         0xa0b001fc, 0x002c3000, 0x7f000c0d, 0x001fc003,
+         0x438007f0, 0x00e0f001, 0xfc003fff, 0xfffff800,
+         0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
+         0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
+         0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
+         0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
+         0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
+         0x00000000, 0x00000000, 0x00000000, 0x00000000,
+         0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff},
+
+/* dmiss image
+ * 
+ * ctr0 : counts cycles
+ * ctr1 : counts cycles where something retired
+ * ctr2 : counts dmisses
+ * ctr3 : (same as ctr2)
+ */
+         {
+         0x3c00c000, 0x00000000, 0x00060000, 0x00000000,
+         0xe0e0e0e0, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xff000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffff0000, 0x00000000, 0x6fffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xf0000000,
+         0xf0000000, 0x00003c04, 0x007f0009, 0x02001fc0,
+         0x0280c007, 0xf000b040, 0x01fc0030, 0x14007f00,
+         0x0d06001f, 0xc00381c0, 0x07f000f0, 0x8001fc00,
+         0x2024007f, 0x00090a00, 0x1fc00282, 0xc007f000,
+         0xb0c001fc, 0x00303400, 0x7f000d0e, 0x001fc003,
+         0x83c007f0, 0x00f00001, 0xfc0023ff, 0xfffff800,
+         0xfffffffe, 0x003fffff, 0xff800fff, 0xffffe003,
+         0xfffffff8, 0x00ffffff, 0xfe003fff, 0xffff800f,
+         0xffffffe0, 0x03ffffff, 0xf800ffff, 0xfffe003f,
+         0xffffff80, 0x0fffffff, 0xe003ffff, 0xfff800ff,
+         0xfffffe00, 0x3fffffff, 0x800fffff, 0xffe00000,
+         0x00000000, 0x00000000, 0x00000000, 0x00000000,
+         0x6fff0000, 0x00000000, 0x60000000, 0x00000000,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xfffffc00, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xfffffc00, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffaaaa, 0xffffffff, 0xf3ffffff, 0xffffffff,
+         0xfdffffff, 0xffffffff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0xffffffff, 0xfffff9ff, 0xfe000000, 0x00000000,
+         0x00030000, 0x00000000, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+         0xffffffff, 0xffffffff },
+
+/* dcmiss 
+ *
+ * ctr0: counts store instructions retired 
+ * ctr1: counts load instructions retired
+ * ctr2: counts dmisses 
+ * ctr3: counts READ_SHARED_OR_PRIV and READ_PRIVATE transactions on Runway 
+ */
+{
+0x2c90c000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf00000e8,0x00003c02,0x00bf0001,0x02002fc0,
+0x0080a00b,0xf0003040,0x02fc0010,0x1200bf00,
+0x0506002f,0xc00181a0,0x0bf00070,0x8002fc00,
+0x202200bf,0x00090a00,0x2fc00282,0xa00bf000,
+0xb0c002fc,0x00303200,0xbf000d0e,0x002fc003,
+0x83a00bf0,0x00ffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0x6fff0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0x55555555,0xd5555555,
+0x55555555,0x75555555,0x5e1ffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf8000000,00000000,
+00000000,00000000,0xf4000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* big_cpi
+ *
+ * ctr0: counts total cycles 
+ * ctr1: counts overflows of ctr0 (for greater than 32-bit values) 
+ * ctr2: counts overflows of ctr3 (for greater than 32-bit values) 
+ * ctr3: counts unnullified instructions retired 
+ */
+{
+0x0c00c000,00000000,0x00060000,00000000,
+0xe7e7e0e0,0x004e0004,0x07ffffff,0xffc01380,
+0x0101ffff,0xfffff104,0xe000c06a,0xafffc85c,
+0x01380010,0x1fffffff,0xff000000,00000000,
+0x01b9e000,0x0001b8c0,00000000,0x0fffff00,
+0x000fffff,00000000,00000000,0x00400000,
+0x00001000,0x00000004,00000000,0x01000000,
+0x0000ffff,0xfffffff0,00000000,0x0fffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff55ff5,0xffffffff,0xffffffff,0xf0000000,
+0xf0000010,0x00003c00,0x01760008,0x00025d80,
+0x02800417,0x6000c001,0x25d80038,0x04017600,
+0x0901025d,0x8002c044,0x176000d0,0x1125d800,
+0x3c2001f6,0x08080400,0x7d820203,0x001f6080,
+0x804027d8,0x20282009,0xf6080a0c,0x027d8202,
+0x81041f60,0x80c08107,0xd8203030,0x41f6080c,
+0x04127d82,0x0382049f,0x6080e0c1,0x27d82038,
+0x4006f608,0x081011bd,0x82030400,0xef6080a1,
+0x013bd820,0x384806f6,0x00081211,0xbd800304,
+0x80ef6000,0xa1213bd8,0x003bc007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x6fff0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* big_ls
+ *
+ * ctr0:counts the total number of cycles for which local_stall_A1 is asserted. 
+ * ctr1: is the overflow for counter 0. 
+ * ctr2: counts IFLUSH_AV 
+ * ctr3: is the overflow for counter 2. 
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00029408,0x02f50002,0x0800bd40,
+0x0202802f,0x5000a000,0x4bd40004,0x0812f500,
+0x030804bd,0x40024281,0x2f5000b0,0x010bd400,
+0x100842f5,0x00060810,0xbd400302,0x842f5000,
+0xe0014bd4,0x00140852,0xf5000708,0x14bd4003,
+0x42852f50,0x00ff001f,0xffe003c0,0x07fff800,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x0df70000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* br_abort
+ *
+ * ctr0: counts BRAD_STALLH 
+ * ctr1: counts ONE_QUAD 
+ * ctr2: counts BR0_ABRT 
+ * ctr3: counts BR1_ABRT
+ */
+{
+0x0c002000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x1fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x1a250000,00000000,0x10000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* isnt
+ *
+ * ctr0: counts the total number of cycles for which iside_notrans is asserted 
+ * ctr1: counts the number of times iside_notrans is asserted for 1-4 cycles 
+ * ctr2: counts the number of times iside_notrans is asserted for 5-7 cycles 
+ * ctr3: counts the number of times iside_notrans is asserted for > 7 cycles 
+ */
+{
+0x0c018000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xcfffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00021c20,0x03ff0808,0x1800ffc4,
+0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00,
+0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0,
+0x210003ff,0x00045800,0xffcc0214,0x003ff000,
+0x26800ffc,0xe0218003,0xff000278,0x00ffd002,
+0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0xcdff0000,00000000,0xc0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* quadrant
+ *
+ * ctr0: Total number of instructions in quadrant 0 
+ * ctr1: Total number of instructions in quadrant 1 
+ * ctr2: Total number of instructions in quadrant 2 
+ * ctr3: Total number of instructions in quadrant 3 
+ * Works only with 32-bit
+ */
+
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0x004e0004,   0x07ffffff,   0xffc01380,
+   0x0101ffff,   0xfffff004,   0xe000407f,   0xfffffffc,
+   0x01380010,   0x1fffffff,   0xff000000,   0x00000000,
+   0x00000fff,   0xff00000f,   0xffff0000,   0x0fffff00,
+   0x000fffff,   0x00000000,   0x00000000,   0x00ffffff,
+   0xffcff000,   0x0000040f,   0xfffffffc,   0xff000000,
+   0x0080ffff,   0xffffcff0,   0x0000000c,   0x0fffffff,
+   0xfcff0000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xfff55ff5,   0x5fffffff,   0xffffffff,   0xf0000000,
+   0xf00000f0,   0x00003c00,   0x007f0000,   0x01001fc0,
+   0x00408007,   0xf0002030,   0x01fc000c,   0x10007f00,
+   0x0405001f,   0xc0014180,   0x07f00060,   0x7001fc00,
+   0x1c20007f,   0x00080900,   0x1fc00242,   0x8007f000,
+   0xa0b001fc,   0x002c3000,   0x7f000c0d,   0x001fc003,
+   0x438007f0,   0x00e0f001,   0xfc003fff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffffc00,
+   0x00000000,   0x00000000,   0x00000000,   0x00000000,
+   0xffff0000,   0x00000000,   0xf0000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xfffffc00,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xfffffc00,   0x00000000,
+   0xffffffff,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0x00030000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff},
+
+/* rw_pdfet (READ_PRIV transactions)
+ *
+ * ctr0: counts address valid cycles 
+ * ctr1: counts *all* data valid cycles 
+ * ctr2: is the overflow from counter 0 
+ * ctr3: is the overflow from counter 1 
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf8000000,00000000,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff},
+
+/* rw_wdfet (WRITEBACKS)
+ *
+ * ctr0: counts address valid cycles 
+ * ctr1: counts *all* data valid cycles 
+ * ctr2: is the overflow from counter 0 
+ * ctr3: is the overflow from counter 1
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0x98000000,00000000,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff},
+
+/* shlib_cpi
+ *
+ * ctr0: Total number of instructions in quad 0 
+ * ctr1: Total number of CPU clock cycles in quad 0 
+ * ctr2: total instructions without nullified   
+ * ctr3: total number of CPU clock cycles 
+ */
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0x004e0004,   0x07ffffff,   0xffc01380,
+   0x0101ffff,   0xfffff004,   0xe000407f,   0xfffffffc,
+   0x01380010,   0x1fffffff,   0xff000000,   0x00000000,
+   0x00000fff,   0xff00000f,   0xffffffff,   0xffffffff,
+   0xffffffff,   0x00000000,   0x00000000,   0x00ffffff,
+   0xffcff000,   0x0000000f,   0xfffffffc,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xfff77ff5,   0x7fffffff,   0xffffffff,   0xf0000000,
+   0xf00000a0,   0x00003c00,   0x01ff0005,   0x08007fc0,
+   0x03c1001f,   0xf08030c0,   0x07fc203c,   0x4001ff08,
+   0x0118007f,   0xc003c500,   0x1ff08031,   0xc007fc00,
+   0x3fffffff,   0xf800ffff,   0xfffe003f,   0xffffff80,
+   0x0fffffff,   0xe003ffff,   0xfff800ff,   0xfffffe00,
+   0x3fffffff,   0x800fffff,   0xffe003ff,   0xfffff800,
+   0xfffffffe,   0x003fffff,   0xff800fff,   0xffffe003,
+   0xfffffff8,   0x00ffffff,   0xfe003fff,   0xffff800f,
+   0xffffffe0,   0x03ffffff,   0xf800ffff,   0xfffe003f,
+   0xffffff80,   0x0fffffff,   0xe003ffff,   0xfff800ff,
+   0xfffffe00,   0x3fffffff,   0x800fffff,   0xffe00000,
+   0x00000000,   0x00000000,   0x00000000,   0x00000000,
+   0xffff0000,   0x00000000,   0xf0000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xfffffc00,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xfffffc00,   0x00000000,
+   0xffffffff,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0x00030000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff},
+
+
+/* addr_inv_abort_alu
+ *
+ * ctr0: counts ABORT_ALU0L 
+ * ctr1: counts ABORT_ALU1L 
+ * ctr2: counts ADDR0_INVALID 
+ * ctr3: counts ADDR1_INVALID 
+ */
+
+{
+0x0c00c000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000d,0x01001fc0,
+0x03008007,0xf000f030,0x01fc0038,0x10007f00,
+0x0905001f,0xc0020180,0x07f000b0,0x7001fc00,
+0x2820007f,0x00050900,0x1fc00102,0x8007f000,
+0x70b001fc,0x00183000,0x7f00010d,0x001fc000,
+0x038007f0,0x0030f001,0xfc000bff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x65380000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+
+/* brad_stall
+ *
+ * ctr0: counts the total number of cycles for which brad_stall is asserted 
+ * ctr1: counts the number of times brad_stall is asserted for 1-4 cycles 
+ * ctr2: counts the number of times brad_stall is asserted for 5-7 cycles 
+ * ctr3: counts the number of times brad_stall is asserted for > 7 cycles 
+ */
+{
+0x0c002000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x1fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00021c20,0x03ff0808,0x1800ffc4,
+0x0204003f,0xf0004280,0x0ffc6020,0x8003ff00,
+0x043800ff,0xc8020c00,0x3ff00044,0x800ffca0,
+0x210003ff,0x00045800,0xffcc0214,0x003ff000,
+0x26800ffc,0xe0218003,0xff000278,0x00ffd002,
+0x1c003ff0,0x0028800f,0xfd002200,0x03ff0001,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x1bff0000,00000000,0x10000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* cntl_in_pipel
+ *
+ * ctr0: counts the total number of cycles for which cntl_in_pipel is asserted 
+ * ctr1: counts the number of times cntl_in_pipel is asserted for 1-4 cycles 
+ * ctr2: counts the number of times cntl_in_pipel is asserted for 5-7 cycles 
+ * ctr3: counts the number of times cntl_in_pipel is asserted for > 7 cycles 
+ */
+{
+0x0c006000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x3fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00021c00,0x03ff0808,0x1000ffc4,
+0x0206003f,0xf0004200,0x0ffc6020,0xa003ff00,
+0x043000ff,0xc8020e00,0x3ff00044,0x000ffca0,
+0x212003ff,0x00045000,0xffcc0216,0x003ff000,
+0x26000ffc,0xe021a003,0xff000270,0x00ffd002,
+0x1e003ff0,0x0028000f,0xfd002220,0x03ff0001,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x3fff0000,00000000,0x30000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+/* dsnt_xfh
+ *
+ * ctr0: counts dside_notrans 
+ * ctr1: counts xfhang 
+ * ctr2: is the overflow for ctr0 
+ * ctr3: is the overflow for ctr1 
+ */
+{
+0x0c018000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xcfffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x00030000,0x01f30000,0x00087cc0,
+0x0040041f,0x30002001,0x87cc000c,0x1001f300,
+0x0404087c,0xc0014104,0x1f300060,0x4187cc00,
+0x1c2001f3,0x00080808,0x7cc00242,0x041f3000,
+0xa08187cc,0x002c3001,0xf3000c0c,0x087cc003,
+0x43041f30,0x00e0c187,0xcc003fc0,0x07fff800,
+0xf001fffe,0x003c007f,0xff800f00,0x1fffe003,
+0xc007fff8,0x00f001ff,0xfe003c00,0x7fff800f,
+0x001fffe0,0x03c007ff,0xf800f001,0xfffe003c,
+0x007fff80,0x0f001fff,0xe003c007,0xfff800f0,
+0x01fffe00,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0xcb3f0000,00000000,0xc0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff }, 
+
+/* fet_sig1
+ *
+ * ctr0: counts ICORE_AV 
+ * ctr1: counts ITRANS_STALL 
+ * ctr2: counts SEL_PCQH 
+ * ctr3: counts OUT_OF_CONTEXT 
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x07c10000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff},
+
+/* fet_sig2
+ *
+ * ctr0: counts ICORE_AV  
+ * ctr1: counts IRTN_AV 
+ * ctr2: counts ADDRESS_INC 
+ * ctr3: counts ADDRESS_DEC 
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x06930000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_1
+ *
+ * ctr0: counts HIT_RETRY0 
+ * ctr1: counts HIT_RETRY1 
+ * ctr2: counts GO_TAG_E 
+ * ctr3: counts GO_TAG_O 
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x71c10000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_2
+ *
+ * ctr0: counts HIT_DM0 
+ * ctr1: counts HIT_DM1 
+ * ctr2: counts GO_STORE_E 
+ * ctr3: counts GO_STORE_O 
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x72930000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_3
+ *
+ * ctr0: counts HIT_DV0 
+ * ctr1: counts HIT_DV1 
+ * ctr2: counts STBYPT_E (load bypasses from store queue) 
+ * ctr3: counts STBYPT_O
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f0002,0x01001fc0,
+0x00c08007,0xf0000030,0x01fc0004,0x10007f00,
+0x0605001f,0xc001c180,0x07f00040,0x7001fc00,
+0x1420007f,0x000a0900,0x1fc002c2,0x8007f000,
+0x80b001fc,0x00243000,0x7f000e0d,0x001fc003,
+0xc38007f0,0x00c0f001,0xfc0037ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x77250000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* g7_4
+ *
+ * ctr0: counts HIT_DIRTY0 
+ * ctr1: counts HIT_DIRTY1 
+ * ctr2: counts CA_BYP_E (quick launch) 
+ * ctr3: counts CA_BYP_O 
+ */
+{
+0x0c00e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x7fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x7bb70000,00000000,0x70000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+
+/* mpb_labort
+ *
+ * ctr0: counts L_ABORT_ALU0L
+ * ctr1: counts L_ABORT_ALU1L 
+ * ctr2: counts MPB0H 
+ * ctr3: counts MPB1H 
+ */
+{
+0x0c00c000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffa5ffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x6fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+00000000,0x0003f800,0x007f000e,0x01001fc0,
+0x03c08007,0xf000c030,0x01fc0034,0x10007f00,
+0x0a05001f,0xc002c180,0x07f00080,0x7001fc00,
+0x2420007f,0x00060900,0x1fc001c2,0x8007f000,
+0x40b001fc,0x00143000,0x7f00020d,0x001fc000,
+0xc38007f0,0x0000f001,0xfc0007ff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x605c0000,00000000,0x60000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffaaaa,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* panic
+ *
+ * ctr0: is the overflow for counter 1 
+ * ctr1: counts traps and RFI's 
+ * ctr2: counts panic traps 
+ * ctr3: is the overflow for counter 2
+ */
+{
+0x0c002000,00000000,0x00060000,00000000,
+0xe7efe0e0,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffffc,
+0x41380030,0x1aabfff2,0x17000000,00000000,
+0x01b80000,0x3effffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,00000000,0x00400000,
+0x00001fff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x1fffffff,0xffffffff,
+0xfff7fff7,0xffffffff,0xffffffff,0xf0000000,
+0xb0000000,0x00012c04,0x05790804,0x14013e44,
+0x0008004f,0x90000040,0x15e46000,0xc0047920,
+0x004a003e,0x40011080,0x0f900024,0x4003e460,
+0x00c80479,0x00023301,0x1e400100,0x4157d080,
+0x514053f4,0x40048014,0xfd000104,0x055f4600,
+0x4c0147d2,0x0014a043,0xf4001508,0x10fd0003,
+0x44043f46,0x004c8147,0xd0003330,0x51f40014,
+0x04257908,0x0c14093e,0x44020802,0x4f900080,
+0x4095e460,0x20c02479,0x20084a08,0x3e400310,
+0x820f9000,0xa44083e4,0x6020c824,0x79000a33,
+0x091e4003,0x3c007fff,0x800f001f,0xffe00000,
+00000000,00000000,00000000,00000000,
+0x10400000,00000000,0x10000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* rare_inst
+ *
+ * ctr0: counts sync and syncdma instructions 
+ * ctr1: counts pxtlbx,x instructions 
+ * ctr2: counts ixtlbt instructions 
+ * ctr3: counts cycles 
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xe0e0e0e0,0x004e000c,0x000843fc,0x85c09380,
+0x0121ebfd,0xff217124,0xe0004000,0x943fc85f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xe00000e0,0x00003c00,0x007f0001,0x01001fc0,
+0x00408007,0xf0003030,0x01fc000c,0x10007f00,
+0x0505001f,0xc0014180,0x07f00070,0x7001fc00,
+0x1c20007f,0x00090900,0x1fc00242,0x8007f000,
+0xb0b001fc,0x002c3000,0x7f000d0d,0x001fc003,
+0x438007f0,0x00f0f001,0xfc003fff,0xfffff800,
+0xfffffffe,0x003fffff,0xff800fff,0xffffe003,
+0xfffffff8,0x00ffffff,0xfe003fff,0xffff800f,
+0xffffffe0,0x03ffffff,0xf800ffff,0xfffe003f,
+0xffffff80,0x0fffffff,0xe003ffff,0xfff800ff,
+0xfffffe00,0x3fffffff,0x800fffff,0xffe00000,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* rw_dfet (for D-cache misses and writebacks)
+ *
+ * ctr0: counts address valid cycles 
+ * ctr1: counts *all* data valid cycles 
+ * ctr2: is the overflow from counter 0 
+ * ctr3: is the overflow from counter 1 
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf0000000,00000000,
+00000000,00000000,0x98000000,00000000,
+0xffffffff,0xffffffff,0x0fffffff,0xffffffff,
+00000000,00000000,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* rw_ifet (I-cache misses -- actually dumb READ transactions)
+ *
+ * ctr0: counts address valid cycles 
+ * ctr1: counts *all* data valid cycles 
+ * ctr2: is the overflow from counter 0 
+ * ctr3: is the overflow from counter 1 
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xd0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff,00000000,00000000,
+0xffffffff,0xffffffff },
+
+
+/* rw_sdfet (READ_SHARED_OR_PRIVATE transactions)
+ *
+ * ctr0: counts address valid cycles
+ * ctr1: counts *all* data valid cycles 
+ * ctr2: is the overflow from counter 0 
+ * ctr3: is the overflow from counter 1 
+ */
+{
+0x0c01e000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x0000000c,0x00003c00,0x07930000,0x0041e4c0,
+0x01002079,0x3000800c,0x1e4c0030,0x00279300,
+0x010049e4,0xc0014022,0x79300090,0x0c9e4c00,
+0x34004793,0x00020051,0xe4c00180,0x24793000,
+0xa00d1e4c,0x00380067,0x93000300,0x59e4c001,
+0xc0267930,0x00b00d9e,0x4c003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00100000,00000000,0xf4000000,00000000,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+00000000,00000000,00000000,00000000,
+0xffffffff,0xffffffff },
+
+
+/* spec_ifet
+ *
+ * ICORE_AV fires for every request which the Instruction Fetch Unit sends
+ * to the Runway Interface Block.  Hence, this counts all I-misses, speculative
+ * or not, but does *not* include I-cache prefetches, which are generated by
+ * RIB.
+ * IRTN_AV fires twice for every I-cache miss returning from RIB to the IFU.
+ * It will not fire if a second I-cache miss is issued from the IFU to RIB
+ * before the first returns.  Therefore, if the IRTN_AV count is much less
+ * than 2x the ICORE_AV count, many speculative I-cache misses are occuring
+ * which are "discovered" to be incorrect fairly quickly.
+ * The ratio of I-cache miss transactions on Runway to the ICORE_AV count is
+ * a measure of the effectiveness of instruction prefetching.  This ratio
+ * should be between 1 and 2.  If it is close to 1, most prefetches are
+ * eventually called for by the IFU; if it is close to 2, almost no prefetches
+ * are useful and they are wasted bus traffic.
+ *
+ * ctr0: counts ICORE_AV 
+ * ctr1: counts IRTN_AV 
+ * ctr2: counts all non-coherent READ transactions on Runway. (TTYPE D0) 
+ *	This should be just I-cache miss and I-prefetch transactions.
+ * ctr3: counts total processor cycles 
+ */
+{
+0x0c000000,00000000,0x00060000,00000000,
+0xefefefef,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0x0fffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0x00000008,0x00030c00,0x01bf0001,0x00806fc0,
+0x00c1001b,0xf0005048,0x06fc001c,0x2001bf00,
+0x0908806f,0xc002c300,0x1bf000d0,0xc806fc00,
+0x3fffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0x06bf0000,00000000,00000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00110000,00000000,0xd0ffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0x00ffffff,0xffffffff,
+0xffffffff,0xffffffff,00000000,00000000,
+0xffffffff,0xffffffff },
+
+/* st_cond0
+ *
+ * ctr0: is the overflow for ctr1
+ * ctr1: counts major ops 0C and 0E (fp ops, not fmac or fmpyadd) 
+ * ctr2: counts B,L (including long and push) and GATE (including nullified),
+ *	 predicted not-taken
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc13380,
+0x0101ffff,0xffa1f057,0xe000407f,0xdfffc87f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond1
+ *
+ * ctr0: is the overflow for ctr1 
+ * ctr1: counts major ops 1x (most of the load/stores) 
+ * ctr2: counts CMPB (dw) predicted not-taken 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc01b80,
+0x0101ffff,0xffb7f03d,0xe000407f,0xffffc8ff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond2
+ *
+ * ctr0: is the overflow for ctr1 
+ * ctr1: counts major op 03 
+ * ctr2: counts CMPIB (dw) predicted not taken. 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc09780,
+0x0101ffff,0xff21f077,0xe000407f,0xffffc87f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond3
+ *
+ * ctr0: is the overflow for ctr1 
+ * ctr1: counts major ops 06 & 26 
+ * ctr2: counts BB, BVB, MOVB, MOVIB (incl. nullified) predicted not-taken 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc03780,
+0x0101ffff,0xff29f016,0xe000407f,0xffffe97f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_cond4
+ *
+ * ctr0: is the overflow for ctr1 
+ * ctr1: counts major op 2E 
+ * ctr2: counts CMPB, CMPIB, ADDB, ADDIB (incl. nullified) predicted not-taken 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0e0c0e0,0xffffffff,0xffffffff,0xffc17780,
+0x0101ffff,0xff21f014,0xe000407f,0xffffe9ff,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_unpred0
+ *
+ * ctr0: is the overflow for ctr1 
+ * ctr1: counts BE and BE,L 
+ * ctr2: counts BE and BE,L including nullified 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0c0c0e0,0xffffffff,0xffffffff,0xffdf5bbf,
+0xffffffff,0xff25f7d6,0xefffffff,0xffffc97f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* st_unpred1
+ *
+ * ctr0: is the overflow for ctr1 
+ * ctr1: counts BLR, BV, BVE, BVE,L 
+ * ctr2: counts BLR, BV, BVE, BVE,L including nullified 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0x4c01e000,00000000,0x00060000,00000000,
+0xe0c0c0e0,0xffffffff,0xffffffff,0xffc15f80,
+0x0501ff7f,0xff21f057,0xe001407f,0xdfffc87f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf0000060,0x00003c00,0x04f90000,0x02013e40,
+0x0081004f,0x90004060,0x13e40018,0x0024f900,
+0x0802093e,0x40028102,0x4f9000c0,0x6093e400,
+0x380014f9,0x00010205,0x3e4000c1,0x014f9000,
+0x506053e4,0x001c0034,0xf9000902,0x0d3e4002,
+0xc1034f90,0x00d060d3,0xe4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+
+/* unpred
+ *
+ * ctr0: counts non-nullified unpredictable branches 
+ * ctr1: is the overflow for ctr0 
+ * ctr2: counts all unpredictable branches (nullified or not) 
+ * ctr3: is the overflow for ctr2 
+ */
+{
+0xcc01e000,00000000,0x00060000,00000000,
+0x20202020,0xff31ffff,0xfff7fffe,0x97ffcc7f,
+0xfffffdff,0xffa5fff3,0x1fffffff,0x7fffe97f,
+0xffffffff,0xffffffff,0xff000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffff0000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xf0000000,
+0xf00000a0,0x00003c00,0x02f50000,0x0004bd40,
+0x0040802f,0x50002020,0x4bd4000c,0x0042f500,
+0x040014bd,0x40014084,0x2f500060,0x214bd400,
+0x1c2002f5,0x00080804,0xbd400242,0x802f5000,
+0xa0a04bd4,0x002c2042,0xf5000c08,0x14bd4003,
+0x42842f50,0x00e0a14b,0xd4003fff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xfffffc00,
+00000000,00000000,00000000,00000000,
+0xffff0000,00000000,0xf0000000,00000000,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xfffffc00,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xfffffc00,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xffffffff,0xf3ffffff,0xffffffff,
+0xfdffffff,0xffffffff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0xffffffff,0xfffff9ff,0xfe000000,00000000,
+0x00030000,00000000,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff,0xffffffff,0xffffffff,
+0xffffffff,0xffffffff },
+   
+
+/* go_store
+ *
+ * ctr0: Overflow for counter 2 
+ * ctr1: Overflow for counter 3 
+ * ctr2: count of GO_STORE_E signal 
+ * ctr3: count of GO_STORE_O signal 
+ */
+
+   {
+   0x0c00e000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffa5ffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xff000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x7fffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xf0000000,
+   0x00000000,   0x0000c000,   0x067c0000,   0x01019f00,
+   0x00408067,   0xc0002030,   0x19f0000c,   0x000e7c00,
+   0x0401039f,   0x00014080,   0xe7c00060,   0x3039f000,
+   0x1c00167c,   0x00080105,   0x9f000240,   0x8167c000,
+   0xa03059f0,   0x002c001e,   0x7c000c01,   0x079f0003,
+   0x4081e7c0,   0x00e03079,   0xf0003fc0,   0x07fff800,
+   0xf001fffe,   0x003c007f,   0xff800f00,   0x1fffe003,
+   0xc007fff8,   0x00f001ff,   0xfe003c00,   0x7fff800f,
+   0x001fffe0,   0x03c007ff,   0xf800f001,   0xfffe003c,
+   0x007fff80,   0x0f001fff,   0xe003c007,   0xfff800f0,
+   0x01fffe00,   0x3c007fff,   0x800f001f,   0xffe00000,
+   0x00000000,   0x00000000,   0x00000000,   0x00000000,
+   0x70130000,   0x00000000,   0x70000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xfffffc00,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xfffffc00,   0x00000000,
+   0xffffaaaa,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffaaaa,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0x00030000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff
+   },
+
+
+/* shlib_call
+ *
+ * ctr0: SharedLib call Depth1 
+ * ctr1: SharedLib call Depth2 
+ * ctr2: SharedLib call Depth3 
+ * ctr3: SharedLib call Depth>3 
+ */
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0xc76fa005,   0x07dd7e9c,   0x87115b80,
+   0x01100200,   0x07200004,   0xe000407f,   0xfffffffc,
+   0x01380010,   0x1fffffff,   0xff000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xf0000000,
+   0xf0000000,   0x00003c20,   0x01ff0808,   0x04007fc0,
+   0x0003001f,   0xf0000180,   0x07fc4010,   0x5001ff00,
+   0x001c007f,   0xc2000a00,   0x1ff18022,   0x4007fc20,
+   0x00b001ff,   0x10003800,   0x7fc8004d,   0x001ff100,
+   0x03c007fc,   0x60012001,   0xff280144,   0x007fc600,
+   0x13001ff2,   0x00058007,   0xfcc00550,   0x01ff2000,
+   0x5c007fca,   0x001a001f,   0xf3801640,   0x07fca001,
+   0xb001ff30,   0x0078007f,   0xd0005d00,   0x1ff30007,
+   0xc007fce0,   0x022001ff,   0x48018400,   0x7fce0023,
+   0x001ff400,   0x098007fd,   0x20065001,   0xff40009c,
+   0x007fd200,   0x3fffffff,   0x800fffff,   0xffe00000,
+   0x00000000,   0x00000000,   0x00000000,   0x00000000,
+   0xffff0000,   0x00000000,   0xf0000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xfffffc00,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xfffffc00,   0x00000000,
+   0xffffffff,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xf3ffffff,   0xffffffff,
+   0xfdffffff,   0xffffffff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0xffffffff,   0xfffff9ff,   0xfe000000,   0x00000000,
+   0x00030000,   0x00000000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff
+   }
+};
+#define PCXW_IMAGE_SIZE 576
+
+static uint32_t cuda_images[][PCXW_IMAGE_SIZE/sizeof(uint32_t)] = {
+/*
+ * CPI:     FROM CPI.IDF (Image 0)
+ *
+ * Counts the following:
+ *
+ * ctr0 : total cycles
+ * ctr1 : total cycles where nothing retired
+ * ctr2 : total instructions retired, including nullified
+ * ctr3 : total instructions retired, less nullified instructions
+ */
+   {
+   0x4c00c000,   0x00000000,   0x00060000,   0x00000000, 
+   0xe0e0e0e0,   0x00001fff,   0xfc00007f,   0xfff00001, 
+   0xffffc000,   0x07ffff00,   0x07ffffff,   0x6007ffff, 
+   0xff0007ff,   0xffff0007,   0xffffff00,   0x00000000, 
+   0x60f00000,   0x0fffff00,   0x000fffff,   0x00000fff, 
+   0xff00000f,   0xffff0000,   0x00000000,   0x00ffffff, 
+   0xfffff000,   0x0000000f,   0xffffffff,   0xff000000, 
+   0x0000ffff,   0xfffffff0,   0x00000000,   0x0fffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0x00270000,   0x00000055, 
+   0x0200000e,   0x4d300000,   0x00000000,   0x0ff00002, 
+   0x70000000,   0x00000020,   0x0000e400,   0x00000ff0, 
+   0x00000000,   0x00000000,   0x00000055,   0xffffff00, 
+   0x00000000,   0x0000ff00,   0x00000000,   0x0f000000, 
+   0x0000055f,   0xfffff000,   0x00000000,   0x000ff000, 
+   0x00000000,   0x00000000,   0x000055ff,   0xffff0000, 
+   0x00000000,   0x00ff0000,   0x00000000,   0xf0000000, 
+   0x000055ff,   0xffff0000,   0x00000000,   0x00ff0000, 
+   0x00000000,   0x00000000,   0x00055fff,   0xfff00000, 
+   0x00000000,   0x0ff00000,   0x00000030,   0x00000000, 
+   0x00157fff,   0xffc00000,   0x034c0000,   0x00000000, 
+   0x03fc0000,   0x00000000,   0x6fff0000,   0x00000000, 
+   0x60000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff7fbfc,   0x00000000,   0xffffafff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffafff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* Bus utilization image   FROM BUS_UTIL.IDF (Image 1)
+ *
+ * ctr0 : counts address valid cycles
+ * ctr1 : counts data valid cycles
+ * ctr2 : counts overflow from counter 0
+ * ctr3 : counts overflow from counter 1
+ */
+         {
+	 0x0c01e000, 0x00000000, 0x00060000, 0x00000000,
+	 0xefefefef, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffff00, 0x00000000,
+	 0xf0ffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffff0000, 0x00000000, 0x00000000, 0x00000000,
+	 0x00000000, 0x00000000, 0x00001b00, 0xaa000000,
+	 0x00000001, 0x30700000, 0x00055aaf, 0xf0000000,
+	 0x01b00000, 0x00000000, 0x00001037, 0x00000000,
+	 0x55aaff00, 0x00c00000, 0x1b55aa00, 0x00000000,
+	 0x0001fff0, 0xcfffff00, 0x00000000, 0x0f0fffff,
+	 0xffffffff, 0xffffffff, 0x30ffff0c, 0xfffff000,
+	 0x00000000, 0x00ffffff, 0xffffffff, 0xfffffff3,
+	 0x0ffff0cf, 0xffff0000, 0x00000000, 0x00ffffff,
+	 0xffffffff, 0xfffffff3, 0x0ffff0cf, 0xffff0000,
+	 0x00000000, 0x0fffffff, 0xffffffff, 0xffffff30,
+	 0xfff70000, 0x000055aa, 0xff000000, 0x000006d5,
+	 0x40000000, 0x00000000, 0x731c0000, 0x000156ab,
+	 0xfc000000, 0x00000000, 0xffff0000, 0x00000000,
+	 0xf0000000, 0x00000000, 0x00ffffff, 0xff3fffff,
+	 0xffffffff, 0xffcfffff, 0xfff7fbfc, 0x00000000,
+	 0x00ffffff, 0xff3fffff, 0xffffffff, 0xffcfffff,
+	 0xfff7fbfc, 0x00000000, 0xffffffff, 0xffffff3f,
+	 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+	 0x00000000, 0x00000000, 0xffffffff, 0xffffff3f,
+	 0xffffffff, 0xffffff7f, 0xffffffff, 0xfffffefc,
+	 0x00000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+	 0xfe000000, 0x00000000, 0xffffffff, 0xfffff9ff,
+	 0xfe000000, 0x00000000, 0x00100000, 0x00000000,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+   },
+
+/*
+ * TLB counts:    FROM TLBSTATS.IDF (Image 2)
+ *
+ * Counts the following:
+ *
+ * ctr0: DTLB misses
+ * ctr1: ITLB misses
+ * ctr2: total cycles in the miss handlers
+ * ctr3: total cycles
+ */
+
+   {
+   0x0c00c000,   0x00000000,   0x00060000,   0x00000000, 
+   0xe7e7e0e0,   0x00001fff,   0xfc00007f,   0xfff00001, 
+   0xfff00000,   0x07ffff00,   0x07ffffff,   0x6007ffff, 
+   0xa00007ff,   0xffff0007,   0xffffff00,   0x00000000, 
+   0x603001c1,   0xe0000001,   0xc0c00000,   0x00000fff, 
+   0xff00000f,   0xffff0000,   0x00000000,   0x00400000, 
+   0x00001000,   0x00000004,   0x00000000,   0x01000000, 
+   0x0000ffff,   0xfffffff0,   0x00000000,   0x0fffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0x00800000,   0x00153f7f, 
+   0x55000000,   0xaf800000,   0xc0000000,   0x0403f240, 
+   0x00000000,   0x00001010,   0x00004700,   0x00000ff0, 
+   0x00000000,   0x00000000,   0x00000055,   0xffffff00, 
+   0x00000000,   0x0000ff00,   0x00000000,   0x0f000000, 
+   0x0000055f,   0xfffff000,   0x00000000,   0x000ff000, 
+   0x00000000,   0x00000000,   0x000055ff,   0xffff0000, 
+   0x00000000,   0x00ff0000,   0x00000000,   0xf0000000, 
+   0x000055ff,   0xffff0000,   0x00000000,   0x00ff0000, 
+   0x00000000,   0x00000000,   0x00055fff,   0xfff00000, 
+   0x00000000,   0x0ff00000,   0x00000000,   0x00000000, 
+   0x00157fff,   0xffc00000,   0x00000000,   0x3fc00000, 
+   0x00040000,   0x00000000,   0x6fff0000,   0x00000000, 
+   0x60000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff7fbfc,   0x00000000,   0xffffafff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffafff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* tlbhandler  FROM tlbHandMiss.idf (Image 3)
+ *
+ * ctr0: TLB misses
+ * ctr1: dmisses inside the TLB miss handler
+ * ctr2: cycles in the TLB miss handler
+ * ctr3: overflow of ctr2
+ */
+   {
+   0x1c00c000,   0x00000000,   0x00060000,   0x00000000, 
+   0xe7e7e0e0,   0x00001fff,   0xfc00007f,   0xfff00001, 
+   0xfff00000,   0x07ffff00,   0x07ffffff,   0x6007ffff, 
+   0xa00007ff,   0xffff0007,   0xffffff00,   0x00000000, 
+   0x603001c1,   0xe0000001,   0xc0c00000,   0x00000fff, 
+   0xff00000f,   0xffff0000,   0x00000000,   0x00400000, 
+   0x00001000,   0x00000004,   0x00000000,   0x01000000, 
+   0x0000ffff,   0xfffffff0,   0x00000000,   0x0fffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0x006c0000,   0x01000054, 
+   0x02000002,   0xc3200000,   0xc00aa000,   0x0c03f240, 
+   0x00000000,   0x00001010,   0x000044f4,   0x00000c00, 
+   0xaa0000f0,   0x0f0000b0,   0x00005005,   0x0f5f0000, 
+   0x0001f000,   0x0000ff00,   0x00000000,   0x0f000000, 
+   0x0000055f,   0xfffff000,   0x00000000,   0x000ff000, 
+   0x00000000,   0x00000000,   0x000055ff,   0xffff0000, 
+   0x00000000,   0x00ff0000,   0x00000000,   0xf0000000, 
+   0x000055ff,   0xffff0000,   0x00000000,   0x00ff0000, 
+   0x00000000,   0x00000000,   0x00055fff,   0xfff00000, 
+   0x00000000,   0x0ff00a00,   0x000f0000,   0x24004000, 
+   0x15400001,   0x40c00003,   0x3da00000,   0x0002a800, 
+   0x00ff0000,   0x00000000,   0x6fff0000,   0x00000000, 
+   0x60000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff7fbfc,   0x00000000,   0xffffafff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffafff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* branch_taken image  FROM PTKN.IDF (Image 4)
+ *
+ * ctr0: mispredicted branches
+ * ctr1: predicted taken branches, actually taken
+ * ctr2: predicted taken branches (includes nullfied)
+ * ctr3: all branches
+ */
+
+   {
+   0xcc01e000,   0x00000000,   0x00000000,   0x00000000, 
+   0xa08080a0,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xfffffeff,   0xfffeffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf4ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xd22d0000,   0x00000000, 
+   0x0000000b,   0x46000000,   0x00000000,   0x0ffff900, 
+   0x90000000,   0x00000000,   0x0000907e,   0x00000000, 
+   0x000000ff,   0xff00bfdf,   0x03030303,   0x03030000, 
+   0x000dbfff,   0xffffff00,   0x00000000,   0x0f0fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffff5555,   0x55500000,   0x003f3ff0,   0x2766c000, 
+   0x00000000,   0x00000002,   0x67840000,   0x00000000, 
+   0x03fffc00,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* branch_nottaken  FROM PNTKN.IDF (Image 5)
+ *
+ * ctr0: mispredicted branches
+ * ctr1: branches predicted not-taken, but actually taken
+ * ctr2: branches predicted not-taken (includes nullified)
+ * ctr3: all branches
+ */
+   {
+   0xcc01e000,   0x00000000,   0x00000000,   0x00000000, 
+   0xe0c0c0e0,   0xffffffff,   0xffffffff,   0xffefffff, 
+   0xffffbfff,   0xfffffeff,   0xfffeffff,   0xfffffeff, 
+   0xfffffffe,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf4ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xd22d0000,   0x00000000, 
+   0x0000000b,   0x46000000,   0x00000000,   0x0ffff900, 
+   0x90000000,   0x00000000,   0x0000907e,   0x00000000, 
+   0x000000ff,   0xff00bfdf,   0x03030303,   0x03030000, 
+   0x000dbfff,   0xffffff00,   0x00000000,   0x0f0fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffff5555,   0x55500000,   0x003f3ff0,   0x2766c000, 
+   0x00000000,   0x00000002,   0x67840000,   0x00000000, 
+   0x03fffc00,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+   
+/* IMISS image (Image 6)
+ *
+ * ctr0 : icache misses for retired instructions
+ * ctr1 : total cycles
+ * ctr2 : dcache misses for retired instructions
+ * ctr3 : number of retired instructions
+ */
+   {
+   0x2801e000,   0x00000000,   0x00010000,   0x00000000, 
+   0x00001000,   0xffffffff,   0xffffffff,   0xfff00fff, 
+   0xfffa3fff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xf2fdf0f0,   0xf0f0f0f0, 
+   0xffffffff,   0xf6c00000,   0x00000000,   0x0ff55800, 
+   0x90000000,   0x00000000,   0x0000b0ff,   0xfffffff0, 
+   0x00000003,   0x0100bfff,   0x3f3f3f3f,   0x3f3f5555, 
+   0x555fffff,   0xffffff00,   0x00000000,   0x000fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xfff00000,   0x000301b0,   0x2fefcfcf, 
+   0xcfcfcfcf,   0xd5555557,   0xf7b40000,   0x00000000, 
+   0x03c14000,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* DMISS image (Image 7)
+ *
+ * ctr0 : icache misses for retired instructions
+ * ctr1 : total cycles
+ * ctr2 : dcache misses for retired instructions
+ * ctr3 : number of retired instructions
+ */
+   {
+   0x2801e000,   0x00000000,   0x00010000,   0x00000000, 
+   0x00001000,   0xffffffff,   0xffffffff,   0xfff00fff, 
+   0xfffa3fff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xf2fdf0f0,   0xf0f0f0f0, 
+   0xffffffff,   0xf6c00000,   0x00000000,   0x0ff55800, 
+   0x90000000,   0x00000000,   0x0000b0ff,   0xfffffff0, 
+   0x00000003,   0x0100bfff,   0x3f3f3f3f,   0x3f3f5555, 
+   0x555fffff,   0xffffff00,   0x00000000,   0x000fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xfff00000,   0x000301b0,   0x2fefcfcf, 
+   0xcfcfcfcf,   0xd5555557,   0xf7b40000,   0x00000000, 
+   0x03c14000,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* dmiss_access image    FROM DMISS_RATIO.IDF  (Image 8)
+ * 
+ * ctr0 : all loads and stores that retire (even lines)
+ * ctr1 : all loads and stores that retire (odd lines)
+ * ctr2 : dcache misses of retired loads/stores
+ * ctr3 : all READ_PRIV and READ_SHAR_OR_PRIV on Runway
+ *        (Speculative and Non-Speculative)
+ */
+   {
+   0x2d81e000,   0x00000000,   0x00000000,   0x00000000, 
+   0x10101010,   0x00ffffff,   0xa003ffff,   0xfe800fff, 
+   0xfffa003f,   0xffffe8ff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xd2280a00,   0x00000000, 
+   0x0000000b,   0x46000000,   0x00000005,   0x555ff900, 
+   0x80200000,   0x00000000,   0x0000907e,   0x00000000, 
+   0x00005555,   0xff80bf8b,   0xab030303,   0x03030000, 
+   0x000dbfff,   0xffffff00,   0x00000000,   0x000fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffff5555,   0x55500000,   0x15153fe0,   0x27628880, 
+   0x00000000,   0x00000002,   0x67840000,   0x00000001, 
+   0x5557fc00,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00110000,   0x00000000, 
+   0xf4ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xf8ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0x00ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0x00ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+
+/* big_cpi image  (Image 9)
+ * 
+ * ctr0 : Total number of CPU clock cycles. 
+ * ctr1 : Unused 
+ * ctr2 : Unused
+ * ctr3 : Total number of Non-Nullified instructions retired. 
+ */
+   {
+   0x0c00c000,   0x00000000,   0x00060000,   0x00000000,
+   0xe7e7e0e0,   0x00001fff,   0xfc00007f,   0xfff00001,
+   0xfff00000,   0x07ffff00,   0x07ffffff,   0x6007ffff,
+   0xa00007ff,   0xffff0007,   0xffffff00,   0x00000000,
+   0x603001c1,   0xe0000001,   0xc0c00000,   0x00000fff,
+   0xff00000f,   0xffff0000,   0x00000000,   0x00400000,
+   0x00001000,   0x00000004,   0x00000000,   0x01000000,
+   0x0000ffff,   0xfffffff0,   0x00000000,   0x0fffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x00550005,   0x00220000,
+   0x0000000c,   0x71f00000,   0x00f00aa0,   0x0aaff000,
+   0x00005002,   0x20000000,   0x0000c413,   0x00000c0f,
+   0x00aa0000,   0xff00b600,   0x000500a0,   0x00000300,
+   0x000cc3f0,   0x0000c0f0,   0x0aa0000f,   0xff000000,
+   0x011000a0,   0x05503000,   0x00d03700,   0x00000f00,
+   0xaa005500,   0x00000000,   0x000055ff,   0xffff0000,
+   0x00000000,   0x00ff0000,   0x00000000,   0xf000aa00,
+   0x11000a00,   0x55000000,   0x0d037000,   0x00c0f00a,
+   0xa0055000,   0x0db00005,   0x5002a000,   0x00300000,
+   0xf40f0000,   0x0c0f00aa,   0x0000ff10,   0x27400000,
+   0x00008000,   0x00c00003,   0x037c0000,   0x003c02a8,
+   0x02abfc00,   0x00000000,   0x6fff0000,   0x00000000,
+   0x60000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffafff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffafff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* big_ls image  (Image 10)
+ * 
+ * ctr0 : Total number of CPU clock cycles during which local_stall_A1 is asserted 
+ * ctr1 : Overflow of Counter 0 
+ * ctr2 : Total number of IFLUSH_AV 
+ * ctr3 : Overflow of Counter 2 
+ */
+   {
+   0x0c000000,   0x00000000,   0x00060000,   0x00000000,
+   0xefefefef,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0x00ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x28880001,   0x54000000,
+   0x00000004,   0xb6200000,   0x000aaaa0,   0x05555288,
+   0x80000010,   0x00000000,   0x0000486e,   0x00000000,
+   0xaaaa0055,   0x55002888,   0x00545401,   0x03030000,
+   0x0007b000,   0x0000ff00,   0x00000000,   0x05000000,
+   0x0000055f,   0xfffff000,   0x00000000,   0x000ff000,
+   0x00000000,   0x00000000,   0x000055ff,   0xffff0000,
+   0x00000000,   0x00ff0000,   0x00000000,   0x00000000,
+   0x000055ff,   0xffff0000,   0x00000000,   0x00ff0000,
+   0x00000000,   0xa0000000,   0x00055fff,   0xfff00000,
+   0x00aa0000,   0x05502a2a,   0x00151500,   0x0a220015,
+   0x40400000,   0x00000001,   0xe2980000,   0x0002aaa8,
+   0x01555400,   0x00000000,   0x0df70000,   0x00000000,
+   0x00000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* br_abort image  (Image 12)
+ * 
+ * ctr0 : Total number of BRAD_STALLH
+ * ctr1 : Total number of ONE_QUAD
+ * ctr2 : Total number of BR0_ABRT
+ * ctr3 : Total number of BR1_ABRT
+ */
+
+   {
+   0x0c002000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0xffffffff,   0xffffffff,   0xff0fffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0x1077ffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x551b0000,   0x00000000,
+   0x0000000c,   0xd4f00000,   0x00000000,   0x0ffff001,
+   0xb0000000,   0x00000000,   0x0000fd4c,   0x00000000,
+   0x000000ff,   0xff00ff1b,   0x00000000,   0x00000000,
+   0x0000d000,   0x0000ff00,   0x00000000,   0x0e0fffff,
+   0xffffffff,   0xfffff000,   0x00000000,   0x000ff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffff0000,
+   0x00000000,   0x00ff0000,   0x00000000,   0x00ffffff,
+   0xffffffff,   0xffff0000,   0x00000000,   0x00ff0000,
+   0x00000000,   0xffffffff,   0xffffffff,   0xfff00000,
+   0x00400000,   0x00000000,   0x00ffff00,   0x2a86c000,
+   0x00000000,   0x00000000,   0xf50c0000,   0x00000000,
+   0x03fffc00,   0x00000000,   0x1a250000,   0x00000000,
+   0x10000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffafff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffafff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+
+/* isnt image  (Image 13)
+ * 
+ * ctr0 : Total number of cycles for which iside_notrans is asserted. 
+ * ctr1 : Total number of times iside_notrans is asserted for 1-4 cycles. 
+ * ctr2 : Total number of times iside_notrans is asserted for 5-7 cycles. 
+ * ctr3 : Total number of times iside_notrans is asserted for > 7 cycles. 
+ */
+
+   {
+   0x0c018000,   0x00000000,   0x00060000,   0x00000000,
+   0xefefefef,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0xc0ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x22000000,   0x000001bc,
+   0x10000006,   0x00900000,   0x50000000,   0x00055a20,
+   0x00000000,   0x00016060,   0x0000c021,   0x00000540,
+   0x00000000,   0x55002200,   0x00000000,   0x56bc4000,
+   0x00048000,   0x0000ff00,   0x00000000,   0x17000000,
+   0x0000055f,   0xfffff000,   0x00000000,   0x000ff000,
+   0x00000000,   0x00000000,   0x000055ff,   0xffff0000,
+   0x00000000,   0x00ff0000,   0x00000000,   0x00000000,
+   0x000055ff,   0xffff0000,   0x00000000,   0x00ff0000,
+   0x00000000,   0x80000000,   0x00015bf3,   0xf5500000,
+   0x02210000,   0x00100000,   0x00005500,   0x08800000,
+   0x00001545,   0x85000001,   0x80240000,   0x11000000,
+   0x00015400,   0x00000000,   0xcdff0000,   0x00000000,
+   0xc0000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* quadrant image  (image 14)
+ * 
+ * ctr0 : Total number of instructions in quadrant 0. 
+ * ctr1 : Total number of instructions in quadrant 1. 
+ * ctr2 : Total number of instructions in quadrant 2. 
+ * ctr3 : Total number of instructions in quadrant 3. 
+ *
+ * Only works for 32-bit applications.
+ */
+
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0x00001fff,   0xfc00007f,   0xfff00001,
+   0xffffc000,   0x07ffff00,   0x07ffffff,   0x0007ffff,
+   0xff0007ff,   0xffff0007,   0xffffff00,   0x00000000,
+   0xf0000000,   0x0fffff00,   0x000fffff,   0x00000fff,
+   0xff00000f,   0xffff0000,   0x00000000,   0x00ffffff,
+   0xffcff000,   0x0000040f,   0xfffffffc,   0xff000000,
+   0x0080ffff,   0xffffcff0,   0x0000000c,   0x0fffffff,
+   0xfcff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x551b0000,   0x00000000,
+   0x00000003,   0x17000000,   0x00000000,   0x0ffff001,
+   0xb0000000,   0x00000000,   0x00000173,   0x00000000,
+   0x000000ff,   0xff00ff1b,   0x00000000,   0x00000000,
+   0x000f1ff0,   0xcfffff00,   0x00000000,   0x0f0fffff,
+   0xffffffff,   0xffffffff,   0x30ffff0c,   0xfffff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xfffffff3,
+   0x0ffff0cf,   0xffff0000,   0x00000000,   0xf0ffffff,
+   0xffffffff,   0xfffffff3,   0x0ffff0cf,   0xffff0000,
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffff30,
+   0xff7f0000,   0x00000000,   0x00fffff0,   0x2a86c000,
+   0x00000000,   0x00000003,   0x05f00000,   0x00000000,
+   0x03fffc00,   0x00000000,   0xffff0000,   0x00000000,
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* rw_pdfet image (Image 15)
+ * 
+ * ctr0 : Total of all READ_PRIV address valid cycles. 
+ * ctr1 : Total of all READ_PRIV data valid cycles. 
+ * ctr2 : Overflow of Counter 0. 
+ * ctr3 : Overflow of Counter 1. 
+ */
+
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xefefefef,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x00001b00,   0xaa000000,
+   0x00000001,   0x30700000,   0x00055aaf,   0xf0000000,
+   0x01b00000,   0x00000000,   0x00001037,   0x00000000,
+   0x55aaff00,   0x00c00000,   0x1b55aa00,   0x00000000,
+   0x0001fff0,   0xcfffff00,   0x00000000,   0x0f0fffff,
+   0xffffffff,   0xffffffff,   0x30ffff0c,   0xfffff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xfffffff3,
+   0x0ffff0cf,   0xffff0000,   0x00000000,   0x00ffffff,
+   0xffffffff,   0xfffffff3,   0x0ffff0cf,   0xffff0000,
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffff30,
+   0xfff70000,   0x000055aa,   0xff000000,   0x000006d5,
+   0x40000000,   0x00000000,   0x731c0000,   0x000156ab,
+   0xfc000000,   0x00000000,   0xffff0000,   0x00000000,
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00100000,   0x00000000,
+   0xf8000000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffffff,
+   0x00ffffff,   0xffffffff,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffffff,
+   },
+
+
+/* rw_wdfet image  (Image 16)
+ * 
+ * ctr0 : Counts total number of writeback transactions. 
+ * ctr1 : Total number of data valid Runway cycles. 
+ * ctr2 : Overflow of Counter 0. 
+ * ctr3 : Overflow of Counter 1. 
+ */
+
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xefefefef,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x00001b00,   0xaa000000,
+   0x00000001,   0x30700000,   0x00055aaf,   0xf0000000,
+   0x01b00000,   0x00000000,   0x00001037,   0x00000000,
+   0x55aaff00,   0x00c00000,   0x1b55aa00,   0x00000000,
+   0x0001fff0,   0xcfffff00,   0x00000000,   0x0f0fffff,
+   0xffffffff,   0xffffffff,   0x30ffff0c,   0xfffff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xfffffff3,
+   0x0ffff0cf,   0xffff0000,   0x00000000,   0x00ffffff,
+   0xffffffff,   0xfffffff3,   0x0ffff0cf,   0xffff0000,
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffff30,
+   0xfff70000,   0x000055aa,   0xff000000,   0x000006d5,
+   0x40000000,   0x00000000,   0x731c0000,   0x000156ab,
+   0xfc000000,   0x00000000,   0xffff0000,   0x00000000,
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00100000,   0x00000000,
+   0x98000000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffffff,
+   0x00ffffff,   0xffffffff,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffffff,
+   },
+
+/* shlib_cpi image  (Image 17)
+ * 
+ * ctr0 : Total number of instructions in quadrant 0. 
+ * ctr1 : Total number of CPU clock cycles in quadrant 0. 
+ * ctr2 : Total number of Non-Nullified instructions retired. 
+ * ctr3 : Total number of CPU clock cycles. 
+ *
+ * Only works for 32-bit shared libraries.
+ */
+
+   {
+   0x0c01e000,   0x00000000,   0x00060000,   0x00000000,
+   0xe0e0e0e0,   0x00001fff,   0xfc00007f,   0xfff00001,
+   0xffffc000,   0x07ffff00,   0x07ffffff,   0x0007ffff,
+   0xff0007ff,   0xffff0007,   0xffffff00,   0x00000000,
+   0xf0150000,   0x0fffff00,   0x000fffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0x00000000,   0x00ffffff,
+   0xffcff000,   0x0000000f,   0xfffffffc,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0x27000000,   0x00000055,
+   0x02000005,   0x7f500000,   0xc0000000,   0x000ff270,
+   0x00000000,   0x00000000,   0x00007700,   0x00000ff0,
+   0x00000000,   0x0000ffff,   0xffffffff,   0xffffff00,
+   0x00000000,   0x0000ff00,   0x00000000,   0x0f0fffff,
+   0xffffffff,   0xfffff000,   0x00000000,   0x000ff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffff0000,
+   0x00000000,   0x00ff0000,   0x00000000,   0xf0ffffff,
+   0xffffffff,   0xffff0000,   0x00000000,   0x00ff0000,
+   0x00000000,   0x0fffffff,   0xffffffff,   0xfff00000,
+   0x00000000,   0x0ff00000,   0x000000a0,   0x3fffffff,
+   0xffffffff,   0xffc00000,   0x03d40000,   0x20000000,
+   0x0003fc00,   0x00000000,   0xffff0000,   0x00000000,
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff7fbfc,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff7fbfc,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00030000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* flop image  (Image 18)
+ * 
+ * ctr0 : Total number of floating point instructions (opcode = 0xc). 
+ * ctr1 : Total number of floating point instructions (opcode = 0xe, 0x6, 0x2e, 0x26). 
+ * ctr2 : Unused
+ * ctr3 : Unused 
+ */
+
+   {
+   0x0001e000,   0x00000000,   0x00000000,   0x00000000,
+   0x00001010,   0x33ffffff,   0x006fffff,   0xfc5fffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0xd22d0000,   0x00000000,
+   0x0000000b,   0x46000000,   0x00000000,   0x0ffff900,
+   0x90000000,   0x00000000,   0x0000907e,   0x00000000,
+   0x000000ff,   0xff00bfdf,   0x03030303,   0x03030000,
+   0x000dbfff,   0xffffff00,   0x00000000,   0x000fffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000,
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff,
+   0xffff5555,   0x55500000,   0x003f3ff0,   0x2766c000,
+   0x00000000,   0x00000002,   0x67840000,   0x00000000,
+   0x03fffc00,   0x00000000,   0xffff0000,   0x00000000,
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* cachemiss image    FROM I_D_MISSES.IDF  (Image 19)
+ *
+ * ctr0 : icache misses for retired instructions
+ * ctr1 : total cycles
+ * ctr2 : dcache misses for retired instructions
+ * ctr3 : number of retired instructions
+ */
+   {
+   0x2801e000,   0x00000000,   0x00010000,   0x00000000, 
+   0x00001000,   0xffffffff,   0xffffffff,   0xfff00fff, 
+   0xfffa3fff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf0ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xf2fdf0f0,   0xf0f0f0f0, 
+   0xffffffff,   0xf6c00000,   0x00000000,   0x0ff55800, 
+   0x90000000,   0x00000000,   0x0000b0ff,   0xfffffff0, 
+   0x00000003,   0x0100bfff,   0x3f3f3f3f,   0x3f3f5555, 
+   0x555fffff,   0xffffff00,   0x00000000,   0x000fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xfff00000,   0x000301b0,   0x2fefcfcf, 
+   0xcfcfcfcf,   0xd5555557,   0xf7b40000,   0x00000000, 
+   0x03c14000,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* branch   FROM br_report3.idf 
+ *
+ * ctr0 : Total number of mispredicted branches. 
+ * ctr1 : Some Non-Nullified unpredictable branches. 
+ * ctr2 : Total number of branches (Nullified + Non-Nullified)
+ *        (Unpredicted+ Predicted Taken +Predicted Not Taken). 
+ *	  Total of All Branches.
+ * ctr3 : Remaining Non-Nullified unpredictable branches.
+ */
+   {
+   0x4001e000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0xffffffff,   0xff9fffff,   0xfe0fffff, 
+   0xffffbaff,   0xfdffc0ff,   0xfffdffff,   0xfffffeff, 
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf4ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xd22d0000,   0x00000000, 
+   0x0000000b,   0x46000000,   0x00000000,   0x0ffff900, 
+   0x90000000,   0x00000000,   0x0000907e,   0x00000000, 
+   0x000000ff,   0xff00bfdf,   0x03030303,   0x03030000, 
+   0x000dbfff,   0xffffff00,   0x00000000,   0x000fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffff5555,   0x55500000,   0x003f3ff0,   0x2766c000, 
+   0x00000000,   0x00000002,   0x67840000,   0x00000000, 
+   0x03fffc00,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* crstack  FROM crs_report.idf
+ *
+ * ctr0: correctly predicted branches by the pop_latch
+ * ctr1: some procedure returns
+ * ctr2: all branches, (includes nullified)
+ * ctr3: remaining procedure returns
+ */
+   {
+   0x4001e000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0xffffffff,   0xffa10300,   0x000fffff, 
+   0xffffbaf8,   0x3000007f,   0xffffffff,   0xfffffeff, 
+   0xff7fffff,   0xffffffff,   0xffffff00,   0x00000000, 
+   0xf2ffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000, 
+   0x00000000,   0x00000000,   0xd22d0000,   0x00000000, 
+   0x0000000b,   0x46000000,   0x00000000,   0x0ffff900, 
+   0x90000000,   0x00000000,   0x0000907e,   0x00000000, 
+   0x000000ff,   0xff00bfdf,   0x03030303,   0x03030000, 
+   0x000dbfff,   0xffffff00,   0x00000000,   0x000fffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000, 
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffff0000,   0x00000000,   0xf0ffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000, 
+   0x00000000,   0x0fffffff,   0xffffffff,   0xffffffff, 
+   0xffff5555,   0x55500000,   0x003f3ff0,   0x2766c000, 
+   0x00000000,   0x00000002,   0x67840000,   0x00000000, 
+   0x03fffc00,   0x00000000,   0xffff0000,   0x00000000, 
+   0xf0000000,   0x00000000,   0x00ffffff,   0xff3fffff, 
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000, 
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff, 
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f, 
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc, 
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff, 
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff, 
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   },
+
+/* icache_report image 
+ * 
+ * ctr0 : Icache misses actually used by the core. 
+ * ctr1 : ICORE_AV (Icache misses the core THINKS it needs, including fetching down speculative paths). 
+ * ctr2 : READs on Runway (Icache misses that made it out to Runway, including
+ *	  prefetches).
+ * ctr3 : Prefetch returns (1x and 2x). 
+ */
+   {
+   0x00000000,   0x00000000,   0x00010000,   0x00000000,
+   0x00000000,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffff00,   0x00000000,
+   0x00ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffff0000,   0x00000000,   0x00000000,   0x00000000,
+   0x00000000,   0x00000000,   0xd2002d00,   0x00000000,
+   0x0000000b,   0x46000000,   0x0000000f,   0xf00ff900,
+   0x00900000,   0x00000000,   0x0000907e,   0x00000000,
+   0x0000ff00,   0xff83bf03,   0xdf030303,   0x03030000,
+   0x000dbfff,   0xffffff00,   0x00000000,   0x000fffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xfffff000,
+   0x00000000,   0x00ffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffff0000,   0x00000000,   0x80ffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffff0000,
+   0x00000000,   0x4fffffff,   0xffffffff,   0xffffffff,
+   0xffff5555,   0x55500000,   0x3f003f80,   0x274026c0,
+   0x00000000,   0x00000002,   0x67840000,   0x00000003,
+   0xfc03fc00,   0x00000000,   0x0eff0000,   0x00000000,
+   0x00000000,   0x00000000,   0x00ffffff,   0xff3fffff,
+   0xffffffff,   0xffcfffff,   0xfff6fb7c,   0x00000000,
+   0x00ffffff,   0xff3fffff,   0xffffffff,   0xffcfffff,
+   0xfff6fb7c,   0x00000000,   0xffff0fff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffff0fff,   0xffffff3f,
+   0xffffffff,   0xffffff7f,   0xffffffff,   0xfffffefc,
+   0x00000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0xffffffff,   0xfffff9ff,
+   0xfe000000,   0x00000000,   0x00130000,   0x00000000,
+   0xd0ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0x00ffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   0xffffffff,   0xffffffff,   0xffffffff,   0xffffffff,
+   
+   }
+
+};
+
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/power.c linux/arch/parisc/kernel/power.c
--- linux.orig/arch/parisc/kernel/power.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/power.c	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,377 @@
+/*
+ * linux/arch/parisc/kernel/power.c
+ * HP PARISC soft power switch support driver
+ *
+ * Copyright (c) 2001-2002 Helge Deller <deller@gmx.de>
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ *
+ * 
+ *  HINT:
+ *  Support of the soft power switch button may be enabled or disabled at
+ *  runtime through the "/proc/sys/kernel/power" procfs entry.
+ */ 
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+
+#include <asm/gsc.h>
+#include <asm/pdc.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/led.h>
+#include <asm/led.h>
+#include <asm/uaccess.h>
+
+
+#ifdef DEBUG
+# define DPRINTK(x) printk x
+#else
+# define DPRINTK(x) do { } while (0)
+#endif
+
+
+/* filename in /proc which can be used to enable/disable the power switch */
+#define SYSCTL_FILENAME		"sys/kernel/power"
+
+
+#define DIAG_CODE(code)		(0x14000000 + ((code)<<5))
+
+/* this will go to processor.h or any other place... */
+/* taken from PCXL ERS page 82 */
+#define MFCPU_X(rDiagReg, t_ch, t_th, code) \
+	(DIAG_CODE(code) + ((rDiagReg)<<21) + ((t_ch)<<16) + ((t_th)<<0) )
+	
+#define MTCPU(dr, gr)		MFCPU_X(dr, gr,  0, 0x12)       /* move value of gr to dr[dr] */
+#define MFCPU_C(dr, gr)		MFCPU_X(dr, gr,  0, 0x30)	/* for dr0 and dr8 only ! */
+#define MFCPU_T(dr, gr)		MFCPU_X(dr,  0, gr, 0xa0)	/* all dr except dr0 and dr8 */
+	
+#define __getDIAG(dr) ( { 			\
+        register unsigned long __res asm("r28");\
+	 __asm__ __volatile__ (			\
+		".word %1\n nop\n" : "=&r" (__res) : "i" (MFCPU_T(dr,28)) \
+	);					\
+	__res;					\
+} )
+
+
+static void deferred_poweroff(void *dummy)
+{
+	extern int cad_pid;	/* from kernel/sys.c */
+	if (kill_proc(cad_pid, SIGINT, 1)) {
+		/* just in case killing init process failed */
+		machine_power_off();
+	}
+}
+
+/*
+ * This function gets called from interrupt context.
+ * As it's called within an interrupt, it wouldn't sync if we don't
+ * use schedule_task().
+ */
+
+static void poweroff(void)
+{
+	static int powering_off;
+	static struct tq_struct poweroff_tq = {
+		routine: deferred_poweroff,
+	};
+
+	if (powering_off)
+		return;
+
+	powering_off++;
+	schedule_task(&poweroff_tq);
+}
+
+
+/* local time-counter for shutdown */
+static int shutdown_timer;
+
+/* check, give feedback and start shutdown after one second */
+static void process_shutdown(void)
+{
+	if (shutdown_timer == 0)
+		DPRINTK((KERN_INFO "Shutdown requested...\n"));
+
+	shutdown_timer++;
+	
+	/* wait until the button was pressed for 1 second */
+	if (shutdown_timer == HZ) {
+		static char msg[] = "Shutting down...";
+		DPRINTK((KERN_INFO "%s\n", msg));
+#ifdef CONFIG_CHASSIS_LCD_LED
+		lcd_print(msg);
+#endif
+		poweroff();
+	}
+}
+
+
+/* main power switch tasklet struct (scheduled from time.c) */
+DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
+
+/* soft power switch enabled/disabled */
+#ifdef CONFIG_PROC_FS
+static int pwrsw_enabled = 1;
+#else
+#define pwrsw_enabled (1)
+#endif
+
+/*
+ * On gecko style machines (e.g. 712/xx and 715/xx) 
+ * the power switch status is stored in Bit 0 ("the highest bit")
+ * of CPU diagnose register 25.
+ * 
+ */
+static void gecko_tasklet_func(unsigned long unused)
+{
+	if (!pwrsw_enabled)
+		return;
+
+	if (__getDIAG(25) & 0x80000000) {
+		/* power switch button not pressed or released again */
+		/* Warning: Some machines do never reset this DIAG flag! */
+		shutdown_timer = 0;
+	} else {
+		process_shutdown();
+	}
+}
+
+
+
+/*
+ * Check the power switch status which is read from the
+ * real I/O location at soft_power_reg.
+ * Bit 31 ("the lowest bit) is the status of the power switch.
+ */
+
+static void polling_tasklet_func(unsigned long soft_power_reg)
+{
+        unsigned long current_status;
+	
+	if (!pwrsw_enabled)
+		return;
+
+	current_status = gsc_readl(soft_power_reg);
+	if (current_status & 0x1) {
+		/* power switch button not pressed */
+		shutdown_timer = 0;
+	} else {
+		process_shutdown();
+	}
+}
+
+
+/*
+ * powerfail interruption handler (irq IRQ_FROM_REGION(CPU_IRQ_REGION)+2) 
+ */
+#if 0
+static void powerfail_interrupt(int code, void *x, struct pt_regs *regs)
+{
+	printk(KERN_CRIT "POWERFAIL INTERRUPTION !\n");
+	poweroff();
+}
+#endif
+
+
+
+
+/* 
+ * /proc filesystem support 
+ */
+
+#ifdef CONFIG_SYSCTL
+static int power_proc_read(char *page, char **start, off_t off, int count, 
+	int *eof, void *data)
+{
+	char *out = page;
+	int len;
+
+	out += sprintf(out, "Software power switch support: ");
+	out += sprintf(out, pwrsw_enabled ? "enabled (1)" : "disabled (0)" );
+	out += sprintf(out, "\n");
+
+	len = out - page - off;
+	if (len < count) {
+		*eof = 1;
+		if (len <= 0) return 0;
+	} else {
+		len = count;
+	}
+	*start = page + off;
+	return len;
+}
+
+static int power_proc_write(struct file *file, const char *buf, 
+	unsigned long count, void *data)
+{
+	char *cur, lbuf[count];
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	memset(lbuf, 0, count);
+
+	copy_from_user(lbuf, buf, count);
+	cur = lbuf;
+
+	/* skip initial spaces */
+	while (*cur && isspace(*cur))
+		cur++;
+
+	switch (*cur) {
+	case '0':	pwrsw_enabled = 0;
+			break;
+	case '1':	pwrsw_enabled = 1;
+			break;
+	default:	printk(KERN_CRIT "/proc/" SYSCTL_FILENAME 
+					": Parse error: only '0' or '1' allowed!\n");
+			return -EINVAL;
+	} /* switch() */
+
+	return count;
+}
+
+static struct proc_dir_entry *ent;
+
+static void __init power_create_procfs(void)
+{
+	if (!power_tasklet.func)
+		return;
+	
+	ent = create_proc_entry(SYSCTL_FILENAME, S_IFREG|S_IRUGO|S_IWUSR, 0);
+	if (!ent) return;
+	
+	ent->nlink = 1;
+	ent->read_proc = power_proc_read;
+	ent->write_proc = power_proc_write;
+	ent->owner = THIS_MODULE;
+}
+
+static void __exit power_remove_procfs(void)
+{
+	remove_proc_entry(SYSCTL_FILENAME, NULL);
+}
+
+#else
+#define power_create_procfs()	do { } while (0)
+#define power_remove_procfs()	do { } while (0)
+#endif	/* CONFIG_SYSCTL */
+
+
+
+/* parisc_panic_event() is called by the panic handler.
+ * As soon as a panic occurs, our tasklets above will not be
+ * executed any longer. This function then re-enables the 
+ * soft-power switch and allows the user to switch off the system
+ */
+static int parisc_panic_event(struct notifier_block *this,
+		unsigned long event, void *ptr)
+{
+	/* re-enable the soft-power switch */
+	pdc_soft_power_button(0);
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block parisc_panic_block = {
+	notifier_call: parisc_panic_event,
+	priority: INT_MAX,
+};
+
+
+static int __init power_init(void)
+{
+	unsigned long ret;
+	unsigned long soft_power_reg = 0;
+
+#if 0
+	request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt,
+		0, "powerfail", NULL);
+#endif
+
+	/* enable the soft power switch if possible */
+	ret = pdc_soft_power_info(&soft_power_reg);
+	if (ret == PDC_OK)
+		ret = pdc_soft_power_button(1);
+	if (ret != PDC_OK)
+		soft_power_reg = -1UL;
+	
+	switch (soft_power_reg) {
+	case 0:		printk(KERN_INFO "Gecko-style soft power switch enabled.\n");
+			power_tasklet.func = gecko_tasklet_func;
+			break;
+			
+	case -1UL:	printk(KERN_INFO "Soft power switch support not available.\n");
+			return -ENODEV;
+	
+	default:	printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n",
+				soft_power_reg);
+			power_tasklet.data = soft_power_reg;
+			power_tasklet.func = polling_tasklet_func;
+	}
+
+	/* Register a call for panic conditions. */
+	notifier_chain_register(&panic_notifier_list, &parisc_panic_block);
+
+	power_create_procfs();
+	tasklet_enable(&power_tasklet);
+
+	return 0;
+}
+
+static void __exit power_exit(void)
+{
+	if (!power_tasklet.func)
+		return;
+
+	tasklet_disable(&power_tasklet);
+	notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block);
+	power_remove_procfs();
+	power_tasklet.func = NULL;
+	pdc_soft_power_button(0);
+}
+
+module_init(power_init);
+module_exit(power_exit);
+
+
+MODULE_AUTHOR("Helge Deller");
+MODULE_DESCRIPTION("Soft power switch driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
+EXPORT_NO_SYMBOLS;
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/process.c linux/arch/parisc/kernel/process.c
--- linux.orig/arch/parisc/kernel/process.c	2001-02-09 19:29:44.000000000 +0000
+++ linux/arch/parisc/kernel/process.c	2002-08-12 22:14:26.000000000 +0000
@@ -26,6 +26,7 @@
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/elf.h>
+#include <linux/personality.h>
 
 #include <asm/machdep.h>
 #include <asm/offset.h>
@@ -36,19 +37,12 @@
 #include <asm/gsc.h>
 #include <asm/processor.h>
 
-spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
+int hlt_counter;
 
-#ifdef __LP64__
-/* The 64-bit code should work equally well in 32-bit land but I didn't
- * want to take the time to confirm that.  -PB
- */
-extern unsigned int ret_from_kernel_thread;
-#else
-asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
-#endif
-
-
-int hlt_counter=0;
+/*
+ * Power off function, if any
+ */ 
+void (*pm_power_off)(void);
 
 void disable_hlt(void)
 {
@@ -81,35 +75,86 @@
 	}
 }
 
-void __init reboot_setup(char *str, int *ints)
-{
-}
 
-struct notifier_block *mach_notifier;
+#ifdef __LP64__
+#define COMMAND_GLOBAL  0xfffffffffffe0030UL
+#else
+#define COMMAND_GLOBAL  0xfffe0030
+#endif
+
+#define CMD_RESET       5       /* reset any module */
 
-void machine_restart(char *ptr)
+/*
+** The Wright Brothers and Gecko systems have a H/W problem
+** (Lasi...'nuf said) may cause a broadcast reset to lockup
+** the system. An HVERSION dependent PDC call was developed
+** to perform a "safe", platform specific broadcast reset instead
+** of kludging up all the code.
+**
+** Older machines which do not implement PDC_BROADCAST_RESET will
+** return (with an error) and the regular broadcast reset can be
+** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
+** the PDC call will not return (the system will be reset).
+*/
+void machine_restart(char *cmd)
 {
-	notifier_call_chain(&mach_notifier, MACH_RESTART, ptr);
+#ifdef FASTBOOT_SELFTEST_SUPPORT
+	/*
+	 ** If user has modified the Firmware Selftest Bitmap,
+	 ** run the tests specified in the bitmap after the
+	 ** system is rebooted w/PDC_DO_RESET.
+	 **
+	 ** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
+	 **
+	 ** Using "directed resets" at each processor with the MEM_TOC
+	 ** vector cleared will also avoid running destructive
+	 ** memory self tests. (Not implemented yet)
+	 */
+	if (ftc_bitmap) {
+		pdc_do_firm_test_reset(ftc_bitmap);
+	}
+#endif
+
+	/* "Normal" system reset */
+	pdc_do_reset();
+
+	/* Nope...box should reset with just CMD_RESET now */
+	gsc_writel(CMD_RESET, COMMAND_GLOBAL);
+
+	/* Wait for RESET to lay us to rest. */
+	while (1) ;
+
 }
 
 void machine_halt(void)
 {
-	notifier_call_chain(&mach_notifier, MACH_HALT, NULL);
+	/*
+	** The LED/ChassisCodes are updated by the led_halt()
+	** function, called by the reboot notifier chain.
+	*/
 }
 
-void machine_power_on(void)
-{
-	notifier_call_chain(&mach_notifier, MACH_POWER_ON, NULL);
-}
 
+/*
+ * This routine is called from sys_reboot to actually turn off the
+ * machine 
+ */
 void machine_power_off(void)
 {
-	notifier_call_chain(&mach_notifier, MACH_POWER_OFF, NULL);
-}
+	/* If there is a registered power off handler, call it. */
+	if(pm_power_off)
+		pm_power_off();
+
+	/* Put the soft power button back under hardware control.
+	 * If the user had already pressed the power button, the
+	 * following call will immediately power off. */
+	pdc_soft_power_button(0);
 
+	/* It seems we have no way to power the system off via
+	 * software. The user has to press the button himself. */
 
-void machine_heartbeat(void)
-{
+	printk(KERN_EMERG "System shut down completed.\n"
+	       KERN_EMERG "Please power this system off now.");
 }
 
 
@@ -138,6 +183,9 @@
 
 void flush_thread(void)
 {
+	/* Only needs to handle fpu stuff or perf monitors.
+	** REVISIT: several arches implement a "lazy fpu state".
+	*/
 	set_fs(USER_DS);
 }
 
@@ -148,6 +196,7 @@
 /*
  * Fill in the FPU structure for a core dump.
  */
+
 int dump_fpu (struct pt_regs * regs, elf_fpregset_t *r)
 {
 	memcpy(r, regs->fr, sizeof *r);
@@ -176,7 +225,13 @@
 	    struct task_struct * p, struct pt_regs * pregs)
 {
 	struct pt_regs * cregs = &(p->thread.regs);
-	long ksp;
+	
+	/* We have to use void * instead of a function pointer, because
+	 * function pointers aren't a pointer to the function on 64-bit.
+	 * Make them const so the compiler knows they live in .text */
+	extern void * const ret_from_kernel_thread;
+	extern void * const child_return;
+	extern void * const hpux_child_return;
 
 	*cregs = *pregs;
 
@@ -193,34 +248,37 @@
 	 * in zero for usp.
 	 */
 	if (usp == 0) {
-		/* Kernel Thread */
-		ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
-		cregs->ksp = ksp;	    /* always return to kernel */
-#ifdef __LP64__
+		/* kernel thread */
+		cregs->ksp = (((unsigned long)(p)) + TASK_SZ_ALGN);
+		/* Must exit via ret_from_kernel_thread in order
+		 * to call schedule_tail()
+		 */
 		cregs->kpc = (unsigned long) &ret_from_kernel_thread;
-#else
-		cregs->kpc = (unsigned long) ret_from_kernel_thread;
-#endif
-
 		/*
 		 * Copy function and argument to be called from
 		 * ret_from_kernel_thread.
 		 */
+#ifdef __LP64__
+		cregs->gr[27] = pregs->gr[27];
+#endif
 		cregs->gr[26] = pregs->gr[26];
 		cregs->gr[25] = pregs->gr[25];
-
 	} else {
-		/* User Thread:
-		 *
-		 * Use same stack depth as parent when in wrapper
-		 *
+		/* user thread */
+		/*
 		 * Note that the fork wrappers are responsible
-		 * for setting gr[20] and gr[21].
+		 * for setting gr[21].
 		 */
 
+		/* Use same stack depth as parent */
 		cregs->ksp = ((unsigned long)(p))
-			+ (pregs->gr[20] & (INIT_TASK_SIZE - 1));
-		cregs->kpc = pregs->gr[21];
+			+ (pregs->gr[21] & (INIT_TASK_SIZE - 1));
+		cregs->gr[30] = usp;
+		if (p->personality == PER_HPUX) {
+			cregs->kpc = (unsigned long) &hpux_child_return;
+		} else {
+			cregs->kpc = (unsigned long) &child_return;
+		}
 	}
 
 	return 0;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/processor.c linux/arch/parisc/kernel/processor.c
--- linux.orig/arch/parisc/kernel/processor.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/processor.c	2002-08-12 22:14:05.000000000 +0000
@@ -0,0 +1,374 @@
+/*    $Id: processor.c,v 1.13 2002/07/04 19:33:01 grundler Exp $
+ *
+ *    Initial setup-routines for HP 9000 based hardware.
+ *
+ *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *    Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
+ *    Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
+ *    Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
+ *    Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *    Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
+ *
+ *    Initial PA-RISC Version: 04-23-1999 by Helge Deller
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#define PCI_DEBUG
+#include <linux/pci.h>
+#undef PCI_DEBUG
+
+#include <asm/cache.h>
+#include <asm/hardware.h>	/* for register_parisc_driver() stuff */
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pdc.h>
+#include <asm/irq.h>		/* for struct irq_region */
+
+struct system_cpuinfo_parisc boot_cpu_data;
+struct cpuinfo_parisc cpu_data[NR_CPUS];
+
+/*
+**  	PARISC CPU driver - claim "device" and initialize CPU data structures.
+**
+** Consolidate per CPU initialization into (mostly) one module.
+** Monarch CPU will initialize boot_cpu_data which shouldn't
+** change once the system has booted.
+**
+** The callback *should* do per-instance initialization of
+** everything including the monarch. "Per CPU" init code in
+** setup.c:start_parisc() has migrated here and start_parisc()
+** will call register_parisc_driver(&cpu_driver) before calling do_inventory().
+**
+** The goal of consolidating CPU initialization into one place is
+** to make sure all CPU's get initialized the same way.
+** The code path not shared is how PDC hands control of the CPU to the OS.
+** The initialization of OS data structures is the same (done below).
+*/
+
+/**
+ * processor_probe - Determine if processor driver should claim this device.
+ * @dev: The device which has been found.
+ *
+ * Determine if processor driver should claim this chip (return 0) or not 
+ * (return 1).  If so, initialize the chip and tell other partners in crime 
+ * they have work to do.
+ */
+static int __init processor_probe(struct parisc_device *dev)
+{
+	unsigned long txn_addr;
+	unsigned long cpuid;
+	struct cpuinfo_parisc *p;
+
+#ifndef CONFIG_SMP
+	if (boot_cpu_data.cpu_count > 0) {
+		printk(KERN_INFO "CONFIG_SMP=n  ignoring additional CPUs\n");
+		return 1;
+	}
+#endif
+
+	/* logical CPU ID and update global counter
+	 * May get overwritten by PAT code.
+	 */
+	cpuid = boot_cpu_data.cpu_count;
+	txn_addr = dev->hpa;	/* for legacy PDC */
+
+#ifdef __LP64__
+	if (is_pdc_pat()) {
+		ulong status;
+		unsigned long bytecnt;
+	        pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
+#undef USE_PAT_CPUID
+#ifdef USE_PAT_CPUID
+		struct pdc_pat_cpu_num cpu_info;
+#endif
+
+		status = pdc_pat_cell_module(&bytecnt, dev->pcell_loc,
+			dev->mod_index, PA_VIEW, &pa_pdc_cell);
+
+		ASSERT(PDC_OK == status);
+
+		/* verify it's the same as what do_pat_inventory() found */
+		ASSERT(dev->mod_info == pa_pdc_cell.mod_info);
+		ASSERT(dev->pmod_loc == pa_pdc_cell.mod_location);
+
+		txn_addr = pa_pdc_cell.mod[0];   /* id_eid for IO sapic */
+
+#ifdef USE_PAT_CPUID
+/* We need contiguous numbers for cpuid. Firmware's notion
+ * of cpuid is for physical CPUs and we just don't care yet.
+ * We'll care when we need to query PAT PDC about a CPU *after*
+ * boot time (ie shutdown a CPU from an OS perspective).
+ */
+		/* get the cpu number */
+		status = pdc_pat_cpu_get_number(&cpu_info, dev->hpa);
+
+		ASSERT(PDC_OK == status);
+
+		if (cpu_info.cpu_num >= NR_CPUS) {
+			printk(KERN_WARNING "IGNORING CPU at 0x%x,"
+				" cpu_slot_id > NR_CPUS"
+				" (%ld > %d)\n",
+				dev->hpa, cpu_info.cpu_num, NR_CPUS);
+			/* Ignore CPU since it will only crash */
+			boot_cpu_data.cpu_count--;
+			return 1;
+		} else {
+			cpuid = cpu_info.cpu_num;
+		}
+#endif
+	}
+#endif
+
+	p = &cpu_data[cpuid];
+	boot_cpu_data.cpu_count++;
+
+	/* initialize counters */
+	memset(p, 0, sizeof(struct cpuinfo_parisc));
+
+	p->dev = dev;		/* Save IODC data in case we need it */
+	p->hpa = dev->hpa;	/* save CPU hpa */
+	p->cpuid = cpuid;	/* save CPU id */
+	p->txn_addr = txn_addr;	/* save CPU IRQ address */
+#ifdef CONFIG_SMP
+	p->lock = SPIN_LOCK_UNLOCKED;
+
+	/*
+	** FIXME: review if any other initialization is clobbered
+	**	for boot_cpu by the above memset().
+	*/
+
+	/* stolen from init_percpu_prof() */
+	cpu_data[cpuid].prof_counter = 1;
+	cpu_data[cpuid].prof_multiplier = 1;
+#endif
+
+	/*
+	** CONFIG_SMP: init_smp_config() will attempt to get CPU's into
+	** OS control. RENDEZVOUS is the default state - see mem_set above.
+	**	p->state = STATE_RENDEZVOUS;
+	*/
+
+	/*
+	** itimer and ipi IRQ handlers are statically initialized in
+	** arch/parisc/kernel/irq.c. ie Don't need to register them.
+	*/
+	p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)];
+
+	return 0;
+}
+
+/**
+ * collect_boot_cpu_data - Fill the boot_cpu_data structure.
+ *
+ * This function collects and stores the generic processor information
+ * in the boot_cpu_data structure.
+ */
+void __init collect_boot_cpu_data(void)
+{
+	memset(&boot_cpu_data, 0, sizeof(boot_cpu_data));
+
+	boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
+
+	/* get CPU-Model Information... */
+#define p ((unsigned long *)&boot_cpu_data.pdc.model)
+	if (pdc_model_info(&boot_cpu_data.pdc.model) == PDC_OK)
+		printk(KERN_INFO 
+			"model %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
+			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
+#undef p
+
+	if (pdc_model_versions(&boot_cpu_data.pdc.versions, 0) == PDC_OK)
+		printk(KERN_INFO "vers  %08lx\n", 
+			boot_cpu_data.pdc.versions);
+
+	if (pdc_model_cpuid(&boot_cpu_data.pdc.cpuid) == PDC_OK)
+		printk(KERN_INFO "CPUID vers %ld rev %ld (0x%08lx)\n",
+			(boot_cpu_data.pdc.cpuid >> 5) & 127,
+			boot_cpu_data.pdc.cpuid & 31,
+			boot_cpu_data.pdc.cpuid);
+
+	if (pdc_model_capabilities(&boot_cpu_data.pdc.capabilities) == PDC_OK)
+		printk(KERN_INFO "capabilities 0x%lx\n",
+			boot_cpu_data.pdc.capabilities);
+
+	if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name) == PDC_OK)
+		printk(KERN_INFO "model %s\n",
+			boot_cpu_data.pdc.sys_model_name);
+
+	boot_cpu_data.hversion =  boot_cpu_data.pdc.model.hversion;
+	boot_cpu_data.sversion =  boot_cpu_data.pdc.model.sversion;
+
+	boot_cpu_data.cpu_type =
+			parisc_get_cpu_type(boot_cpu_data.hversion);
+
+	boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0];
+	boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1];
+}
+
+
+/**
+ * init_cpu_profiler - enable/setup per cpu profiling hooks.
+ * @cpunum: The processor instance.
+ *
+ * FIXME: doesn't do much yet...
+ */
+static inline void __init
+init_percpu_prof(int cpunum)
+{
+	cpu_data[cpunum].prof_counter = 1;
+	cpu_data[cpunum].prof_multiplier = 1;
+}
+
+
+/**
+ * init_per_cpu - Handle individual processor initializations.
+ * @cpunum: logical processor number.
+ *
+ * This function handles initialization for *every* CPU
+ * in the system:
+ *
+ * o Set "default" CPU width for trap handlers
+ *
+ * o Enable FP coprocessor
+ *   REVISIT: this could be done in the "code 22" trap handler.
+ *	(frowands idea - that way we know which processes need FP
+ *	registers saved on the interrupt stack.)
+ *   NEWS FLASH: wide kernels need FP coprocessor enabled to handle
+ *	formatted printing of %lx for example (double divides I think)
+ *
+ * o Enable CPU profiling hooks.
+ */
+int __init init_per_cpu(int cpunum)
+{
+	int ret;
+	struct pdc_coproc_cfg coproc_cfg;
+
+	ret = pdc_coproc_cfg(&coproc_cfg);
+
+	if(ret >= 0 && coproc_cfg.ccr_functional) {
+		mtctl(coproc_cfg.ccr_functional, 10);  /* 10 == Coprocessor Control Reg */
+
+		/* FWIW, FP rev/model is a more accurate way to determine
+		** CPU type. CPU rev/model has some ambiguous cases.
+		*/
+		cpu_data[cpunum].fp_rev = coproc_cfg.revision;
+		cpu_data[cpunum].fp_model = coproc_cfg.model;
+
+		printk(KERN_INFO  "FP[%d] enabled: Rev %ld Model %ld\n",
+			cpunum, coproc_cfg.revision, coproc_cfg.model);
+
+		/*
+		** store status register to stack (hopefully aligned)
+		** and clear the T-bit.
+		*/
+		asm volatile ("fstd    %fr0,8(%sp)");
+
+	} else {
+		printk(KERN_WARNING  "WARNING: No FP CoProcessor?!"
+			" (coproc_cfg.ccr_functional == 0x%lx, expected 0xc0)\n"
+#ifdef __LP64__
+			"Halting Machine - FP required\n"
+#endif
+			, coproc_cfg.ccr_functional);
+#ifdef __LP64__
+		mdelay(100);	/* previous chars get pushed to console */
+		panic("FP CoProc not reported");
+#endif
+	}
+
+	/* FUTURE: Enable Performance Monitor : ccr bit 0x20 */
+	init_percpu_prof(cpunum);
+
+	return ret;
+}
+
+/*
+ * Display cpu info for all cpu's.
+ */
+int
+show_cpuinfo (struct seq_file *m, void *v)
+{
+	int	n;
+
+	for(n=0; n<boot_cpu_data.cpu_count; n++) {
+#ifdef CONFIG_SMP
+		if (0 == cpu_data[n].hpa)
+			continue;
+#ifdef ENTRY_SYS_CPUS
+#error iCOD support wants to show CPU state here
+#endif
+#endif
+		seq_printf(m, "processor\t: %d\n"
+				"cpu family\t: PA-RISC %s\n",
+				 n, boot_cpu_data.family_name);
+
+		seq_printf(m, "cpu\t\t: %s\n",  boot_cpu_data.cpu_name );
+
+		/* cpu MHz */
+		seq_printf(m, "cpu MHz\t\t: %d.%06d\n",
+				 boot_cpu_data.cpu_hz / 1000000,
+				 boot_cpu_data.cpu_hz % 1000000  );
+
+		seq_printf(m, "model\t\t: %s\n"
+				"model name\t: %s\n",
+				 boot_cpu_data.pdc.sys_model_name,
+				 cpu_data[n].dev ? 
+				 cpu_data[n].dev->name : "Unknown" );
+
+		seq_printf(m, "hversion\t: 0x%08x\n"
+			        "sversion\t: 0x%08x\n",
+				 boot_cpu_data.hversion,
+				 boot_cpu_data.sversion );
+
+		/* print cachesize info */
+		show_cache_info(m);
+
+		seq_printf(m, "bogomips\t: %lu.%02lu\n",
+			     loops_per_jiffy / (500000 / HZ),
+			     (loops_per_jiffy / (5000 / HZ)) % 100);
+
+		seq_printf(m, "software id\t: %ld\n\n",
+				boot_cpu_data.pdc.model.sw_id);
+	}
+	return 0;
+}
+
+static struct parisc_device_id processor_tbl[] = {
+	{ HPHW_NPROC, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, SVERSION_ANY_ID },
+	{ 0, }
+};
+
+static struct parisc_driver cpu_driver = {
+	name:		"CPU",
+	id_table:	processor_tbl,
+	probe:		processor_probe
+};
+
+/**
+ * processor_init - Processor initalization procedure.
+ *
+ * Register this driver.
+ */
+void __init processor_init(void)
+{
+	register_parisc_driver(&cpu_driver);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/ptrace.c linux/arch/parisc/kernel/ptrace.c
--- linux.orig/arch/parisc/kernel/ptrace.c	2001-09-18 23:56:19.000000000 +0000
+++ linux/arch/parisc/kernel/ptrace.c	2002-08-12 22:14:05.000000000 +0000
@@ -14,6 +14,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
+#include <linux/personality.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -31,6 +32,47 @@
 #define PT_SINGLESTEP	0x10000
 #define PT_BLOCKSTEP	0x20000
 
+/* PSW bits we allow the debugger to modify */
+#define USER_PSW_BITS	(PSW_N | PSW_V | PSW_CB)
+
+#undef DEBUG_PTRACE
+
+#ifdef DEBUG_PTRACE
+#define DBG(x)	printk x
+#else
+#define DBG(x)
+#endif
+
+#ifdef __LP64__
+
+#define CHILD_IS_32BIT	(child->personality == PER_LINUX_32BIT)
+
+/* This function is needed to translate 32 bit pt_regs offsets in to
+ * 64 bit pt_regs offsets.  For example, a 32 bit gdb under a 64 bit kernel
+ * will request offset 12 if it wants gr3, but the lower 32 bits of
+ * the 64 bit kernels view of gr3 will be at offset 28 (3*8 + 4).
+ * This code relies on a 32 bit pt_regs being comprised of 32 bit values
+ * except for the fp registers which (a) are 64 bits, and (b) follow
+ * the gr registers at the start of pt_regs.  The 32 bit pt_regs should
+ * be half the size of the 64 bit pt_regs, plus 32*4 to allow for fr[]
+ * being 64 bit in both cases.
+ */
+
+static long translate_usr_offset(long offset)
+{
+	if (offset < 0)
+		return -1;
+	else if (offset <= 32*4)	/* gr[0..31] */
+		return offset * 2 + 4;
+	else if (offset <= 32*4+32*8)	/* gr[0..31] + fr[0..31] */
+		return offset + 32*4;
+	else if (offset < sizeof(struct pt_regs)/2 + 32*4)
+		return offset * 2 + 4 - 32*8;
+	else
+		return -1;
+}
+#endif
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
@@ -49,6 +91,9 @@
 {
 	struct task_struct *child;
 	long ret;
+#ifdef DEBUG_PTRACE
+	long oaddr=addr, odata=data;
+#endif
 
 	lock_kernel();
 	ret = -EPERM;
@@ -91,14 +136,33 @@
 	switch (request) {
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: {
-		unsigned long tmp;
 		int copied;
 
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			goto out_tsk;
-		ret = put_user(tmp,(unsigned long *) data);
+#ifdef __LP64__
+		if (CHILD_IS_32BIT) {
+			unsigned int tmp;
+
+			addr &= 0xffffffffL;
+			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+			ret = -EIO;
+			if (copied != sizeof(tmp))
+				goto out_tsk;
+			ret = put_user(tmp,(unsigned int *) data);
+			DBG(("sys_ptrace(PEEK%s, %d, %lx, %lx) returning %ld, data %x\n",
+				request == PTRACE_PEEKTEXT ? "TEXT" : "DATA",
+				pid, oaddr, odata, ret, tmp));
+		}
+		else
+#endif
+		{
+			unsigned long tmp;
+
+			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+			ret = -EIO;
+			if (copied != sizeof(tmp))
+				goto out_tsk;
+			ret = put_user(tmp,(unsigned long *) data);
+		}
 		goto out_tsk;
 	}
 
@@ -106,22 +170,53 @@
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
 		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			goto out_tsk;
+#ifdef __LP64__
+		if (CHILD_IS_32BIT) {
+			unsigned int tmp = (unsigned int)data;
+			DBG(("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
+				request == PTRACE_POKETEXT ? "TEXT" : "DATA",
+				pid, oaddr, odata));
+			addr &= 0xffffffffL;
+			if (access_process_vm(child, addr, &tmp, sizeof(tmp), 1) == sizeof(tmp))
+				goto out_tsk;
+		}
+		else
+#endif
+		{
+			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+				goto out_tsk;
+		}
 		ret = -EIO;
 		goto out_tsk;
 
-	/* Read the word at location addr in the USER area.  This will need
-	   to change when the kernel no longer saves all regs on a syscall. */
+	/* Read the word at location addr in the USER area.  For ptraced
+	   processes, the kernel saves all regs on a syscall. */
 	case PTRACE_PEEKUSR: {
-		unsigned long tmp;
-
 		ret = -EIO;
-		if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs))
-			goto out_tsk;
-
-		tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
-		ret = put_user(tmp, (unsigned long *) data);
+#ifdef __LP64__
+		if (CHILD_IS_32BIT) {
+			unsigned int tmp;
+
+			if (addr & (sizeof(int)-1))
+				goto out_tsk;
+			if ((addr = translate_usr_offset(addr)) < 0)
+				goto out_tsk;
+
+			tmp = *(unsigned int *) ((char *) task_regs(child) + addr);
+			ret = put_user(tmp, (unsigned int *) data);
+			DBG(("sys_ptrace(PEEKUSR, %d, %lx, %lx) returning %ld, addr %lx, data %x\n",
+				pid, oaddr, odata, ret, addr, tmp));
+		}
+		else
+#endif
+		{
+			unsigned long tmp;
+
+			if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
+				goto out_tsk;
+			tmp = *(unsigned long *) ((char *) task_regs(child) + addr);
+			ret = put_user(tmp, (unsigned long *) data);
+		}
 		goto out_tsk;
 	}
 
@@ -133,25 +228,73 @@
 	   exit. */
 	case PTRACE_POKEUSR:
 		ret = -EIO;
-		if ((addr & 3) || (unsigned long) addr >= sizeof(struct pt_regs))
-			goto out_tsk;
-		/* XXX This test probably needs adjusting.  We probably want to
-		 * allow writes to some bits of PSW, and may want to block writes
-		 * to (some) space registers.  Some register values written here
-		 * may be ignored in entry.S:syscall_restore_rfi; e.g. iaoq is
-		 * written with r31/r31+4, and not with the values in pt_regs.
+		/* Some register values written here may be ignored in
+		 * entry.S:syscall_restore_rfi; e.g. iaoq is written with
+		 * r31/r31+4, and not with the values in pt_regs.
+		 */
+		 /* PT_PSW=0, so this is valid for 32 bit processes under 64
+		 * bit kernels.
 		 */
-		/* Allow writing of gr1-gr31, fr*, sr*, iasq*, iaoq*, sar */
-		if (addr == PT_PSW || (addr > PT_IAOQ1 && addr != PT_SAR))
+		if (addr == PT_PSW) {
+			/* PT_PSW=0, so this is valid for 32 bit processes
+			 * under 64 bit kernels.
+			 *
+			 * Allow writing to Nullify, Divide-step-correction,
+			 * and carry/borrow bits.
+			 * BEWARE, if you set N, and then single step, it wont
+			 * stop on the nullified instruction.
+			 */
+			DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx)\n",
+				pid, oaddr, odata));
+			data &= USER_PSW_BITS;
+			task_regs(child)->gr[0] &= ~USER_PSW_BITS;
+			task_regs(child)->gr[0] |= data;
+			ret = 0;
 			goto out_tsk;
-
-		*(unsigned long *) ((char *) task_regs(child) + addr) = data;
-		ret = 0;
-		goto out_tsk;
+		}
+#ifdef __LP64__
+		if (CHILD_IS_32BIT) {
+			if (addr & (sizeof(int)-1))
+				goto out_tsk;
+			if ((addr = translate_usr_offset(addr)) < 0)
+				goto out_tsk;
+			DBG(("sys_ptrace(POKEUSR, %d, %lx, %lx) addr %lx\n",
+				pid, oaddr, odata, addr));
+			if (addr >= PT_FR0 && addr <= PT_FR31) {
+				/* Special case, fp regs are 64 bits anyway */
+				*(unsigned int *) ((char *) task_regs(child) + addr) = data;
+				ret = 0;
+			}
+			else if ((addr >= PT_GR1+4 && addr <= PT_GR31+4) ||
+					addr == PT_IAOQ0+4 || addr == PT_IAOQ1+4 ||
+					addr == PT_SAR+4) {
+				/* Zero the top 32 bits */
+				*(unsigned int *) ((char *) task_regs(child) + addr - 4) = 0;
+				*(unsigned int *) ((char *) task_regs(child) + addr) = data;
+				ret = 0;
+			}
+			goto out_tsk;
+		}
+		else
+#endif
+		{
+			if ((addr & (sizeof(long)-1)) || (unsigned long) addr >= sizeof(struct pt_regs))
+				goto out_tsk;
+			if ((addr >= PT_GR1 && addr <= PT_GR31) ||
+					addr == PT_IAOQ0 || addr == PT_IAOQ1 ||
+					(addr >= PT_FR0 && addr <= PT_FR31) ||
+					addr == PT_SAR) {
+				*(unsigned long *) ((char *) task_regs(child) + addr) = data;
+				ret = 0;
+			}
+			goto out_tsk;
+		}
 
 	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 	case PTRACE_CONT:
 		ret = -EIO;
+		DBG(("sys_ptrace(%s)\n",
+			request == PTRACE_SYSCALL ? "SYSCALL" : "CONT"));
 		if ((unsigned long) data > _NSIG)
 			goto out_tsk;
 		child->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP);
@@ -168,12 +311,14 @@
 		 * sigkill.  perhaps it should be put in the status
 		 * that it wants to exit.
 		 */
+		DBG(("sys_ptrace(KILL)\n"));
 		if (child->state == TASK_ZOMBIE)	/* already dead */
 			goto out_tsk;
 		child->exit_code = SIGKILL;
 		goto out_wake_notrap;
 
 	case PTRACE_SINGLEBLOCK:
+		DBG(("sys_ptrace(SINGLEBLOCK)\n"));
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			goto out_tsk;
@@ -189,6 +334,7 @@
 		goto out_wake;
 
 	case PTRACE_SINGLESTEP:
+		DBG(("sys_ptrace(SINGLESTEP)\n"));
 		ret = -EIO;
 		if ((unsigned long) data > _NSIG)
 			goto out_tsk;
@@ -208,10 +354,7 @@
 			pa_psw(child)->y = 0;
 			pa_psw(child)->z = 0;
 			pa_psw(child)->b = 0;
-			pa_psw(child)->r = 0;
-			pa_psw(child)->t = 0;
-			pa_psw(child)->h = 0;
-			pa_psw(child)->l = 0;
+			ptrace_disable(child);
 			/* Don't wake up the child, but let the
 			   parent know something happened. */
 			si.si_code = TRAP_TRACE;
@@ -249,11 +392,7 @@
 	}
 
 out_wake_notrap:
-	/* make sure the trap bits are not set */
-	pa_psw(child)->r = 0;
-	pa_psw(child)->t = 0;
-	pa_psw(child)->h = 0;
-	pa_psw(child)->l = 0;
+	ptrace_disable(child);
 out_wake:
 	wake_up_process(child);
 	ret = 0;
@@ -261,6 +400,8 @@
 	free_task_struct(child);
 out:
 	unlock_kernel();
+	DBG(("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n",
+		request, pid, oaddr, odata, ret));
 	return ret;
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/real1.c linux/arch/parisc/kernel/real1.c
--- linux.orig/arch/parisc/kernel/real1.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/real1.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,154 +0,0 @@
-/*
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- *
- * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
- *
- * most of these calls might reasonably be moved to ../kernel -PB
- *
- * The basic principle is to construct a stack frame in C then call
- * some assembly which adopts that stack, does some rfi magic, may
- * switch wide/narrow mode, and calls the routine described by the
- * 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!!
- */
-#include <linux/spinlock.h>
-#include <asm/system.h>
-#include <stdarg.h>
-#include <asm/pgtable.h>		/* for __pa() */
-#include <asm/pdc.h>
-
-static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
-
-/***************** 32-bit real-mode calls ***********/
-/* The struct below is used
- * to overlay real_stack (real2.S), preparing a 32-bit call frame.
- * real32_call_asm() then uses this stack in narrow real mode
- */
-
-struct narrow_stack {
-    /* use int, not long which is 64 bits */
-    unsigned int arg13;
-    unsigned int arg12;
-    unsigned int arg11;
-    unsigned int arg10;
-    unsigned int arg9;
-    unsigned int arg8;
-    unsigned int arg7;
-    unsigned int arg6;
-    unsigned int arg5;
-    unsigned int arg4;
-    unsigned int arg3;
-    unsigned int arg2;
-    unsigned int arg1;
-    unsigned int arg0;
-    unsigned int frame_marker[8];
-    unsigned int sp;
-    /* in reality, there's nearly 8k of stack after this */
-};
-
-long
-real32_call(unsigned long fn, ...)
-{
-    unsigned long r;
-    va_list args;
-    unsigned long flags;
-    extern struct narrow_stack real_stack;
-    extern unsigned long real32_call_asm(unsigned int *,
-				unsigned int *, unsigned int);
-    
-    va_start(args, fn);
-    real_stack.arg0 = va_arg(args, unsigned int);
-    real_stack.arg1 = va_arg(args, unsigned int);
-    real_stack.arg2 = va_arg(args, unsigned int);
-    real_stack.arg3 = va_arg(args, unsigned int);
-    real_stack.arg4 = va_arg(args, unsigned int);
-    real_stack.arg5 = va_arg(args, unsigned int);
-    real_stack.arg6 = va_arg(args, unsigned int);
-    real_stack.arg7 = va_arg(args, unsigned int);
-    real_stack.arg8 = va_arg(args, unsigned int);
-    real_stack.arg9 = va_arg(args, unsigned int);
-    real_stack.arg10 = va_arg(args, unsigned int);
-    real_stack.arg11 = va_arg(args, unsigned int);
-    real_stack.arg12 = va_arg(args, unsigned int);
-    real_stack.arg13 = va_arg(args, unsigned int);
-    va_end(args);
-
-    if (fn == 0) {
-	    /* mem_pdc call */
-	    fn = PAGE0->mem_pdc;
-    }
-
-    spin_lock_irqsave(&pdc_lock, flags);
-    r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
-    spin_unlock_irqrestore(&pdc_lock, flags);
-
-    return r;
-}
-
-#ifdef __LP64__
-/***************** 64-bit real-mode calls ***********/
-
-struct wide_stack {
-    unsigned long arg0;
-    unsigned long arg1;
-    unsigned long arg2;
-    unsigned long arg3;
-    unsigned long arg4;
-    unsigned long arg5;
-    unsigned long arg6;
-    unsigned long arg7;
-    unsigned long arg8;
-    unsigned long arg9;
-    unsigned long arg10;
-    unsigned long arg11;
-    unsigned long arg12;
-    unsigned long arg13;
-    unsigned long frame_marker[2];	/* rp, previous sp */
-    unsigned long sp;
-    /* in reality, there's nearly 8k of stack after this */
-};
-
-long
-real64_call(unsigned long fn, ...)
-{
-    unsigned long r;
-    va_list args;
-    unsigned long flags;
-    extern struct wide_stack real_stack;
-    extern unsigned long real64_call_asm(unsigned long *,
-				unsigned long *, unsigned long);
-    
-    va_start(args, fn);
-    real_stack.arg0 = va_arg(args, unsigned long);
-    real_stack.arg1 = va_arg(args, unsigned long);
-    real_stack.arg2 = va_arg(args, unsigned long);
-    real_stack.arg3 = va_arg(args, unsigned long);
-    real_stack.arg4 = va_arg(args, unsigned long);
-    real_stack.arg5 = va_arg(args, unsigned long);
-    real_stack.arg6 = va_arg(args, unsigned long);
-    real_stack.arg7 = va_arg(args, unsigned long);
-    real_stack.arg8 = va_arg(args, unsigned long);
-    real_stack.arg9 = va_arg(args, unsigned long);
-    real_stack.arg10 = va_arg(args, unsigned long);
-    real_stack.arg11 = va_arg(args, unsigned long);
-    real_stack.arg12 = va_arg(args, unsigned long);
-    real_stack.arg13 = va_arg(args, unsigned long);
-    va_end(args);
-
-    if (fn == 0) {
-	    /* mem_pdc call */
-	    fn = PAGE0->mem_pdc_hi;
-	    fn <<= 32;
-	    fn |= PAGE0->mem_pdc;
-    }
-
-    spin_lock_irqsave(&pdc_lock, flags);
-    r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
-    spin_unlock_irqrestore(&pdc_lock, flags);
-
-    return r;
-}
-
-#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/real2.S linux/arch/parisc/kernel/real2.S
--- linux.orig/arch/parisc/kernel/real2.S	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/kernel/real2.S	2002-08-12 22:14:20.000000000 +0000
@@ -7,7 +7,6 @@
  * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
  *
  */
-#define __ASSEMBLY__
 #include <asm/assembly.h>
 #include <asm/psw.h>
 
@@ -31,8 +30,11 @@
 
 /************************ 32-bit real-mode calls ***********************/
 /* This can be called in both narrow and wide kernels */
+
 	.text
+
 	.export real32_call_asm
+
 	/* unsigned long real32_call_asm(unsigned int *sp,
 	 *		unsigned int *arg0p,
 	 *		unsigned int iodc_fn)
@@ -40,6 +42,7 @@
 	 *	arg0p points to where saved arg values may be found
 	 *	iodc_fn is the IODC function to call
 	 */
+
 real32_call_asm:
 	STREG	%rp, -RP_OFFSET(%sp)	/* save RP */
 #ifdef __LP64__
@@ -61,7 +64,7 @@
 	ldw	-12(%arg1), %arg3
 	ldw	-4(%arg1), %arg1	/* obviously must do this one last! */
 
-	tophys	%sp
+	tophys_r1  %sp
 
 	b,l	rfi_virt2real,%r2
 	nop
@@ -88,7 +91,7 @@
 	b,l	rfi_real2virt,%r2
 	nop
 
-	tovirt	%sp
+	tovirt_r1 %sp
 	LDREG	-REG_SZ(%sp), %sp	/* restore SP */
 #ifdef __LP64__
 	LDREG	-1*REG_SZ(%sp), %r27
@@ -150,14 +153,14 @@
 	nop
 	nop
 	
-	mtsm		0		/* disable interruptions */
+	rsm             (PSW_SM_Q|PSW_SM_I),%r0  /* disable Q & I bits to load iia queue */
 	mtctl		0, %cr17	/* space 0 */
 	mtctl		0, %cr17
 	load32		PA(rfi_v2r_1), %r1
 	mtctl		%r1, %cr18
 	ldo		4(%r1), %r1
 	mtctl		%r1, %cr18
-	load32		PDC_PSW, %r1
+	load32          REAL_MODE_PSW, %r1
 	mtctl		%r1, %cr22
 	rfi
 	
@@ -170,7 +173,7 @@
 	nop
 	nop
 rfi_v2r_1:
-	tophys	%r2
+	tophys_r1 %r2
 	bv	0(%r2)
 	nop
 
@@ -187,7 +190,7 @@
 	nop
 	nop
 	
-	mtsm		0		/* disable interruptions */
+	rsm             PSW_SM_Q,%r0    /* disable Q bit to load iia queue */
 	mtctl		0, %cr17	/* space 0 */
 	mtctl		0, %cr17
 	load32		(rfi_r2v_1), %r1
@@ -207,7 +210,7 @@
 	nop
 	nop
 rfi_r2v_1:
-	tovirt	%r2
+	tovirt_r1 %r2
 	bv	0(%r2)
 	nop
 
@@ -246,7 +249,7 @@
 	ldd	7*REG_SZ(%arg1), %r19
 	ldd	1*REG_SZ(%arg1), %arg1		/* do this one last! */
 
-	tophys	%sp
+	tophys_r1 %sp
 
 	b,l	rfi_virt2real,%r2
 	nop
@@ -265,10 +268,18 @@
 	b,l	rfi_real2virt,%r2
 	nop
 
-	tovirt	%sp
+	tovirt_r1 %sp
 	ldd	-8(%sp), %sp		/* restore SP */
 	ldd	-0x10(%sp), %rp		/* restore RP */
 	bv	0(%rp)
 	nop
 
 #endif
+	.export pc_in_user_space
+	.text
+	/* Doesn't belong here but I couldn't find a nicer spot. */
+	/* Should never get called, only used by profile stuff in time.c */
+pc_in_user_space:
+	bv,n	0(%rp)
+	nop
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/sba_iommu.c linux/arch/parisc/kernel/sba_iommu.c
--- linux.orig/arch/parisc/kernel/sba_iommu.c	2001-10-12 22:35:53.000000000 +0000
+++ linux/arch/parisc/kernel/sba_iommu.c	2002-08-12 22:14:08.000000000 +0000
@@ -15,7 +15,6 @@
 ** This module initializes the IOC (I/O Controller) found on B1000/C3000/
 ** J5000/J7000/N-class/L-class machines and their successors.
 **
-** FIXME: Multi-IOC support missing - depends on hp_device data
 ** FIXME: add DMA hint support programming in both sba and lba modules.
 */
 
@@ -28,7 +27,7 @@
 
 #include <linux/mm.h>
 #include <linux/string.h>
-#define PCI_DEBUG		/* for ASSERT */
+#undef PCI_DEBUG		/* for ASSERT */
 #include <linux/pci.h>
 #undef PCI_DEBUG
 
@@ -36,19 +35,19 @@
 #include <asm/io.h>
 #include <asm/dma.h>		/* for DMA_CHUNK_SIZE */
 
-#include <asm/hardware.h>	/* for register_driver() stuff */
+#include <asm/hardware.h>	/* for register_parisc_driver() stuff */
 #include <asm/gsc.h>		/* FIXME: for gsc_read/gsc_write */
 
 #include <linux/proc_fs.h>
 #include <asm/runway.h>		/* for proc_runway_root */
-
+#include <asm/pdc.h>		/* for PDC_MODEL_* */
 
 #define MODULE_NAME "SBA"
 
 /*
 ** The number of debug flags is a clue - this code is fragile.
 ** Don't even think about messing with it unless you have
-** plenty of 710's to sacrafice to the computer gods. :^)
+** plenty of 710's to sacrifice to the computer gods. :^)
 */
 #undef DEBUG_SBA_INIT
 #undef DEBUG_SBA_RUN
@@ -56,12 +55,9 @@
 #undef DEBUG_SBA_RESOURCE
 #undef ASSERT_PDIR_SANITY
 #undef DEBUG_LARGE_SG_ENTRIES
+#undef DEBUG_DMB_TRAP
 
-#if 1
-#define SBA_INLINE
-#else
 #define SBA_INLINE	__inline__
-#endif
 
 #ifdef DEBUG_SBA_INIT
 #define DBG_INIT(x...)	printk(x)
@@ -95,73 +91,43 @@
 ** allocated and free'd/purged at a time might make this
 ** less interesting).
 */
-#if 0
 #define DELAYED_RESOURCE_CNT	16
-#else
-#undef DELAYED_RESOURCE_CNT
-#endif
 
 #define DEFAULT_DMA_HINT_REG	0
 
-#define ASTRO_RUNWAY_PORT    0x582
-#define ASTRO_ROPES_PORT     0x780
-
-#define IKE_MERCED_PORT      0x803
-#define IKE_ROPES_PORT       0x781
-
-int sba_driver_callback(struct hp_device *, struct pa_iodc_driver *);
+#define ASTRO_RUNWAY_PORT	0x582
+#define ASTRO_ROPES_PORT	0x780
 
-static struct pa_iodc_driver sba_drivers_for[] = {
+#define IKE_MERCED_PORT		0x803
+#define IKE_ROPES_PORT		0x781
 
-/* FIXME: why is SVERSION checked? */
-
-   {HPHW_IOA, ASTRO_RUNWAY_PORT, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
-
-   {HPHW_BCPORT, ASTRO_ROPES_PORT, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
-
-#if 0
-/* FIXME : N-class! Use a different "callback"? */
-   {HPHW_BCPORT, IKE_MERCED_PORT, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
-
-   {HPHW_BCPORT, IKE_ROPES_PORT, 0x0, 0xb, 0, 0x10,
-		DRIVER_CHECK_HVERSION +
-		DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
-                MODULE_NAME, "I/O MMU", (void *) sba_driver_callback},
-#endif
-
-   {0,0,0,0,0,0,
-   0,
-   (char *) NULL, (char *) NULL, (void *) NULL }
-};
+#define REO_MERCED_PORT		0x804
+#define REO_ROPES_PORT		0x782
 
+#define REOG_MERCED_PORT	0x805
+#define REOG_ROPES_PORT		0x783
 
 #define SBA_FUNC_ID	0x0000	/* function id */
 #define SBA_FCLASS	0x0008	/* function class, bist, header, rev... */
 
-#define IS_ASTRO(id) ( \
-    (((id)->hw_type == HPHW_IOA) && ((id)->hversion == ASTRO_RUNWAY_PORT)) || \
-    (((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == ASTRO_ROPES_PORT))  \
-)
+#define IS_ASTRO(id) \
+(((id)->hversion == ASTRO_RUNWAY_PORT) || ((id)->hversion == ASTRO_ROPES_PORT))
+
+#define IS_IKE(id) \
+(((id)->hversion == IKE_MERCED_PORT) || ((id)->hversion == IKE_ROPES_PORT))
 
-#define CONFIG_FUNC_SIZE 4096   /* SBA configuration function reg set */
+#define SBA_FUNC_SIZE 4096   /* SBA configuration function reg set */
 
 #define ASTRO_IOC_OFFSET 0x20000
 /* Ike's IOC's occupy functions 2 and 3 (not 0 and 1) */
-#define IKE_IOC_OFFSET(p) ((p+2)*CONFIG_FUNC_SIZE)
+#define IKE_IOC_OFFSET(p) ((p+2)*SBA_FUNC_SIZE)
 
 #define IOC_CTRL          0x8	/* IOC_CTRL offset */
-#define IOC_CTRL_TE       (0x1 << 0) /* TOC Enable */
-#define IOC_CTRL_RM       (0x1 << 8) /* Real Mode */
-#define IOC_CTRL_NC       (0x1 << 9) /* Non Coherent Mode */
+#define IOC_CTRL_TC       (1 << 0) /* TOC Enable */
+#define IOC_CTRL_CE       (1 << 1) /* Coalesce Enable */
+#define IOC_CTRL_DE       (1 << 2) /* Dillon Enable */
+#define IOC_CTRL_RM       (1 << 8) /* Real Mode */
+#define IOC_CTRL_NC       (1 << 9) /* Non Coherent Mode */
 
 #define MAX_IOC		2	/* per Ike. Astro only has 1 */
 
@@ -233,18 +199,22 @@
 
 
 struct ioc {
-	char    *ioc_hpa;	/* I/O MMU base address */
+	unsigned long	ioc_hpa;	/* I/O MMU base address */
 	char	*res_map;	/* resource map, bit == pdir entry */
 	u64	*pdir_base;	/* physical base address */
 
-	unsigned long	*res_hint;	/* next available IOVP - circular search */
+	unsigned long	*res_hint;	/* next avail IOVP - circular search */
+	spinlock_t	res_lock;
+	unsigned long	hint_mask_pdir;	/* bits used for DMA hints */
 	unsigned int	res_bitshift;	/* from the LEFT! */
 	unsigned int	res_size;	/* size of resource map in bytes */
 	unsigned int	hint_shift_pdir;
-	spinlock_t	res_lock;
-	unsigned long	hint_mask_pdir;		/* bits used for DMA hints */
-#ifdef DELAYED_RESOURCE_CNT
-	dma_addr_t res_delay[DELAYED_RESOURCE_CNT];
+#if DELAYED_RESOURCE_CNT > 0
+	int saved_cnt;
+	struct sba_dma_pair {
+		dma_addr_t	iova;
+		size_t		size;
+	} saved[DELAYED_RESOURCE_CNT];
 #endif
 
 #ifdef CONFIG_PROC_FS
@@ -269,23 +239,32 @@
 };
 
 struct sba_device {
-	struct sba_device	*next;	/* list of LBA's in system */
-	struct hp_device	*iodc;	/* data about dev from firmware */
-	char			*sba_hpa; /* base address */
+	struct sba_device	*next;	/* list of SBA's in system */
+	struct parisc_device	*dev;	/* dev found in bus walk */
+	struct parisc_device_id	*iodc;	/* data about dev from firmware */
+	const char 		*name;
+	unsigned long		sba_hpa; /* base address */
 	spinlock_t		sba_lock;
-	unsigned int			flags;  /* state/functionality enabled */
-	unsigned int			hw_rev;  /* HW revision of chip */
+	unsigned int		flags;  /* state/functionality enabled */
+	unsigned int		hw_rev;  /* HW revision of chip */
 
-	unsigned int			num_ioc;  /* number of on-board IOC's */
+	unsigned int		num_ioc;  /* number of on-board IOC's */
 	struct ioc		ioc[MAX_IOC];
 };
 
 
 static struct sba_device *sba_list;
-static int sba_count;
+
+static unsigned long ioc_needs_fdc = 0;
 
 /* Ratio of Host MEM to IOV Space size */
-static unsigned long sba_mem_ratio = 4;
+static unsigned long sba_mem_ratio = 8;
+
+/* global count of IOMMUs in the system */
+static unsigned int global_ioc_cnt = 0;
+
+/* PA8700 (Piranha 2.2) bug workaround */
+static unsigned long piranha_bad_128k = 0;
 
 /* Looks nice and keeps the compiler happy */
 #define SBA_DEV(d) ((struct sba_device *) (d))
@@ -299,73 +278,75 @@
 **
 ** BE WARNED: register writes are posted.
 **  (ie follow writes which must reach HW with a read)
+**
+** Superdome (in particular, REO) allows only 64-bit CSR accesses.
 */
-#define READ_U8(addr)  gsc_readb(addr)
-#define READ_U16(addr) gsc_readw((u16 *) (addr))
-#define READ_U32(addr) gsc_readl((u32 *) (addr))
-#define WRITE_U8(value, addr) gsc_writeb(value, addr)
-#define WRITE_U16(value, addr) gsc_writew(value, (u16 *) (addr))
-#define WRITE_U32(value, addr) gsc_writel(value, (u32 *) (addr))
-
-#define READ_REG8(addr)  gsc_readb(addr)
-#define READ_REG16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
-#define READ_REG32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
-#define READ_REG64(addr) le64_to_cpu(gsc_readq((u64 *) (addr)))
-#define WRITE_REG8(value, addr) gsc_writeb(value, addr)
-#define WRITE_REG16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
-#define WRITE_REG32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
-#define WRITE_REG64(value, addr) gsc_writeq(cpu_to_le64(value), (u64 *) (addr))
+#define READ_REG32(addr)	 le32_to_cpu(__raw_readl(addr))
+#define READ_REG64(addr)	 le64_to_cpu(__raw_readq(addr))
+#define WRITE_REG32(val, addr) __raw_writel(cpu_to_le32(val), addr)
+#define WRITE_REG64(val, addr) __raw_writeq(cpu_to_le64(val), addr)
+
+#ifdef __LP64__
+#define READ_REG(addr)		READ_REG64(addr)
+#define WRITE_REG(value, addr)	WRITE_REG64(value, addr)
+#else
+#define READ_REG(addr)		READ_REG32(addr)
+#define WRITE_REG(value, addr)	WRITE_REG32(value, addr)
+#endif
 
 #ifdef DEBUG_SBA_INIT
 
+/* NOTE: When __LP64__ isn't defined, READ_REG64() is two 32-bit reads */
+
+/**
+ * sba_dump_ranges - debugging only - print ranges assigned to this IOA
+ * @hpa: base address of the sba
+ *
+ * Print the MMIO and IO Port address ranges forwarded by an Astro/Ike/RIO
+ * IO Adapter (aka Bus Converter).
+ */
 static void
-sba_dump_ranges(char *hpa)
+sba_dump_ranges(unsigned long hpa)
 {
-	printk("SBA at 0x%p\n", hpa);
-	printk("IOS_DIST_BASE   : %08x %08x\n",
-			READ_REG32(hpa+IOS_DIST_BASE+4),
-			READ_REG32(hpa+IOS_DIST_BASE));
-	printk("IOS_DIST_MASK   : %08x %08x\n",
-			READ_REG32(hpa+IOS_DIST_MASK+4),
-			READ_REG32(hpa+IOS_DIST_MASK));
-	printk("IOS_DIST_ROUTE  : %08x %08x\n",
-			READ_REG32(hpa+IOS_DIST_ROUTE+4),
-			READ_REG32(hpa+IOS_DIST_ROUTE));
-	printk("\n");
-	printk("IOS_DIRECT_BASE : %08x %08x\n",
-			READ_REG32(hpa+IOS_DIRECT_BASE+4),
-			READ_REG32(hpa+IOS_DIRECT_BASE));
-	printk("IOS_DIRECT_MASK : %08x %08x\n",
-			READ_REG32(hpa+IOS_DIRECT_MASK+4),
-			READ_REG32(hpa+IOS_DIRECT_MASK));
-	printk("IOS_DIRECT_ROUTE: %08x %08x\n",
-			READ_REG32(hpa+IOS_DIRECT_ROUTE+4),
-			READ_REG32(hpa+IOS_DIRECT_ROUTE));
+	DBG_INIT("SBA at 0x%lx\n", hpa);
+	DBG_INIT("IOS_DIST_BASE   : %Lx\n", READ_REG64(hpa+IOS_DIST_BASE));
+	DBG_INIT("IOS_DIST_MASK   : %Lx\n", READ_REG64(hpa+IOS_DIST_MASK));
+	DBG_INIT("IOS_DIST_ROUTE  : %Lx\n", READ_REG64(hpa+IOS_DIST_ROUTE));
+	DBG_INIT("\n");
+	DBG_INIT("IOS_DIRECT_BASE : %Lx\n", READ_REG64(hpa+IOS_DIRECT_BASE));
+	DBG_INIT("IOS_DIRECT_MASK : %Lx\n", READ_REG64(hpa+IOS_DIRECT_MASK));
+	DBG_INIT("IOS_DIRECT_ROUTE: %Lx\n", READ_REG64(hpa+IOS_DIRECT_ROUTE));
 }
 
+/**
+ * sba_dump_tlb - debugging only - print IOMMU operating parameters
+ * @hpa: base address of the IOMMU
+ *
+ * Print the size/location of the IO MMU PDIR.
+ */
 static void
-sba_dump_tlb(char *hpa)
+sba_dump_tlb(unsigned long hpa)
 {
-	printk("IO TLB at 0x%p\n", hpa);
-	printk("IOC_IBASE   : %08x %08x\n",
-			READ_REG32(hpa+IOC_IBASE+4),
-			READ_REG32(hpa+IOC_IBASE));
-	printk("IOC_IMASK   : %08x %08x\n",
-			READ_REG32(hpa+IOC_IMASK+4),
-			READ_REG32(hpa+IOC_IMASK));
-	printk("IOC_TCNFG   : %08x %08x\n",
-			READ_REG32(hpa+IOC_TCNFG+4),
-			READ_REG32(hpa+IOC_TCNFG));
-	printk("IOC_PDIR_BASE: %08x %08x\n",
-			READ_REG32(hpa+IOC_PDIR_BASE+4),
-			READ_REG32(hpa+IOC_PDIR_BASE));
-	printk("\n");
+	DBG_INIT("IO TLB at 0x%lx\n", hpa);
+	DBG_INIT("IOC_IBASE    : %Lx\n", READ_REG64(hpa+IOC_IBASE));
+	DBG_INIT("IOC_IMASK    : %Lx\n", READ_REG64(hpa+IOC_IMASK));
+	DBG_INIT("IOC_TCNFG    : %Lx\n", READ_REG64(hpa+IOC_TCNFG));
+	DBG_INIT("IOC_PDIR_BASE: %Lx\n", READ_REG64(hpa+IOC_PDIR_BASE));
+	DBG_INIT("\n");
 }
 #endif
 
 
 #ifdef ASSERT_PDIR_SANITY
 
+/**
+ * sba_dump_pdir_entry - debugging only - print one IOMMU PDIR entry
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @msg: text to print ont the output line.
+ * @pide: pdir index.
+ *
+ * Print one entry of the IO MMU PDIR in human readable form.
+ */
 static void
 sba_dump_pdir_entry(struct ioc *ioc, char *msg, uint pide)
 {
@@ -374,24 +355,30 @@
 	unsigned long *rptr = (unsigned long *) &(ioc->res_map[(pide >>3) & ~(sizeof(unsigned long) - 1)]);
 	uint rcnt;
 
-	printk("SBA: %s rp %p bit %d rval 0x%lx\n",
+	printk(KERN_DEBUG "SBA: %s rp %p bit %d rval 0x%lx\n",
 		 msg,
 		 rptr, pide & (BITS_PER_LONG - 1), *rptr);
 
 	rcnt = 0;
 	while (rcnt < BITS_PER_LONG) {
-		printk("%s %2d %p %016Lx\n",
+		printk(KERN_DEBUG "%s %2d %p %016Lx\n",
 			(rcnt == (pide & (BITS_PER_LONG - 1)))
 				? "    -->" : "       ",
 			rcnt, ptr, *ptr );
 		rcnt++;
 		ptr++;
 	}
-	printk(msg);
+	printk(KERN_DEBUG "%s", msg);
 }
 
 
-/* Verify the resource map and pdir state is consistent */
+/**
+ * sba_check_pdir - debugging only - consistency checker
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @msg: text to print ont the output line.
+ *
+ * Verify the resource map and pdir state is consistent
+ */
 static int
 sba_check_pdir(struct ioc *ioc, char *msg)
 {
@@ -428,15 +415,23 @@
 }
 
 
+/**
+ * sba_dump_sg - debugging only - print Scatter-Gather list
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg: head of the SG list
+ * @nents: number of entries in SG list
+ *
+ * print the SG list so we can verify it's correct by hand.
+ */
 static void
 sba_dump_sg( struct ioc *ioc, struct scatterlist *startsg, int nents)
 {
 	while (nents-- > 0) {
-		printk(" %d : %08lx/%05x %p/%05x\n",
+		printk(KERN_DEBUG " %d : %08lx/%05x %p/%05x\n",
 				nents,
 				(unsigned long) sg_dma_address(startsg),
 				sg_dma_len(startsg),
-				startsg->address, startsg->length);
+				sg_virt_addr(startsg), startsg->length);
 		startsg++;
 	}
 }
@@ -445,25 +440,6 @@
 
 
 
-/*
-** One time initialization to let the world know the LBA was found.
-** This is the only routine which is NOT static.
-** Must be called exactly once before pci_init().
-*/
-void __init
-sba_init(void)
-{
-	sba_list = (struct sba_device *) NULL;
-	sba_count = 0;
-
-#ifdef DEBUG_SBA_INIT
-	sba_dump_ranges((char *) 0xFED00000L);
-#endif
-
-	register_driver(sba_drivers_for);
-}
-
-
 
 /**************************************************************
 *
@@ -489,13 +465,15 @@
 #define RESMAP_IDX_MASK   (sizeof(unsigned long) - 1)
 
 
-/*
-** Perf optimizations:
-** o search for log2(size) bits at a time.
-**
-** Search should use register width as "stride" to search the res_map. 
-*/
-
+/**
+ * sba_search_bitmap - find free space in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @bits_wanted: number of entries we need.
+ *
+ * Find consecutive free bits in resource bitmap.
+ * Each bit represents one entry in the IO Pdir.
+ * Cool perf optimization: search for log2(size) bits at a time.
+ */
 static SBA_INLINE unsigned long
 sba_search_bitmap(struct ioc *ioc, unsigned long bits_wanted)
 {
@@ -512,7 +490,6 @@
 				*res_ptr = RESMAP_MASK(bits_wanted);
 				pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
 				pide <<= 3;	/* convert to bit address */
-				ASSERT(0 != pide);
 				break;
 			}
 		}
@@ -536,7 +513,7 @@
 		}
 		mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt;
 
-		DBG_RES("sba_search_bitmap() o %ld %p", o, res_ptr);
+		DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr);
 		while(res_ptr < res_end)
 		{ 
 			DBG_RES("    %p %lx %lx\n", res_ptr, mask, *res_ptr);
@@ -546,7 +523,6 @@
 				pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map);
 				pide <<= 3;	/* convert to bit address */
 				pide += bitshiftcnt;
-				ASSERT(0 != pide);
 				break;
 			}
 			mask >>= o;
@@ -562,11 +538,24 @@
 	}
 
 	/* wrapped ? */
-	ioc->res_hint = (res_end == res_ptr) ? (unsigned long *) ioc->res_map : res_ptr;
+	if (res_end <= res_ptr) {
+		ioc->res_hint = (unsigned long *) ioc->res_map;
+		ioc->res_bitshift = 0;
+	} else {
+		ioc->res_hint = res_ptr;
+	}
 	return (pide);
 }
 
 
+/**
+ * sba_alloc_range - find free bits and mark them in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @size: number of bytes to create a mapping for
+ *
+ * Given a size, find consecutive unmarked and then mark those bits in the
+ * resource bit map.
+ */
 static int
 sba_alloc_range(struct ioc *ioc, size_t size)
 {
@@ -577,8 +566,8 @@
 	unsigned long pide;
 
 	ASSERT(pages_needed);
-	ASSERT((pages_needed * IOVP_SIZE) < DMA_CHUNK_SIZE);
-	ASSERT(pages_needed < BITS_PER_LONG);
+	ASSERT((pages_needed * IOVP_SIZE) <= DMA_CHUNK_SIZE);
+	ASSERT(pages_needed <= BITS_PER_LONG);
 	ASSERT(0 == (size & ~IOVP_MASK));
 
 	/*
@@ -590,7 +579,7 @@
 	if (pide >= (ioc->res_size << 3)) {
 		pide = sba_search_bitmap(ioc, pages_needed);
 		if (pide >= (ioc->res_size << 3))
-			panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa);
+			panic(__FILE__ ": I/O MMU @ %lx is out of mapping resources\n", ioc->ioc_hpa);
 	}
 
 #ifdef ASSERT_PDIR_SANITY
@@ -600,8 +589,8 @@
 	}
 #endif
 
-	DBG_RES("sba_alloc_range(%x) %d -> %lx hint %x/%x\n",
-		size, pages_needed, pide,
+	DBG_RES("%s(%x) %d -> %lx hint %x/%x\n",
+		__FUNCTION__, size, pages_needed, pide,
 		(uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map),
 		ioc->res_bitshift );
 
@@ -622,9 +611,14 @@
 }
 
 
-/*
-** clear bits in the ioc's resource map
-*/
+/**
+ * sba_free_range - unmark bits in IO PDIR resource bitmap
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @iova: IO virtual address which was previously allocated.
+ * @size: number of bytes to create a mapping for
+ *
+ * clear bits in the ioc's resource map
+ */
 static SBA_INLINE void
 sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size)
 {
@@ -638,8 +632,8 @@
 	/* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */
 	unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1));
 
-	DBG_RES("sba_free_range( ,%x,%x) %x/%lx %x %p %lx\n",
-		(uint) iova, size,
+	DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n",
+		__FUNCTION__, (uint) iova, size,
 		bits_not_wanted, m, pide, res_ptr, *res_ptr);
 
 #ifdef CONFIG_PROC_FS
@@ -648,8 +642,8 @@
 
 	ASSERT(m != 0);
 	ASSERT(bits_not_wanted);
-	ASSERT((bits_not_wanted * IOVP_SIZE) < DMA_CHUNK_SIZE);
-	ASSERT(bits_not_wanted < BITS_PER_LONG);
+	ASSERT((bits_not_wanted * IOVP_SIZE) <= DMA_CHUNK_SIZE);
+	ASSERT(bits_not_wanted <= BITS_PER_LONG);
 	ASSERT((*res_ptr & m) == m); /* verify same bits are set */
 	*res_ptr &= ~m;
 }
@@ -667,31 +661,37 @@
 typedef unsigned long space_t;
 #define KERNEL_SPACE 0
 
-/*
-* SBA Mapping Routine
-*
-* Given a virtual address (vba, arg2) and space id, (sid, arg1)
-* sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
-* pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
-* shown below (MSB == bit 0):
-*
-*  0                    19                                 51   55       63
-* +-+---------------------+----------------------------------+----+--------+
-* |V|        U            |            PPN[43:12]            | U  |   VI   |
-* +-+---------------------+----------------------------------+----+--------+
-*
-*  V  == Valid Bit
-*  U  == Unused
-* PPN == Physical Page Number
-* VI  == Virtual Index (aka Coherent Index)
-*
-* The physical address fields are filled with the results of the LPA
-* instruction.  The virtual index field is filled with the results of
-* of the LCI (Load Coherence Index) instruction.  The 8 bits used for
-* the virtual index are bits 12:19 of the value returned by LCI.
-*
-* We need to pre-swap the bytes since PCX-W is Big Endian.
-*/
+/**
+ * sba_io_pdir_entry - fill in one IO PDIR entry
+ * @pdir_ptr:  pointer to IO PDIR entry
+ * @sid: process Space ID
+ * @vba: Virtual CPU address of buffer to map
+ *
+ * SBA Mapping Routine
+ *
+ * Given a virtual address (vba, arg2) and space id, (sid, arg1)
+ * sba_io_pdir_entry() loads the I/O PDIR entry pointed to by
+ * pdir_ptr (arg0). Each IO Pdir entry consists of 8 bytes as
+ * shown below (MSB == bit 0):
+ *
+ *  0                    19                                 51   55       63
+ * +-+---------------------+----------------------------------+----+--------+
+ * |V|        U            |            PPN[43:12]            | U  |   VI   |
+ * +-+---------------------+----------------------------------+----+--------+
+ *
+ *  V  == Valid Bit
+ *  U  == Unused
+ * PPN == Physical Page Number
+ * VI  == Virtual Index (aka Coherent Index)
+ *
+ * The physical address fields are filled with the results of the LPA
+ * instruction.  The virtual index field is filled with the results of
+ * of the LCI (Load Coherence Index) instruction.  The 8 bits used for
+ * the virtual index are bits 12:19 of the value returned by LCI.
+ *
+ * We need to pre-swap the bytes since PCX-W is Big Endian.
+ */
+
 
 void SBA_INLINE
 sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba)
@@ -699,9 +699,11 @@
 	u64 pa; /* physical address */
 	register unsigned ci; /* coherent index */
 
-	/* We currently only support kernel addresses */
-	ASSERT(sid == 0);
-	ASSERT(((unsigned long) vba & 0xc0000000UL) == 0xc0000000UL);
+	/* We currently only support kernel addresses.
+	 * fdc instr below will need to reload sr1 with KERNEL_SPACE
+	 * once we try to support direct DMA to user space.
+	 */
+	ASSERT(sid == KERNEL_SPACE);
 
 	pa = virt_to_phys(vba);
 	pa &= ~4095ULL;			/* clear out offset bits */
@@ -712,25 +714,41 @@
 
 	pa |= 0x8000000000000000ULL;	/* set "valid" bit */
 	*pdir_ptr = cpu_to_le64(pa);	/* swap and store into I/O Pdir */
+
+	/*
+	 * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set
+	 * (bit #61, big endian), we have to flush and sync every time
+	 * IO-PDIR is changed in Ike/Astro.
+	 */
+	if (ioc_needs_fdc) {
+		asm volatile("fdc 0(%%sr1,%0)\n\tsync" : : "r" (pdir_ptr));
+	}
 }
 
 
-/***********************************************************
- * The Ike PCOM (Purge Command Register) is to purge
- * stale entries in the IO TLB when unmapping entries.
+/**
+ * sba_mark_invalid - invalidate one or more IO PDIR entries
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @iova:  IO Virtual Address mapped earlier
+ * @byte_cnt:  number of bytes this mapping covers.
+ *
+ * Marking the IO PDIR entry(ies) as Invalid and invalidate
+ * corresponding IO TLB entry. The Ike PCOM (Purge Command Register)
+ * is to purge stale entries in the IO TLB when unmapping entries.
  *
  * The PCOM register supports purging of multiple pages, with a minium
  * of 1 page and a maximum of 2GB. Hardware requires the address be
  * aligned to the size of the range being purged. The size of the range
- * must be a power of 2.
- ***********************************************************/
+ * must be a power of 2. The "Cool perf optimization" in the
+ * allocation routine helps keep that true.
+ */
 static SBA_INLINE void
 sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt)
 {
 	u32 iovp = (u32) SBA_IOVP(ioc,iova);
 
 	/* Even though this is a big-endian machine, the entries
-	** in the iopdir are swapped. That's why we clear the byte
+	** in the iopdir are little endian. That's why we clear the byte
 	** at +7 instead of at +0.
 	*/
 	int off = PDIR_INDEX(iovp)*sizeof(u64)+7;
@@ -775,32 +793,45 @@
 		} while (byte_cnt > 0);
 	}
 
-	WRITE_REG32(iovp, ioc->ioc_hpa+IOC_PCOM);
+	WRITE_REG(iovp, ioc->ioc_hpa+IOC_PCOM);
 }
 
+/**
+ * sba_dma_supported - PCI driver can query DMA support
+ * @dev: instance of PCI owned by the driver that's asking
+ * @mask:  number of address bits this PCI device can handle
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static int
 sba_dma_supported( struct pci_dev *dev, u64 mask)
 {
 	if (dev == NULL) {
-		printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
+		printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
 		BUG();
 		return(0);
 	}
 
 	dev->dma_mask = mask;	/* save it */
 
-	/* only support PCI devices */
-	return((int) (mask >= 0xffffffff));
+	/* only support 32-bit PCI devices - no DAC support (yet) */
+	return((int) (mask == 0xffffffff));
 }
 
 
-/*
-** map_single returns a fully formed IOVA
-*/
+/**
+ * sba_map_single - map one buffer and return IOVA for DMA
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @addr:  driver buffer to map.
+ * @size:  number of bytes to map in driver buffer.
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static dma_addr_t
 sba_map_single(struct pci_dev *dev, void *addr, size_t size, int direction)
 {
-	struct ioc *ioc = &sba_list->ioc[0];  /* FIXME : see Multi-IOC below */
+	struct ioc *ioc;
 	unsigned long flags; 
 	dma_addr_t iovp;
 	dma_addr_t offset;
@@ -808,9 +839,14 @@
 	int pide;
 
 	ASSERT(size > 0);
+	ASSERT(size <= DMA_CHUNK_SIZE);
+
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
 
 	/* save offset bits */
-	offset = ((dma_addr_t) addr) & ~IOVP_MASK;
+	offset = ((dma_addr_t) (long) addr) & ~IOVP_MASK;
 
 	/* round up to nearest IOVP_SIZE */
 	size = (size + offset + ~IOVP_MASK) & IOVP_MASK;
@@ -827,7 +863,8 @@
 	pide = sba_alloc_range(ioc, size);
 	iovp = (dma_addr_t) pide << IOVP_SHIFT;
 
-	DBG_RUN("sba_map_single() 0x%p -> 0x%lx", addr, (long) iovp | offset);
+	DBG_RUN("%s() 0x%p -> 0x%lx",
+		__FUNCTION__, addr, (long) iovp | offset);
 
 	pdir_start = &(ioc->pdir_base[pide]);
 
@@ -860,72 +897,85 @@
 }
 
 
+/**
+ * sba_unmap_single - unmap one IOVA and free resources
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @iova:  IOVA of driver buffer previously mapped.
+ * @size:  number of bytes mapped in driver buffer.
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void
 sba_unmap_single(struct pci_dev *dev, dma_addr_t iova, size_t size, int direction)
 {
-#ifdef FIXME
-/* Multi-IOC (ie N-class) :  need to lookup IOC from dev
-** o If we can't know about lba PCI data structs, that eliminates ->sysdata.
-** o walking up pcidev->parent dead ends at elroy too
-** o leaves hashing dev->bus->number into some lookup.
-**   (may only work for N-class)
-** o use (struct pci_hba) and put fields in there for DMA.
-**   (ioc and per device dma_hint.)
-**
-** Last one seems the clearest and most promising.
-** sba_dma_supported() fill in those fields when the driver queries
-** the system for support.
-*/
-	struct ioc *ioc = (struct ioc *) ((struct pci_hba *) (dev->sysdata))->dma_data;
-#else
-	struct ioc *ioc = &sba_list->ioc[0];
+	struct ioc *ioc;
+#if DELAYED_RESOURCE_CNT > 0
+	struct sba_dma_pair *d;
 #endif
-	
 	unsigned long flags; 
 	dma_addr_t offset;
+
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
 	offset = iova & ~IOVP_MASK;
 
-	DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size);
+	DBG_RUN("%s() iovp 0x%lx/%x\n",
+		__FUNCTION__, (long) iova, size);
 
 	iova ^= offset;        /* clear offset bits */
 	size += offset;
 	size = ROUNDUP(size, IOVP_SIZE);
 
-	ASSERT(0 != iova);
-
 	spin_lock_irqsave(&ioc->res_lock, flags);
+
 #ifdef CONFIG_PROC_FS
 	ioc->usingle_calls++;
 	ioc->usingle_pages += size >> IOVP_SHIFT;
 #endif
-#ifdef DELAYED_RESOURCE_CNT
-	if (ioc->saved_cnt < DELAYED_RESOURCE_CNT) {
-		ioc->saved_iova[ioc->saved_cnt] = iova;
-		ioc->saved_size[ioc->saved_cnt] = size;
-		ioc_saved_cnt++;
-	} else {
-		do {
-#endif
-			sba_mark_invalid(ioc, iova, size);
-			sba_free_range(ioc, iova, size);
 
-#ifdef DELAYED_RESOURCE_CNT
-			ioc->saved_cnt--;
-			iova = ioc->saved_iova[ioc->saved_cnt];
-			size = ioc->saved_size[ioc->saved_cnt];
-		} while (ioc->saved_cnt)
-
-		/* flush purges */
-		(void) (volatile) READ_REG32(ioc->ioc_hpa+IOC_PCOM);
+#if DELAYED_RESOURCE_CNT > 0
+	d = &(ioc->saved[ioc->saved_cnt]);
+	d->iova = iova;
+	d->size = size;
+	if (++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT) {
+		int cnt = ioc->saved_cnt;
+		while (cnt--) {
+			sba_mark_invalid(ioc, d->iova, d->size);
+			sba_free_range(ioc, d->iova, d->size);
+			d--;
+		}
+		ioc->saved_cnt = 0;
+		READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
 	}
-#else
-	/* flush purges */
-	READ_REG32(ioc->ioc_hpa+IOC_PCOM);
-#endif
+#else /* DELAYED_RESOURCE_CNT == 0 */
+	sba_mark_invalid(ioc, iova, size);
+	sba_free_range(ioc, iova, size);
+	READ_REG(ioc->ioc_hpa+IOC_PCOM);	/* flush purges */
+#endif /* DELAYED_RESOURCE_CNT == 0 */
 	spin_unlock_irqrestore(&ioc->res_lock, flags);
+
+	/* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support.
+	** For Astro based systems this isn't a big deal WRT performance.
+	** As long as 2.4 kernels copyin/copyout data from/to userspace,
+	** we don't need the syncdma. The issue here is I/O MMU cachelines
+	** are *not* coherent in all cases.  May be hwrev dependent.
+	** Need to investigate more.
+	asm volatile("syncdma");	
+	*/
 }
 
 
+/**
+ * sba_alloc_consistent - allocate/map shared mem for DMA
+ * @hwdev: instance of PCI owned by the driver that's asking.
+ * @size:  number of bytes mapped in driver buffer.
+ * @dma_handle:  IOVA of new buffer.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void *
 sba_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
 {
@@ -948,6 +998,15 @@
 }
 
 
+/**
+ * sba_free_consistent - free/unmap shared mem for DMA
+ * @hwdev: instance of PCI owned by the driver that's asking.
+ * @size:  number of bytes mapped in driver buffer.
+ * @vaddr:  virtual address IOVA of "consistent" buffer.
+ * @dma_handler:  IO virtual address of "consistent" buffer.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void
 sba_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
 {
@@ -955,27 +1014,6 @@
 	free_pages((unsigned long) vaddr, get_order(size));
 }
 
-/*
-** Two address ranges are "virtually contiguous" iff:
-** 1) end of prev == start of next, or...	 append case
-** 3) end of next == start of prev		 prepend case
-**
-** and they are DMA contiguous *iff*:
-** 2) end of prev and start of next are both on a page boundry
-**
-** (shift left is a quick trick to mask off upper bits)
-*/
-#define DMA_CONTIG(__X, __Y) \
-	(((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
-
-/*
-** Assumption is two transactions are mutually exclusive.
-** ie both go to different parts of memory.
-** If both are true, then both transaction are on the same page.
-*/
-#define DMA_SAME_PAGE(s1,e1,s2,e2) \
-	( ((((s1) ^ (s2)) >> PAGE_SHIFT) == 0) \
-		&& ((((e1) ^ (e2)) >> PAGE_SHIFT) == 0) )
 
 /*
 ** Since 0 is a valid pdir_base index value, can't use that
@@ -988,6 +1026,17 @@
 int dump_run_sg = 0;
 #endif
 
+
+/**
+ * sba_fill_pdir - write allocated SG entries into IO PDIR
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg:  list of IOVA/size pairs
+ * @nents: number of entries in startsg list
+ *
+ * Take preprocessed SG list and write corresponding entries
+ * in the IO PDIR.
+ */
+
 static SBA_INLINE int
 sba_fill_pdir(
 	struct ioc *ioc,
@@ -1006,16 +1055,16 @@
 
 #ifdef DEBUG_LARGE_SG_ENTRIES
 		if (dump_run_sg)
-			printk(" %d : %08lx/%05x %p/%05x\n",
+			printk(KERN_DEBUG " %2d : %08lx/%05x %p/%05x\n",
 				nents,
 				(unsigned long) sg_dma_address(startsg), cnt,
-				startsg->address, startsg->length
+				sg_virt_address(startsg), startsg->length
 		);
 #else
 		DBG_RUN_SG(" %d : %08lx/%05x %p/%05x\n",
 				nents,
 				(unsigned long) sg_dma_address(startsg), cnt,
-				startsg->address, startsg->length
+				sg_virt_addr(startsg), startsg->length
 		);
 #endif
 		/*
@@ -1024,11 +1073,10 @@
 		if (sg_dma_address(startsg) & PIDE_FLAG) {
 			u32 pide = sg_dma_address(startsg) & ~PIDE_FLAG;
 			dma_offset = (unsigned long) pide & ~IOVP_MASK;
-			pide >>= IOVP_SHIFT;
-			pdirp = &(ioc->pdir_base[pide]);
 			sg_dma_address(startsg) = 0;
-			++dma_sg;
-			sg_dma_address(dma_sg) = (pide << IOVP_SHIFT) + dma_offset;
+			dma_sg++;
+			sg_dma_address(dma_sg) = pide;
+			pdirp = &(ioc->pdir_base[pide >> IOVP_SHIFT]);
 			n_mappings++;
 		}
 
@@ -1036,9 +1084,12 @@
 		** Look for a VCONTIG chunk
 		*/
 		if (cnt) {
-			unsigned long vaddr = (unsigned long) startsg->address;
+			unsigned long vaddr = (unsigned long) sg_virt_addr(startsg);
 			ASSERT(pdirp);
 
+			/* Since multiple Vcontig blocks could make up
+			** one DMA stream, *add* cnt to dma_len.
+			*/
 			sg_dma_len(dma_sg) += cnt;
 			cnt += dma_offset;
 			dma_offset=0;	/* only want offset on first chunk */
@@ -1062,133 +1113,142 @@
 }
 
 
-
 /*
-** First pass is to walk the SG list and determine where the breaks are
-** in the DMA stream. Allocates PDIR entries but does not fill them.
-** Returns the number of DMA chunks.
+** Two address ranges are DMA contiguous *iff* "end of prev" and
+** "start of next" are both on a page boundry.
 **
-** Doing the fill seperate from the coalescing/allocation keeps the
-** code simpler. Future enhancement could make one pass through
-** the sglist do both.
+** (shift left is a quick trick to mask off upper bits)
 */
+#define DMA_CONTIG(__X, __Y) \
+	(((((unsigned long) __X) | ((unsigned long) __Y)) << (BITS_PER_LONG - PAGE_SHIFT)) == 0UL)
+
+
+/**
+ * sba_coalesce_chunks - preprocess the SG list
+ * @ioc: IO MMU structure which owns the pdir we are interested in.
+ * @startsg:  list of IOVA/size pairs
+ * @nents: number of entries in startsg list
+ *
+ * First pass is to walk the SG list and determine where the breaks are
+ * in the DMA stream. Allocates PDIR entries but does not fill them.
+ * Returns the number of DMA chunks.
+ *
+ * Doing the fill seperate from the coalescing/allocation keeps the
+ * code simpler. Future enhancement could make one pass through
+ * the sglist do both.
+ */
 static SBA_INLINE int
 sba_coalesce_chunks( struct ioc *ioc,
 	struct scatterlist *startsg,
 	int nents)
 {
+	struct scatterlist *vcontig_sg;    /* VCONTIG chunk head */
+	unsigned long vcontig_len;         /* len of VCONTIG chunk */
+	unsigned long vcontig_end;
+	struct scatterlist *dma_sg;        /* next DMA stream head */
+	unsigned long dma_offset, dma_len; /* start/len of DMA stream */
 	int n_mappings = 0;
 
 	while (nents > 0) {
-		struct scatterlist *dma_sg;  /* next DMA stream head */
-		unsigned long dma_offset, dma_len;   /* start/len of DMA stream */
-		struct scatterlist *chunksg; /* virtually contig chunk head */
-		unsigned long chunk_addr, chunk_len; /* start/len of VCONTIG chunk */
+		unsigned long vaddr = (unsigned long) sg_virt_addr(startsg); 
 
 		/*
 		** Prepare for first/next DMA stream
 		*/
-		dma_sg = chunksg = startsg;
-		dma_len = chunk_len  = startsg->length;
-		chunk_addr = (unsigned long) startsg->address;
-		dma_offset = 0UL;
+		dma_sg = vcontig_sg = startsg;
+		dma_len = vcontig_len = vcontig_end = startsg->length;
+		vcontig_end +=  vaddr;
+		dma_offset = vaddr & ~IOVP_MASK;
+
+		/* PARANOID: clear entries */
+		sg_dma_address(startsg) = 0;
+		sg_dma_len(startsg) = 0;
 
 		/*
 		** This loop terminates one iteration "early" since
 		** it's always looking one "ahead".
 		*/
 		while (--nents > 0) {
-			/* ptr to coalesce prev and next */
-			struct scatterlist *prev_sg = startsg;
-			unsigned long prev_end = (unsigned long) prev_sg->address + prev_sg->length;
-			unsigned long current_end;
+			unsigned long vaddr;	/* tmp */
+
+			startsg++;
 
 			/* PARANOID: clear entries */
 			sg_dma_address(startsg) = 0;
 			sg_dma_len(startsg) = 0;
 
-			/* Now start looking ahead */
-			startsg++;
-			current_end  = (unsigned long) startsg->address + startsg->length;
+			/* catch brokenness in SCSI layer */
+			ASSERT(startsg->length <= DMA_CHUNK_SIZE);
 
 			/*
-			** First look for virtually contiguous blocks.
-			** PARISC needs this since it's cache is virtually
-			** indexed and we need the associated virtual
-			** address for each I/O address we map.
-			**
-			** 1) can we *prepend* the next transaction?
+			** First make sure current dma stream won't
+			** exceed DMA_CHUNK_SIZE if we coalesce the
+			** next entry.
 			*/
-			if (current_end == (unsigned long) prev_sg->address)
-			{
-				/* prepend : get new offset */
-				chunksg = startsg;
-				chunk_addr = (unsigned long) prev_sg->address;
-				chunk_len += startsg->length;
-				dma_len   += startsg->length;
-				continue;
-			}
+			if (((dma_len + dma_offset + startsg->length + ~IOVP_MASK) & IOVP_MASK) > DMA_CHUNK_SIZE)
+				break;
 
 			/*
-			** 2) or append the next transaction?
+			** Then look for virtually contiguous blocks.
+			** PARISC needs to associate a virtual address
+			** with each IO address mapped. The CPU cache is
+			** virtually tagged and the IOMMU uses part
+			** of the virtual address to participate in
+			** CPU cache coherency.
+			**
+			** append the next transaction?
 			*/
-			if  (prev_end == (unsigned long) startsg->address)
+			vaddr = (unsigned long) sg_virt_addr(startsg);
+			if  (vcontig_end == vaddr)
 			{
-				chunk_len += startsg->length;
-				dma_len   += startsg->length;
+				vcontig_len += startsg->length;
+				vcontig_end += startsg->length;
+				dma_len     += startsg->length;
 				continue;
 			}
 
 #ifdef DEBUG_LARGE_SG_ENTRIES
-			dump_run_sg = (chunk_len > IOVP_SIZE);
+			dump_run_sg = (vcontig_len > IOVP_SIZE);
 #endif
+
 			/*
 			** Not virtually contigous.
 			** Terminate prev chunk.
 			** Start a new chunk.
 			**
-			** Once we start a new VCONTIG chunk, the offset
+			** Once we start a new VCONTIG chunk, dma_offset
 			** can't change. And we need the offset from the first
 			** chunk - not the last one. Ergo Successive chunks
 			** must start on page boundaries and dove tail
 			** with it's predecessor.
 			*/
-			sg_dma_len(prev_sg) = chunk_len;
+			sg_dma_len(vcontig_sg) = vcontig_len;
 
-			chunk_len = startsg->length;
-			dma_offset |= (chunk_addr & ~IOVP_MASK);
-			ASSERT((0 == (chunk_addr & ~IOVP_MASK)) ||
-				(dma_offset == (chunk_addr & ~IOVP_MASK)));
+			vcontig_sg = startsg;
+			vcontig_len = startsg->length;
 
-#if 0
 			/*
-			** 4) do the chunks end/start on page boundaries?
-			**  Easier than 3 since no offsets are involved.
+			** 3) do the entries end/start on page boundaries?
+			**    Don't update vcontig_end until we've checked.
 			*/
-			if (DMA_CONTIG(prev_end, startsg->address))
+			if (DMA_CONTIG(vcontig_end, vaddr))
 			{
-				/*
-				** Yes.
-				** Reset chunk ptr.
-				*/
-				chunksg = startsg;
-				chunk_addr = (unsigned long) startsg->address;
-
+				vcontig_end = vcontig_len + vaddr;
+				dma_len += vcontig_len;
 				continue;
-			} else
-#endif
-			{
+			} else {
 				break;
 			}
 		}
 
 		/*
 		** End of DMA Stream
-		** Terminate chunk.
+		** Terminate last VCONTIG block.
 		** Allocate space for DMA stream.
 		*/
-		sg_dma_len(startsg) = chunk_len;
+		sg_dma_len(vcontig_sg) = vcontig_len;
 		dma_len = (dma_len + dma_offset + ~IOVP_MASK) & IOVP_MASK;
+		ASSERT(dma_len <= DMA_CHUNK_SIZE);
 		sg_dma_address(dma_sg) =
 			PIDE_FLAG 
 			| (sba_alloc_range(ioc, dma_len) << IOVP_SHIFT)
@@ -1200,24 +1260,34 @@
 }
 
 
-/*
-** And this algorithm still generally only ends up coalescing entries
-** that happens to be on the same page due to how sglists are assembled.
-*/
+/**
+ * sba_map_sg - map Scatter/Gather list
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @sglist:  array of buffer/length pairs
+ * @nents:  number of entries in list
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static int
 sba_map_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
 {
-	struct ioc *ioc = &sba_list->ioc[0];  /* FIXME : see Multi-IOC below */
+	struct ioc *ioc;
 	int coalesced, filled = 0;
 	unsigned long flags;
 
 	DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents);
 
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
+
 	/* Fast path single entry scatterlists. */
 	if (nents == 1) {
-		sg_dma_address(sglist)= sba_map_single(dev, sglist->address,
+		sg_dma_address(sglist) = sba_map_single(dev,
+						sg_virt_addr(sglist),
 						sglist->length, direction);
-		sg_dma_len(sglist)= sglist->length;
+		sg_dma_len(sglist)     = sglist->length;
 		return 1;
 	}
 
@@ -1272,16 +1342,29 @@
 }
 
 
+/**
+ * sba_unmap_sg - unmap Scatter/Gather list
+ * @dev: instance of PCI owned by the driver that's asking.
+ * @sglist:  array of buffer/length pairs
+ * @nents:  number of entries in list
+ * @direction:  R/W or both.
+ *
+ * See Documentation/DMA-mapping.txt
+ */
 static void 
 sba_unmap_sg(struct pci_dev *dev, struct scatterlist *sglist, int nents, int direction)
 {
-	struct ioc *ioc = &sba_list->ioc[0];  /* FIXME : see Multi-IOC below */
+	struct ioc *ioc;
 #ifdef ASSERT_PDIR_SANITY
 	unsigned long flags;
 #endif
 
 	DBG_RUN_SG("%s() START %d entries,  %p,%x\n",
-		__FUNCTION__, nents, sglist->address, sglist->length);
+		__FUNCTION__, nents, sg_virt_addr(sglist), sglist->length);
+
+	ASSERT(dev->sysdata);
+	ioc = GET_IOC(dev);
+	ASSERT(ioc);
 
 #ifdef CONFIG_PROC_FS
 	ioc->usg_calls++;
@@ -1295,10 +1378,11 @@
 
 	while (sg_dma_len(sglist) && nents--) {
 
+		sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
 #ifdef CONFIG_PROC_FS
-	ioc->usg_pages += sg_dma_len(sglist) >> PAGE_SHIFT;
+		ioc->usg_pages += ((sg_dma_address(sglist) & ~IOVP_MASK) + sg_dma_len(sglist) + IOVP_SIZE - 1) >> PAGE_SHIFT;
+		ioc->usingle_calls--;	/* kluge since call is unmap_sg() */
 #endif
-		sba_unmap_single(dev, sg_dma_address(sglist), sg_dma_len(sglist), direction);
 		++sglist;
 	}
 
@@ -1359,21 +1443,117 @@
 *   Initialization and claim
 *
 ***************************************************************/
+#define PIRANHA_ADDR_MASK	0x00160000UL /* bit 17,18,20 */
+#define PIRANHA_ADDR_VAL	0x00060000UL /* bit 17,18 on */
+static void *
+sba_alloc_pdir(unsigned int pdir_size)
+{
+        unsigned long pdir_base;
+	unsigned long pdir_order = get_order(pdir_size);
+
+	pdir_base = __get_free_pages(GFP_KERNEL, pdir_order);
+	if (NULL == (void *) pdir_base)
+		panic("sba_ioc_init() could not allocate I/O Page Table\n");
+
+	/* If this is not PA8700 (PCX-W2)
+	**	OR newer than ver 2.2
+	**	OR in a system that doesn't need VINDEX bits from SBA,
+	**
+	** then we aren't exposed to the HW bug.
+	*/
+	if ( ((boot_cpu_data.pdc.cpuid >> 5) & 0x7f) != 0x13
+			|| (boot_cpu_data.pdc.versions > 0x202)
+			|| (boot_cpu_data.pdc.capabilities & 0x08L) )
+		return (void *) pdir_base;
+
+	/*
+	 * PA8700 (PCX-W2, aka piranha) silent data corruption fix
+	 *
+	 * An interaction between PA8700 CPU (Ver 2.2 or older) and
+	 * Ike/Astro can cause silent data corruption. This is only
+	 * a problem if the I/O PDIR is located in memory such that
+	 * (little-endian)  bits 17 and 18 are on and bit 20 is off.
+	 *
+	 * Since the max IO Pdir size is 2MB, by cleverly allocating the
+	 * right physical address, we can either avoid (IOPDIR <= 1MB)
+	 * or minimize (2MB IO Pdir) the problem if we restrict the
+	 * IO Pdir to a maximum size of 2MB-128K (1902K).
+	 *
+	 * Because we always allocate 2^N sized IO pdirs, either of the
+	 * "bad" regions will be the last 128K if at all. That's easy
+	 * to test for.
+	 * 
+	 */
+	if (pdir_order <= (19-12)) {
+		if (((virt_to_phys(pdir_base)+pdir_size-1) & PIRANHA_ADDR_MASK) == PIRANHA_ADDR_VAL) {
+			/* allocate a new one on 512k alignment */
+			unsigned long new_pdir = __get_free_pages(GFP_KERNEL, (19-12));
+			/* release original */
+			free_pages(pdir_base, pdir_order);
+
+			pdir_base = new_pdir;
+
+			/* release excess */
+			while (pdir_order < (19-12)) {
+				new_pdir += pdir_size;
+				free_pages(new_pdir, pdir_order);
+				pdir_order +=1;
+				pdir_size <<=1;
+			}
+		}
+	} else {
+		/*
+		** 1MB or 2MB Pdir
+		** Needs to be aligned on an "odd" 1MB boundary.
+		*/
+		unsigned long new_pdir = __get_free_pages(GFP_KERNEL, pdir_order+1); /* 2 or 4MB */
+
+		/* release original */
+		free_pages( pdir_base, pdir_order);
+
+		/* release first 1MB */
+		free_pages(new_pdir, 20-12);
+
+		pdir_base = new_pdir + 1024*1024;
+
+		if (pdir_order > (20-12)) {
+			/*
+			** 2MB Pdir.
+			**
+			** Flag tells init_bitmap() to mark bad 128k as used
+			** and to reduce the size by 128k.
+			*/
+			piranha_bad_128k = 1;
+
+			new_pdir += 3*1024*1024;
+			/* release last 1MB */
+			free_pages(new_pdir, 20-12);
+
+			/* release unusable 128KB */
+			free_pages(new_pdir - 128*1024 , 17-12);
+
+			pdir_size -= 128*1024;
+		}
+	}
+
+	memset((void *) pdir_base, 0, pdir_size);
+	return (void *) pdir_base;
+}
 
 
 static void
-sba_ioc_init(struct ioc *ioc)
+sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
-	extern unsigned long mem_max;          /* arch.../setup.c */
-	extern void lba_init_iregs(void *, u32, u32);   /* arch.../lba_pci.c */
+	/* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
+	extern void lba_set_iregs(struct parisc_device *, u32, u32);
 
 	u32 iova_space_size, iova_space_mask;
-	void * pdir_base;
 	int pdir_size, iov_order;
+	unsigned long physmem;
+	struct parisc_device *lba;
 
 	/*
 	** Determine IOVA Space size from memory size.
-	** Using "mem_max" is a kluge.
 	**
 	** Ideally, PCI drivers would register the maximum number
 	** of DMA they can have outstanding for each device they
@@ -1385,20 +1565,24 @@
 	** While we have 32-bits "IOVA" space, top two 2 bits are used
 	** for DMA hints - ergo only 30 bits max.
 	*/
+
+	physmem = num_physpages << PAGE_SHIFT;
+	iova_space_size = (u32) (physmem/(sba_mem_ratio*global_ioc_cnt));
+
 	/* limit IOVA space size to 1MB-1GB */
-	if (mem_max < (sba_mem_ratio*1024*1024)) {
+	if (iova_space_size < 1024*1024) {
 		iova_space_size = 1024*1024;
+	}
 #ifdef __LP64__
-	} else if (mem_max > (sba_mem_ratio*512*1024*1024)) {
+	else if (iova_space_size > 512*1024*1024) {
 		iova_space_size = 512*1024*1024;
-#endif
-	} else {
-		iova_space_size = (u32) (mem_max/sba_mem_ratio);
 	}
+#endif
 
 	/*
 	** iova space must be log2() in size.
 	** thus, pdir/res_map will also be log2().
+	** PIRANHA BUG: Exception is when IO Pdir is 2MB (gets reduced)
 	*/
 	iov_order = get_order(iova_space_size >> (IOVP_SHIFT-PAGE_SHIFT));
 	ASSERT(iov_order <= (30 - IOVP_SHIFT));   /* iova_space_size <= 1GB */
@@ -1407,35 +1591,27 @@
 
 	ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64);
 
-	ASSERT(pdir_size < 4*1024*1024);   /* max pdir size < 4MB */
+	ASSERT(pdir_size < 4*1024*1024);   /* max pdir size == 2MB */
 
 	/* Verify it's a power of two */
 	ASSERT((1 << get_order(pdir_size)) == (pdir_size >> PAGE_SHIFT));
 
-	DBG_INIT("%s() hpa 0x%p mem %dMBIOV %dMB (%d bits) PDIR size 0x%0x",
-		__FUNCTION__, ioc->ioc_hpa, (int) (mem_max>>20),
+	DBG_INIT("%s() hpa 0x%lx mem %dMB IOV %dMB (%d bits) PDIR size 0x%0x\n",
+		__FUNCTION__, ioc->ioc_hpa, (int) (physmem>>20),
 		iova_space_size>>20, iov_order + PAGE_SHIFT, pdir_size);
 
 	/* FIXME : DMA HINTs not used */
 	ioc->hint_shift_pdir = iov_order + PAGE_SHIFT;
 	ioc->hint_mask_pdir = ~(0x3 << (iov_order + PAGE_SHIFT));
 
-	ioc->pdir_base =
-	pdir_base = (void *) __get_free_pages(GFP_KERNEL, get_order(pdir_size));
-	if (NULL == pdir_base)
-	{
-		panic(__FILE__ ":%s() could not allocate I/O Page Table\n", __FUNCTION__);
-	}
-	memset(pdir_base, 0, pdir_size);
+	ioc->pdir_base = sba_alloc_pdir(pdir_size);
 
-	DBG_INIT("sba_ioc_init() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
-		pdir_base, pdir_size,
+	DBG_INIT("%s() pdir %p size %x hint_shift_pdir %x hint_mask_pdir %lx\n",
+		__FUNCTION__, ioc->pdir_base, pdir_size,
 		ioc->hint_shift_pdir, ioc->hint_mask_pdir);
 
-	ASSERT((((unsigned long) pdir_base) & PAGE_MASK) == (unsigned long) pdir_base);
-	WRITE_REG64(virt_to_phys(pdir_base), (u64 *)(ioc->ioc_hpa+IOC_PDIR_BASE));
-
-	DBG_INIT(" base %p\n", pdir_base);
+	ASSERT((((unsigned long) ioc->pdir_base) & PAGE_MASK) == (unsigned long) ioc->pdir_base);
+	WRITE_REG64(virt_to_phys(ioc->pdir_base), ioc->ioc_hpa + IOC_PDIR_BASE);
 
 	/* build IMASK for IOC and Elroy */
 	iova_space_mask =  0xffffffff;
@@ -1448,8 +1624,8 @@
 	ioc->ibase = IOC_IOVA_SPACE_BASE | 1;	/* bit 0 == enable bit */
 	ioc->imask = iova_space_mask;	/* save it */
 
-	DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", __FUNCTION__,
-		ioc->ibase, ioc->imask);
+	DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n",
+		__FUNCTION__, ioc->ibase, ioc->imask);
 
 	/*
 	** FIXME: Hint registers are programmed with default hint
@@ -1460,22 +1636,26 @@
 	/*
 	** setup Elroy IBASE/IMASK registers as well.
 	*/
-	lba_init_iregs(ioc->ioc_hpa, ioc->ibase, ioc->imask);
+	for (lba = sba->child; lba; lba = lba->sibling) {
+		int rope_num = (lba->hpa >> 13) & 0xf;
+		if (rope_num >> 3 == ioc_num)
+			lba_set_iregs(lba, ioc->ibase, ioc->imask);
+	}
 
 	/*
 	** Program the IOC's ibase and enable IOVA translation
 	*/
-	WRITE_REG32(ioc->ibase, ioc->ioc_hpa+IOC_IBASE);
-	WRITE_REG32(ioc->imask, ioc->ioc_hpa+IOC_IMASK);
+	WRITE_REG(ioc->ibase, ioc->ioc_hpa+IOC_IBASE);
+	WRITE_REG(ioc->imask, ioc->ioc_hpa+IOC_IMASK);
 
 	/* Set I/O PDIR Page size to 4K */
-	WRITE_REG32(0, ioc->ioc_hpa+IOC_TCNFG);
+	WRITE_REG(0, ioc->ioc_hpa+IOC_TCNFG);
 
 	/*
 	** Clear I/O TLB of any possible entries.
-	** (Yes. This is a it paranoid...but so what)
+	** (Yes. This is a bit paranoid...but so what)
 	*/
-	WRITE_REG32(0 | 31, ioc->ioc_hpa+IOC_PCOM);
+	WRITE_REG(0 | 31, ioc->ioc_hpa+IOC_PCOM);
 
 	DBG_INIT("%s() DONE\n", __FUNCTION__);
 }
@@ -1498,23 +1678,24 @@
 { 
 	int i;
 	int num_ioc;
-	u32 ioc_ctl;
+	u64 ioc_ctl;
+
+	ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL);
+	DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->",
+		__FUNCTION__, sba_dev->sba_hpa, ioc_ctl);
+	ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE);
+	ioc_ctl |= IOC_CTRL_TC;	/* Astro: firmware enables this */
 
-	ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL);
-	DBG_INIT("%s() hpa 0x%p ioc_ctl 0x%x ->", __FUNCTION__, sba_dev->sba_hpa, ioc_ctl );
-	ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC);
-	ASSERT(ioc_ctl & IOC_CTRL_TE);	/* astro: firmware enables this */
-
-	WRITE_REG32(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
-
-#ifdef SBA_DEBUG_INIT
-	ioc_ctl = READ_REG32(sba_dev->sba_hpa+IOC_CTRL);
-	DBG_INIT(" 0x%x\n", ioc_ctl );
+	WRITE_REG(ioc_ctl, sba_dev->sba_hpa+IOC_CTRL);
+
+#ifdef DEBUG_SBA_INIT
+	ioc_ctl = READ_REG64(sba_dev->sba_hpa+IOC_CTRL);
+	DBG_INIT(" 0x%Lx\n", ioc_ctl);
 #endif
 
 	if (IS_ASTRO(sba_dev->iodc)) {
 		/* PAT_PDC (L-class) also reports the same goofy base */
-		sba_dev->ioc[0].ioc_hpa = (char *) ASTRO_IOC_OFFSET;
+		sba_dev->ioc[0].ioc_hpa = ASTRO_IOC_OFFSET;
 		num_ioc = 1;
 	} else {
 		sba_dev->ioc[0].ioc_hpa = sba_dev->ioc[1].ioc_hpa = 0;
@@ -1522,26 +1703,25 @@
 	}
 
 	sba_dev->num_ioc = num_ioc;
-	for( i = 0; i < num_ioc; i++)
-	{
-		(unsigned long) sba_dev->ioc[i].ioc_hpa += (unsigned long) sba_dev->sba_hpa + IKE_IOC_OFFSET(i);
+	for (i = 0; i < num_ioc; i++) {
+		sba_dev->ioc[i].ioc_hpa += sba_dev->sba_hpa + IKE_IOC_OFFSET(i);
 
 		/*
 		** Make sure the box crashes if we get any errors on a rope.
 		*/
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
-		WRITE_REG32(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE0_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE1_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE2_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE3_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE4_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE5_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE6_CTL);
+		WRITE_REG(HF_ENABLE, sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
 
 		/* flush out the writes */
-		READ_REG32(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
+		READ_REG(sba_dev->ioc[i].ioc_hpa + ROPE7_CTL);
 
-		sba_ioc_init(&(sba_dev->ioc[i]));
+		sba_ioc_init(sba_dev->dev, &(sba_dev->ioc[i]), i);
 	}
 }
 
@@ -1555,11 +1735,10 @@
 	*/
 	sba_dev->next = sba_list;
 	sba_list = sba_dev;
-	sba_count++;
 
 	for(i=0; i< sba_dev->num_ioc; i++) {
 		int res_size;
-#ifdef CONFIG_DMB_TRAP
+#ifdef DEBUG_DMB_TRAP
 		extern void iterate_pages(unsigned long , unsigned long ,
 					  void (*)(pte_t * , unsigned long),
 					  unsigned long );
@@ -1567,13 +1746,20 @@
 #endif
 		/* resource map size dictated by pdir_size */
 		res_size = sba_dev->ioc[i].pdir_size/sizeof(u64); /* entries */
+
+		/* Second part of PIRANHA BUG */
+		if (piranha_bad_128k) {
+			res_size -= (128*1024)/sizeof(u64);
+		}
+
 		res_size >>= 3;  /* convert bit count to byte count */
-		DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, res_size);
+		DBG_INIT("%s() res_size 0x%x\n",
+			__FUNCTION__, res_size);
 
 		sba_dev->ioc[i].res_size = res_size;
 		sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size));
 
-#ifdef CONFIG_DMB_TRAP
+#ifdef DEBUG_DMB_TRAP
 		iterate_pages( sba_dev->ioc[i].res_map, res_size,
 				set_data_memory_break, 0);
 #endif
@@ -1594,39 +1780,66 @@
 		sba_dev->ioc[i].pdir_base[0] = 0xeeffc0addbba0080ULL;
 #endif
 
-#ifdef CONFIG_DMB_TRAP
+		/* Third (and last) part of PIRANHA BUG */
+		if (piranha_bad_128k) {
+			/* region from +1408K to +1536 is un-usable. */
+
+			int idx_start = (1408*1024/sizeof(u64)) >> 3;
+			int idx_end   = (1536*1024/sizeof(u64)) >> 3;
+			long *p_start = (long *) &(sba_dev->ioc[i].res_map[idx_start]);
+			long *p_end   = (long *) &(sba_dev->ioc[i].res_map[idx_end]);
+
+			/* mark that part of the io pdir busy */
+			while (p_start < p_end)
+				*p_start++ = -1;
+				
+		}
+
+#ifdef DEBUG_DMB_TRAP
 		iterate_pages( sba_dev->ioc[i].res_map, res_size,
 				set_data_memory_break, 0);
 		iterate_pages( sba_dev->ioc[i].pdir_base, sba_dev->ioc[i].pdir_size,
 				set_data_memory_break, 0);
 #endif
 
-		DBG_INIT("sba_common_init() %d res_map %x %p\n",
-					i, res_size, sba_dev->ioc[i].res_map);
+		DBG_INIT("%s() %d res_map %x %p\n",
+			__FUNCTION__, i, res_size, sba_dev->ioc[i].res_map);
 	}
 
 	sba_dev->sba_lock = SPIN_LOCK_UNLOCKED;
+	ioc_needs_fdc = boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC;
+
+#ifdef DEBUG_SBA_INIT
+	/*
+	 * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit set
+	 * (bit #61, big endian), we have to flush and sync every time
+	 * IO-PDIR is changed in Ike/Astro.
+	 */
+	if (boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC) {
+		printk(KERN_INFO MODULE_NAME " FDC/SYNC required.\n");
+	} else {
+		printk(KERN_INFO MODULE_NAME " IOC has cache coherent PDIR.\n");
+	}
+#endif
 }
 
 #ifdef CONFIG_PROC_FS
 static int sba_proc_info(char *buf, char **start, off_t offset, int len)
 {
 	struct sba_device *sba_dev = sba_list;
-/* FIXME: Multi-IOC support broken! */
-	struct ioc *ioc = &sba_dev->ioc[0];
+	struct ioc *ioc = &sba_dev->ioc[0];	/* FIXME: Multi-IOC support! */
 	int total_pages = (int) (ioc->res_size << 3); /* 8 bits per byte */
 	unsigned long i = 0, avg = 0, min, max;
 
 	sprintf(buf, "%s rev %d.%d\n",
-		parisc_getHWdescription(sba_dev->iodc->hw_type,
-			sba_dev->iodc->hversion, sba_dev->iodc->sversion),
+		sba_dev->name,
 		(sba_dev->hw_rev & 0x7) + 1,
 		(sba_dev->hw_rev & 0x18) >> 3
 		);
 	sprintf(buf, "%sIO PDIR size    : %d bytes (%d entries)\n",
 		buf,
-		((ioc->res_size << 3) * sizeof(u64)), /* 8 bits per byte */
-		total_pages);                  /* 8 bits per byte */
+		(int) ((ioc->res_size << 3) * sizeof(u64)), /* 8 bits/byte */
+		total_pages);
 
 	sprintf(buf, "%sIO PDIR entries : %ld free  %ld used (%d%%)\n", buf,
 		total_pages - ioc->used_pages, ioc->used_pages,
@@ -1645,46 +1858,72 @@
 	sprintf(buf, "%s  Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n",
 		buf, min, avg, max);
 
-	sprintf(buf, "%spci_map_single(): %8ld calls  %8ld pages (avg %d/1000)\n",
+	sprintf(buf, "%spci_map_single(): %12ld calls  %12ld pages (avg %d/1000)\n",
 		buf, ioc->msingle_calls, ioc->msingle_pages,
 		(int) ((ioc->msingle_pages * 1000)/ioc->msingle_calls));
 
 	/* KLUGE - unmap_sg calls unmap_single for each mapped page */
-	min = ioc->usingle_calls - ioc->usg_calls;
+	min = ioc->usingle_calls;
 	max = ioc->usingle_pages - ioc->usg_pages;
-	sprintf(buf, "%spci_unmap_single: %8ld calls  %8ld pages (avg %d/1000)\n",
+	sprintf(buf, "%spci_unmap_single: %12ld calls  %12ld pages (avg %d/1000)\n",
 		buf, min, max,
 		(int) ((max * 1000)/min));
 
-	sprintf(buf, "%spci_map_sg()    : %8ld calls  %8ld pages (avg %d/1000)\n",
+	sprintf(buf, "%spci_map_sg()    : %12ld calls  %12ld pages (avg %d/1000)\n",
 		buf, ioc->msg_calls, ioc->msg_pages,
 		(int) ((ioc->msg_pages * 1000)/ioc->msg_calls));
 
-	sprintf(buf, "%spci_unmap_sg()  : %8ld calls  %8ld pages (avg %d/1000)\n",
+	sprintf(buf, "%spci_unmap_sg()  : %12ld calls  %12ld pages (avg %d/1000)\n",
 		buf, ioc->usg_calls, ioc->usg_pages,
 		(int) ((ioc->usg_pages * 1000)/ioc->usg_calls));
 
 	return strlen(buf);
 }
 
+#if 0
+/* XXX too much output - exceeds 4k limit and needs to be re-written */
 static int
 sba_resource_map(char *buf, char **start, off_t offset, int len)
 {
 	struct sba_device *sba_dev = sba_list;
-	struct ioc *ioc = &sba_dev->ioc[0];
-	unsigned long *res_ptr = (unsigned long *)ioc->res_map;
+	struct ioc *ioc = &sba_dev->ioc[0];	/* FIXME: Mutli-IOC suppoer! */
+	unsigned int *res_ptr = (unsigned int *)ioc->res_map;
 	int i;
 
-	for(i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) {
+	buf[0] = '\0';
+	for(i = 0; i < (ioc->res_size / sizeof(unsigned int)); ++i, ++res_ptr) {
 		if ((i & 7) == 0)
 		    strcat(buf,"\n   ");
-		sprintf(buf, "%s %08lx", buf, *res_ptr);
+		sprintf(buf, "%s %08x", buf, *res_ptr);
 	}
 	strcat(buf, "\n");
 
 	return strlen(buf);
 }
-#endif
+#endif /* 0 */
+#endif /* CONFIG_PROC_FS */
+
+static struct parisc_device_id sba_tbl[] = {
+	{ HPHW_IOA, HVERSION_REV_ANY_ID, ASTRO_RUNWAY_PORT, 0xb },
+	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_MERCED_PORT, 0xc },
+	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REO_MERCED_PORT, 0xc },
+	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, REOG_MERCED_PORT, 0xc },
+/* These two entries commented out because we don't find them in a
+ * buswalk yet.  If/when we do, they would cause us to think we had
+ * many more SBAs then we really do.
+ *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, ASTRO_ROPES_PORT, 0xc },
+ *	{ HPHW_BCPORT, HVERSION_REV_ANY_ID, IKE_ROPES_PORT, 0xc },
+ */
+	{ 0, }
+};
+
+int sba_driver_callback(struct parisc_device *);
+
+static struct parisc_driver sba_driver = {
+	name:		MODULE_NAME,
+	id_table:	sba_tbl,
+	probe:		sba_driver_callback,
+};
 
 /*
 ** Determine if lba should claim this chip (return 0) or not (return 1).
@@ -1692,47 +1931,75 @@
 ** have work to do.
 */
 int
-sba_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+sba_driver_callback(struct parisc_device *dev)
 {
 	struct sba_device *sba_dev;
 	u32 func_class;
 	int i;
+	char *version;
 
-	if (IS_ASTRO(d)) {
+#ifdef DEBUG_SBA_INIT
+	sba_dump_ranges(dev->hpa);
+#endif
+
+	/* Read HW Rev First */
+	func_class = READ_REG(dev->hpa + SBA_FCLASS);
+
+	if (IS_ASTRO(&dev->id)) {
+		unsigned long fclass;
 		static char astro_rev[]="Astro ?.?";
 
-		/* Read HW Rev First */
-		func_class = READ_REG32(d->hpa);
+		/* Astro is broken...Read HW Rev First */
+		fclass = READ_REG(dev->hpa);
 
-		astro_rev[6] = '1' + (char) (func_class & 0x7);
-		astro_rev[8] = '0' + (char) ((func_class & 0x18) >> 3);
-		dri->version = astro_rev;
-	} else {
-		static char ike_rev[]="Ike rev ?";
+		astro_rev[6] = '1' + (char) (fclass & 0x7);
+		astro_rev[8] = '0' + (char) ((fclass & 0x18) >> 3);
+		version = astro_rev;
 
-		/* Read HW Rev First */
-		func_class = READ_REG32(d->hpa + SBA_FCLASS);
+	} else if (IS_IKE(&dev->id)) {
+		static char ike_rev[]="Ike rev ?";
 
 		ike_rev[8] = '0' + (char) (func_class & 0xff);
-		dri->version = ike_rev;
+		version = ike_rev;
+	} else {
+		static char reo_rev[]="REO rev ?";
+
+		reo_rev[8] = '0' + (char) (func_class & 0xff);
+		version = reo_rev;
+	}
+
+	if (!global_ioc_cnt) {
+		global_ioc_cnt = count_parisc_driver(&sba_driver);
+
+		/* Only Astro has one IOC per SBA */
+		if (!IS_ASTRO(&dev->id))
+			global_ioc_cnt *= 2;
 	}
 
-	printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
+	printk(KERN_INFO "%s found %s at 0x%lx\n",
+		MODULE_NAME, version, dev->hpa);
+
+#ifdef DEBUG_SBA_INIT
+	sba_dump_tlb(dev->hpa);
+#endif
 
 	sba_dev = kmalloc(sizeof(struct sba_device), GFP_KERNEL);
-	if (NULL == sba_dev)
-	{
-		printk(MODULE_NAME " - couldn't alloc sba_device\n");
+	if (NULL == sba_dev) {
+		printk(KERN_ERR MODULE_NAME " - couldn't alloc sba_device\n");
 		return(1);
 	}
+
+	dev->sysdata = (void *) sba_dev;
 	memset(sba_dev, 0, sizeof(struct sba_device));
+
 	for(i=0; i<MAX_IOC; i++)
 		spin_lock_init(&(sba_dev->ioc[i].res_lock));
 
-
+	sba_dev->dev = dev;
 	sba_dev->hw_rev = func_class;
-	sba_dev->iodc = d;
-	sba_dev->sba_hpa = d->hpa;  /* faster access */
+	sba_dev->iodc = &dev->id;
+	sba_dev->name = dev->name;
+	sba_dev->sba_hpa = dev->hpa;  /* faster access */
 
 	sba_get_pat_resources(sba_dev);
 	sba_hw_init(sba_dev);
@@ -1741,12 +2008,46 @@
 	hppa_dma_ops = &sba_ops;
 
 #ifdef CONFIG_PROC_FS
-	if (IS_ASTRO(d)) {
+	if (IS_ASTRO(&dev->id)) {
 		create_proc_info_entry("Astro", 0, proc_runway_root, sba_proc_info);
-	} else {
+	} else if (IS_IKE(&dev->id)) {
 		create_proc_info_entry("Ike", 0, proc_runway_root, sba_proc_info);
+	} else {
+		create_proc_info_entry("Reo", 0, proc_runway_root, sba_proc_info);
 	}
+#if 0
 	create_proc_info_entry("bitmap", 0, proc_runway_root, sba_resource_map);
 #endif
+#endif
 	return 0;
 }
+
+/*
+** One time initialization to let the world know the SBA was found.
+** This is the only routine which is NOT static.
+** Must be called exactly once before pci_init().
+*/
+void __init sba_init(void)
+{
+	register_parisc_driver(&sba_driver);
+}
+
+
+/**
+ * sba_get_iommu - Assign the iommu pointer for the pci bus controller.
+ * @dev: The parisc device.
+ *
+ * This function searches through the registerd IOMMU's and returns the
+ * appropriate IOMMU data for the given parisc PCI controller.
+ */
+void * sba_get_iommu(struct parisc_device *pci_hba)
+{
+	struct sba_device *sba = (struct sba_device *) pci_hba->parent->sysdata;
+	char t = pci_hba->parent->id.hw_type;
+	int iocnum = (pci_hba->hw_path >> 3);	/* rope # */
+
+	if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
+		BUG();
+
+	return &(sba->ioc[iocnum]);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/semaphore.c linux/arch/parisc/kernel/semaphore.c
--- linux.orig/arch/parisc/kernel/semaphore.c	2001-04-18 00:19:25.000000000 +0000
+++ linux/arch/parisc/kernel/semaphore.c	2002-08-12 22:14:24.000000000 +0000
@@ -1,131 +1,100 @@
 /*
- * Just taken from alpha implementation.
- * This can't work well, perhaps.
- */
-/*
- *  Generic semaphore code. Buyer beware. Do your own
- * specific changes in <asm/semaphore-helper.h>
+ * Semaphore implementation Copyright (c) 2001 Matthew Wilcox, Hewlett-Packard
  */
 
 #include <linux/sched.h>
-#include <asm/semaphore-helper.h>
+#include <linux/spinlock.h>
 
 /*
- * Semaphores are implemented using a two-way counter:
- * The "count" variable is decremented for each process
- * that tries to sleep, while the "waking" variable is
- * incremented when the "up()" code goes to wake up waiting
- * processes.
- *
- * Notably, the inline "up()" and "down()" functions can
- * efficiently test if they need to do any extra work (up
- * needs to do something only if count was negative before
- * the increment operation.
- *
- * waking_non_zero() (from asm/semaphore.h) must execute
- * atomically.
- *
- * When __up() is called, the count was negative before
- * incrementing it, and we need to wake up somebody.
- *
- * This routine adds one to the count of processes that need to
- * wake up and exit.  ALL waiting processes actually wake up but
- * only the one that gets to the "waking" field first will gate
- * through and acquire the semaphore.  The others will go back
- * to sleep.
- *
- * Note that these functions are only called when there is
- * contention on the lock, and as such all this is the
- * "non-critical" part of the whole semaphore business. The
- * critical part is the inline stuff in <asm/semaphore.h>
- * where we want to avoid any extra jumps and calls.
+ * Semaphores are complex as we wish to avoid using two variables.
+ * `count' has multiple roles, depending on its value.  If it is positive
+ * or zero, there are no waiters.  The functions here will never be
+ * called; see <asm/semaphore.h>
+ *
+ * When count is -1 it indicates there is at least one task waiting
+ * for the semaphore.
+ *
+ * When count is less than that, there are '- count - 1' wakeups
+ * pending.  ie if it has value -3, there are 2 wakeups pending.
+ *
+ * Note that these functions are only called when there is contention
+ * on the lock, and as such all this is the "non-critical" part of the
+ * whole semaphore business. The critical part is the inline stuff in
+ * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
  */
 void __up(struct semaphore *sem)
 {
-	wake_one_more(sem);
+	sem->count--;
 	wake_up(&sem->wait);
 }
 
-/*
- * Perform the "down" function.  Return zero for semaphore acquired,
- * return negative for signalled out of the function.
- *
- * If called from __down, the return is ignored and the wait loop is
- * not interruptible.  This means that a task waiting on a semaphore
- * using "down()" cannot be killed until someone does an "up()" on
- * the semaphore.
- *
- * If called from __down_interruptible, the return value gets checked
- * upon return.  If the return value is negative then the task continues
- * with the negative value in the return register (it can be tested by
- * the caller).
- *
- * Either form may be used in conjunction with "up()".
- *
- */
-
+#define wakers(count) (-1 - count)
 
-#define DOWN_HEAD(task_state)						\
+#define DOWN_HEAD							\
+	int ret = 0;							\
+	DECLARE_WAITQUEUE(wait, current);				\
 									\
+	/* Note that someone is waiting */				\
+	if (sem->count == 0)						\
+		sem->count = -1;					\
 									\
-	current->state = (task_state);					\
-	add_wait_queue(&sem->wait, &wait);				\
-									\
-	/*								\
-	 * Ok, we're set up.  sem->count is known to be less than zero	\
-	 * so we must wait.						\
-	 *								\
-	 * We can let go the lock for purposes of waiting.		\
-	 * We re-acquire it after awaking so as to protect		\
-	 * all semaphore operations.					\
-	 *								\
-	 * If "up()" is called before we call waking_non_zero() then	\
-	 * we will catch it right away.  If it is called later then	\
-	 * we will have to go through a wakeup cycle to catch it.	\
-	 *								\
-	 * Multiple waiters contend for the semaphore lock to see	\
-	 * who gets to gate through and who has to wait some more.	\
-	 */								\
-	for (;;) {
-
-#define DOWN_TAIL(task_state)			\
-		current->state = (task_state);	\
-	}					\
-	current->state = TASK_RUNNING;		\
-	remove_wait_queue(&sem->wait, &wait);
+	/* protected by the sentry still -- use unlocked version */	\
+	wait.flags = WQ_FLAG_EXCLUSIVE;					\
+	__add_wait_queue_tail(&sem->wait, &wait);			\
+ lost_race:								\
+	spin_unlock_irq(&sem->sentry);					\
+
+#define DOWN_TAIL							\
+	spin_lock_irq(&sem->sentry);					\
+	if (wakers(sem->count) == 0 && ret == 0)			\
+		goto lost_race;	/* Someone stole our wakeup */		\
+	__remove_wait_queue(&sem->wait, &wait);				\
+	current->state = TASK_RUNNING;					\
+	if (!waitqueue_active(&sem->wait) && (sem->count < 0))		\
+		sem->count = wakers(sem->count);
+
+#define UPDATE_COUNT							\
+	sem->count += (sem->count < 0) ? 1 : - 1;
+	
 
 void __down(struct semaphore * sem)
 {
-	DECLARE_WAITQUEUE(wait, current);
+	DOWN_HEAD
+
+	for(;;) {
+		set_task_state(current, TASK_UNINTERRUPTIBLE);
+		/* we can _read_ this without the sentry */
+		if (sem->count != -1)
+			break;
+ 		schedule();
+ 	}
 
-	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
-	if (waking_non_zero(sem))
-		break;
-	schedule();
-	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+	DOWN_TAIL
+	UPDATE_COUNT
 }
 
 int __down_interruptible(struct semaphore * sem)
 {
-	DECLARE_WAITQUEUE(wait, current);
-	int ret = 0;
+	DOWN_HEAD
 
-	DOWN_HEAD(TASK_INTERRUPTIBLE)
+	for(;;) {
+		set_task_state(current, TASK_INTERRUPTIBLE);
+		/* we can _read_ this without the sentry */
+		if (sem->count != -1)
+			break;
+
+		if (signal_pending(current)) {
+			ret = -EINTR;
+			break;
+		}
+		schedule();
+	}
 
-	ret = waking_non_zero_interruptible(sem, current);
-	if (ret)
-	{
-		if (ret == 1)
-			/* ret != 0 only if we get interrupted -arca */
-			ret = 0;
-		break;
+	DOWN_TAIL
+
+	if (!ret) {
+		UPDATE_COUNT
 	}
-	schedule();
-	DOWN_TAIL(TASK_INTERRUPTIBLE)
-	return ret;
-}
 
-int __down_trylock(struct semaphore * sem)
-{
-	return waking_non_zero_trylock(sem);
+	return ret;
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/setup.c linux/arch/parisc/kernel/setup.c
--- linux.orig/arch/parisc/kernel/setup.c	2001-02-09 19:29:44.000000000 +0000
+++ linux/arch/parisc/kernel/setup.c	2002-08-12 22:14:26.000000000 +0000
@@ -1,12 +1,13 @@
 /*    $Id: setup.c,v 1.8 2000/02/02 04:42:38 prumpf Exp $
  *
  *    Initial setup-routines for HP 9000 based hardware.
- * 
+ *
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *    Modifications for PA-RISC (C) 1999 Helge Deller <helge.deller@ruhr-uni-bochum.de>
+ *    Modifications for PA-RISC (C) 1999 Helge Deller <deller@gmx.de>
  *    Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
  *    Modifications copyright 2000 Martin K. Petersen <mkp@mkp.net>
  *    Modifications copyright 2000 Philipp Rumpf <prumpf@tux.org>
+ *    Modifications copyright 2001 Ryan Bradetich <rbradetich@uswest.net>
  *
  *    Initial PA-RISC Version: 04-23-1999 by Helge Deller
  *
@@ -19,596 +20,308 @@
  *    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.
  *
  */
 
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/ptrace.h>
-#include <linux/sched.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/user.h>
-#include <linux/tty.h>
 #include <linux/config.h>
-#include <linux/fs.h>
-#include <linux/kdev_t.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/blk.h>
+#include <linux/kernel.h>
+#include <linux/blk.h>          /* for initrd_start and initrd_end */
 #include <linux/init.h>
-#include <linux/interrupt.h>
 #include <linux/console.h>
-#include <linux/bootmem.h>
-#include <linux/delay.h>
+#include <linux/seq_file.h>
+#define PCI_DEBUG
 #include <linux/pci.h>
-#include <linux/threads.h>
+#undef PCI_DEBUG
+#include <linux/proc_fs.h>
 
-#include <asm/cache.h>
-#include <asm/hardware.h>	/* for register_driver() stuff */
 #include <asm/processor.h>
-#include <asm/page.h>
 #include <asm/pdc.h>
 #include <asm/led.h>
-#include <asm/real.h>
-#include <asm/system.h>
 #include <asm/machdep.h>	/* for pa7300lc_init() proto */
 
-#include <asm/irq.h>		/* for struct irq_region */
-#include <asm/pdcpat.h>		/* for PA_VIEW PDC_PAT_CPU_GET_NUMBER etc */
-
-#include <linux/proc_fs.h>
-
 #define COMMAND_LINE_SIZE 1024
 char	saved_command_line[COMMAND_LINE_SIZE];
+char	command_line[COMMAND_LINE_SIZE];
 
-/*
-** KLUGE ALERT!
-**
-** We *really* should be using a combination of request_resource()
-** and request_region()! But request_region() requires kmalloc since
-** returns a new struct resource. And kmalloc just isn't available
-** until after mem_init() is called from start_kernel().
-**
-** FIXME: assume contiguous memory initially.
-**     Additional chunks of memory might be added to sysram_resource.sibling.
-*/
-static struct resource sysrom_resource  = {
-	name: "System ROM", start: 0x0f0000000UL, end: 0x0f00fffffUL,
-	flags: IORESOURCE_BUSY | IORESOURCE_MEM,
-	parent: &iomem_resource, sibling: NULL, child: NULL };
-
-static struct resource pdcdata_resource;
-
-static struct resource sysram_resource  = {
-	name: "System RAM", start: 0UL, end: ~0UL /* bogus */,
-	flags: IORESOURCE_MEM,
-	parent: &iomem_resource, sibling: &sysrom_resource, child: &pdcdata_resource};
-
-extern char _text;	/* start of kernel code, defined by linker */
-extern int  data_start; 
-extern char _edata;	/* end of data, begin BSS, defined by linker */
-extern char _end;	/* end of BSS, defined by linker */
-
-static struct resource data_resource    = {
-	name: "kernel Data", start: virt_to_phys(&data_start), end: virt_to_phys(&_end)-1,
-	flags: IORESOURCE_BUSY | IORESOURCE_MEM,
-	parent: &sysram_resource, sibling: NULL, child: NULL};
-
-static struct resource code_resource = {
-	name: "Kernel Code", start: virt_to_phys(&_text), end: virt_to_phys(&data_start)-1,
-	flags: IORESOURCE_BUSY | IORESOURCE_MEM,
-	parent: &sysram_resource, sibling: &data_resource, child: NULL};
-
-static struct resource pdcdata_resource = {
-	name: "PDC data (Page Zero)", start: 0, end: 0x9ff,
-	flags: IORESOURCE_BUSY | IORESOURCE_MEM,
-	parent: &sysram_resource, sibling: &code_resource, child: NULL};
-
-
+/* Intended for ccio/sba/cpu statistics under /proc/bus/{runway|gsc} */
+struct proc_dir_entry * proc_runway_root = NULL;
+struct proc_dir_entry * proc_gsc_root = NULL;
 
+#ifdef CONFIG_EISA
+int EISA_bus;	/* This has to go somewhere in architecture specific code. */
+#endif
 
-struct system_cpuinfo_parisc boot_cpu_data;
-struct cpuinfo_parisc cpu_data[NR_CPUS];
-
-extern void do_inventory(void);
-extern void cache_init(void);
-extern struct hp_device * register_module(void *hpa);
-
-static int cpu_driver_callback(struct hp_device *, struct pa_iodc_driver *);
-
-static struct pa_iodc_driver cpu_drivers_for[] = {
-	{HPHW_NPROC, 0x0, 0x0, 0x0, 0, 0,
-		DRIVER_CHECK_HWTYPE,
-		"CPU", "PARISC", (void *) cpu_driver_callback},
-	{0,0,0,0,0,0,
-		0,
-		(char *) NULL, (char *) NULL, (void *) NULL }
-};
+void __init setup_cmdline(char **cmdline_p)
+{
+	extern unsigned int boot_args[];
 
-static long fallback_cpu_hpa[] = { 0xfffa0000L, 0xfffbe000L, 0x0 };
+	/* Collect stuff passed in from the boot loader */
 
+	/* boot_args[0] is free-mem start, boot_args[1] is ptr to command line */
+	if (boot_args[0] < 64) {
+		/* called from hpux boot loader */
+		saved_command_line[0] = '\0';
+	} else {
+		strcpy(saved_command_line, (char *)__va(boot_args[1]));
 
-/*
-**  	PARISC CPU driver - claim "device" and initialize CPU data structures.
-**
-** Consolidate per CPU initialization into (mostly) one module.
-** Monarch CPU will initialize boot_cpu_data which shouldn't
-** change once the system has booted.
-**
-** The callback *should* do per-instance initialization of
-** everything including the monarch. Some of the code that's
-** in setup.c:start_parisc() should migrate here and start_parisc()
-** should "register_driver(cpu_driver_for)" before calling
-** do_inventory().
-**
-** The goal of consolidating CPU initialization into one place is
-** to make sure all CPU's get initialized the same way.
-** It would be nice if the even the manarch through the exact same code path.
-** (up to rendevous at least).
-*/
-#undef ASSERT
-#define ASSERT(expr) \
-	if(!(expr)) { \
-		printk( "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
-		panic(#expr); \
+#ifdef CONFIG_BLK_DEV_INITRD
+		if (boot_args[2] != 0) /* did palo pass us a ramdisk? */
+		{
+		    initrd_start = (unsigned long)__va(boot_args[2]);
+		    initrd_end = (unsigned long)__va(boot_args[3]);
+		}
+#endif
 	}
 
-static int
-cpu_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
+	strcpy(command_line, saved_command_line);
+	*cmdline_p = command_line;
+}
+
+#ifdef CONFIG_PA11
+void __init dma_ops_init(void)
 {
-#ifdef __LP64__
-	extern int pdc_pat;	/* arch/parisc/kernel/inventory.c */
-	static unsigned long pdc_result[32] __attribute__ ((aligned (8))) = {0,0,0,0};
-#endif
-	struct cpuinfo_parisc *p;
+	switch (boot_cpu_data.cpu_type) {
+	case pcx:
+		/*
+		 * We've got way too many dependencies on 1.1 semantics
+		 * to support 1.0 boxes at this point.
+		 */
+		panic(	"PA-RISC Linux currently only supports machines that conform to\n"
+			"the PA-RISC 1.1 or 2.0 architecture specification.\n");
 
-#ifndef CONFIG_SMP
-	if (boot_cpu_data.cpu_count > 0) {
-		printk(KERN_INFO "CONFIG_SMP disabled - not claiming addional CPUs\n");
-		return(1);
+	case pcxs:
+	case pcxt:
+		hppa_dma_ops = &pcx_dma_ops;
+		break;
+	case pcxl2:
+		pa7300lc_init();
+	case pcxl: /* falls through */
+		hppa_dma_ops = &pcxl_dma_ops;
+		break;
+	default:
+		break;
 	}
+}
 #endif
 
-	p = &cpu_data[boot_cpu_data.cpu_count];
-	boot_cpu_data.cpu_count++;
-
-/* TODO: Enable FP regs - done early in start_parisc() now */
-
-	/* initialize counters */
-	memset(p, 0, sizeof(struct cpuinfo_parisc));
+extern int init_per_cpu(int cpuid);
+extern void collect_boot_cpu_data(void);
 
-	p->hpa = (unsigned long) d->hpa; /* save CPU hpa */
+void __init setup_arch(char **cmdline_p)
+{
+	init_per_cpu(smp_processor_id());	/* Set Modes & Enable FP */
 
 #ifdef __LP64__
-	if (pdc_pat) {
-		ulong status;
-	        pdc_pat_cell_mod_maddr_block_t pa_pdc_cell;
-
-		status = pdc_pat_cell_module(& pdc_result, d->pcell_loc,
-			d->mod_index, PA_VIEW, & pa_pdc_cell);
-
-		ASSERT(PDC_RET_OK == status);
-
-		/* verify it's the same as what do_pat_inventory() found */
-		ASSERT(d->mod_info == pa_pdc_cell.mod_info);
-		ASSERT(d->pmod_loc == pa_pdc_cell.mod_location);
-		ASSERT(d->mod_path == pa_pdc_cell.mod_path);
-
-		p->txn_addr = pa_pdc_cell.mod[0];   /* id_eid for IO sapic */
-
-		/* get the cpu number */
-		status = mem_pdc_call( PDC_PAT_CPU, PDC_PAT_CPU_GET_NUMBER,
-				__pa(& pdc_result), d->hpa);
+	printk(KERN_INFO "The 64-bit Kernel has started...\n");
+#else
+	printk(KERN_INFO "The 32-bit Kernel has started...\n");
+#endif
 
-		ASSERT(PDC_RET_OK == status);
+	pdc_console_init();
 
-		p->cpuid = pdc_result[0];
+#ifdef CONFIG_PDC_NARROW
+	printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
+#endif
+	setup_pdc();
+	setup_cmdline(cmdline_p);
+	collect_boot_cpu_data();
+	do_memory_inventory();  /* probe for physical memory */
+	cache_init();
+	paging_init();
 
-	} else
+#ifdef CONFIG_CHASSIS_LCD_LED
+	/* initialize the LCD/LED after boot_cpu_data is available ! */
+        led_init();				/* LCD/LED initialization */
 #endif
-	{
-		p->txn_addr = (unsigned long) d->hpa;	/* for normal parisc */
 
-		/* logical CPU ID and update global counter */
-		p->cpuid = boot_cpu_data.cpu_count - 1;
-	}
+#ifdef CONFIG_PA11
+	dma_ops_init();
+#endif
 
-	/*
-	** itimer and ipi IRQ handlers are statically initialized in
-	** arch/parisc/kernel/irq.c
-	*/
-	p->region = irq_region[IRQ_FROM_REGION(CPU_IRQ_REGION)];
+#ifdef CONFIG_VT
+# if defined(CONFIG_STI_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
+        conswitchp = &dummy_con;        /* we use take_over_console() later ! */
+# endif
+#endif
 
-	return(0);
 }
 
+/*
+ * Display cpu info for all cpu's.
+ * for parisc this is in processor.c
+ */
+extern int show_cpuinfo (struct seq_file *m, void *v);
 
-void __xchg_called_with_bad_pointer(void)
+static void *
+c_start (struct seq_file *m, loff_t *pos)
 {
-    printk(KERN_EMERG "xchg() called with bad pointer !\n");
+    	/* Looks like the caller will call repeatedly until we return
+	 * 0, signaling EOF perhaps.  This could be used to sequence
+	 * through CPUs for example.  Since we print all cpu info in our
+	 * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above)
+	 * we only allow for one "position".  */
+	return ((long)*pos < 1) ? (void *)1 : NULL;
 }
 
-
-/* Some versions of IODC don't list the CPU, and since we don't walk
- * the bus yet, we have to probe for processors at well known hpa
- * addresses.  
- */
-
-void __init register_fallback_cpu (void)
+static void *
+c_next (struct seq_file *m, void *v, loff_t *pos)
 {
-	struct hp_device *d = NULL;
-	int i = 0;
-	
-#ifdef CONFIG_SMP
-#error "Revisit CPU fallback addresses for SMP (Assuming bus walk hasn't been implemented)"
-#endif
-	printk ("No CPUs reported by firmware - probing...\n");
-	
-	while (fallback_cpu_hpa[i]) {
-		
-		d = register_module ((void *) fallback_cpu_hpa[i]);
-		
-		if (d > 0) {
-			printk ("Found CPU at %lx\n", fallback_cpu_hpa[i]);
-			cpu_driver_callback (d, 0);
-			return;
-		}
-		
-		i++;
-	}
-	
-	panic ("No CPUs found.  System halted.\n");
-	return;
+	++*pos;
+	return c_start(m, pos);
 }
 
-
-/*
- * Get CPU information and store it in the boot_cpu_data structure.  */
-void __init collect_boot_cpu_data(void)
+static void
+c_stop (struct seq_file *m, void *v)
 {
-	memset(&boot_cpu_data,0,sizeof(boot_cpu_data));
-
-	boot_cpu_data.cpu_hz = 100 * PAGE0->mem_10msec; /* Hz of this PARISC */
-
-	/* get CPU-Model Information... */
-#define p ((unsigned long *)&boot_cpu_data.pdc.model)
-	if(pdc_model_info(&boot_cpu_data.pdc.model)==0)
-		printk("model	%08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-			p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]);
-#undef p
-
-	if(pdc_model_versions(&boot_cpu_data.pdc.versions, 0)==0)
-		printk("vers	%08lx\n", boot_cpu_data.pdc.versions.cpuid);
-
-	if(pdc_model_cpuid(&boot_cpu_data.pdc.cpuid)==0)
-		printk("cpuid	%08lx\n", boot_cpu_data.pdc.cpuid.cpuid);
-	
-	printk("CPUID	vers %ld rev %ld\n",
-		(boot_cpu_data.pdc.cpuid.cpuid >> 5) & 127,
-		boot_cpu_data.pdc.cpuid.cpuid & 31);
-
-	if (pdc_model_sysmodel(boot_cpu_data.pdc.sys_model_name)==0)
-		printk("model	%s\n",boot_cpu_data.pdc.sys_model_name);
-
-	boot_cpu_data.model_name = parisc_getHWdescription(HPHW_NPROC,
-		boot_cpu_data.pdc.model.hversion>>4,
-		boot_cpu_data.pdc.model.sversion>>8);
-	
-	boot_cpu_data.hversion =  boot_cpu_data.pdc.model.hversion;
-	boot_cpu_data.sversion =  boot_cpu_data.pdc.model.sversion;
-
-	boot_cpu_data.cpu_type =
-			parisc_get_cpu_type(boot_cpu_data.pdc.model.hversion);
-
-	boot_cpu_data.cpu_name = cpu_name_version[boot_cpu_data.cpu_type][0];
-	boot_cpu_data.family_name = cpu_name_version[boot_cpu_data.cpu_type][1];
 }
 
+struct seq_operations cpuinfo_op = {
+	start:	c_start,
+	next:	c_next,
+	stop:	c_stop,
+	show:	show_cpuinfo
+};
 
-#ifdef __LP64__
-#define COMMAND_GLOBAL  0xfffffffffffe0030UL
-#else
-#define COMMAND_GLOBAL  0xfffe0030
-#endif
-
-#define CMD_RESET       5       /* reset any module */
-
-/*
-** The Wright Brothers and Gecko systems have a H/W problem
-** (Lasi...'nuf said) may cause a broadcast reset to lockup
-** the system. An HVERSION dependent PDC call was developed
-** to perform a "safe", platform specific broadcast reset instead
-** of kludging up all the code.
-**
-** Older machines which do not implement PDC_BROADCAST_RESET will
-** return (with an error) and the regular broadcast reset can be
-** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
-** the PDC call will not return (the system will be reset).
-*/
-static int
-reset_parisc(struct notifier_block *self, unsigned long command, void *ptr)
+static void parisc_proc_mkdir(void)
 {
-	printk("%s: %s(cmd=%lu)\n", __FILE__, __FUNCTION__, command);
-
-	switch(command) {
-	case MACH_RESTART:
-#ifdef FASTBOOT_SELFTEST_SUPPORT
-		/*
-		** If user has modified the Firmware Selftest Bitmap,
-		** run the tests specified in the bitmap after the
-		** system is rebooted w/PDC_DO_RESET.
-		**
-		** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
-		**
-		** Using "directed resets" at each processor with the MEM_TOC
-		** vector cleared will also avoid running destructive
-		** memory self tests. (Not implemented yet)
-		*/
-		if (ftc_bitmap) {
-			mem_pdc_call( PDC_BROADCAST_RESET,
-				PDC_DO_FIRM_TEST_RESET, PDC_FIRM_TEST_MAGIC,
-				ftc_bitmap);
+	/*
+	** Can't call proc_mkdir() until after proc_root_init() has been
+	** called by start_kernel(). In other words, this code can't
+	** live in arch/.../setup.c because start_parisc() calls
+	** start_kernel().
+	*/
+	switch (boot_cpu_data.cpu_type) {
+	case pcxl:
+	case pcxl2:
+		if (NULL == proc_gsc_root)
+		{
+			proc_gsc_root = proc_mkdir("bus/gsc", 0);
 		}
-#endif
-
-		/* "Normal" system reset */
-		(void) mem_pdc_call(PDC_BROADCAST_RESET, PDC_DO_RESET,
-			0L, 0L, 0L);
-
-		/* Nope...box should reset with just CMD_RESET now */
-		gsc_writel(CMD_RESET, COMMAND_GLOBAL);
-
-		/* Wait for RESET to lay us to rest. */
-		while (1) ;
-
 		break;
+        case pcxt_:
+        case pcxu:
+        case pcxu_:
+        case pcxw:
+        case pcxw_:
+        case pcxw2:
+                if (NULL == proc_runway_root)
+                {
+                        proc_runway_root = proc_mkdir("bus/runway", 0);
+                }
+                break;
 	}
-	return NOTIFY_DONE;
 }
 
-static struct notifier_block parisc_block = { reset_parisc, NULL, 0 };
+static struct resource central_bus = {
+	name:	"Central Bus",
+	start:	(unsigned long)0xfffffffffff80000,
+	end:    (unsigned long)0xfffffffffffaffff,
+	flags:	IORESOURCE_MEM,
+};
 
+static struct resource local_broadcast = {
+	name:	"Local Broadcast",
+	start:	(unsigned long)0xfffffffffffb0000,
+	end:	(unsigned long)0xfffffffffffdffff,
+	flags:	IORESOURCE_MEM,
+};
 
-/*  start_parisc() will be called from head.S to setup our new memory_start 
-    and actually start our kernel !
-    Memory-Layout is:
-	- Kernel-Image (code+data+BSS)
-	- Stack (stack-size see below!, stack-setup-code is in head.S)
-	- memory_start at end of stack..
-*/
-
-unsigned long mem_start, mem_max;
-unsigned long start_pfn, max_pfn;
-extern asmlinkage void __init start_kernel(void);
-
-#define PFN_UP(x)	(((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
-#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
-#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
+static struct resource global_broadcast = {
+	name:	"Global Broadcast",
+	start:	(unsigned long)0xfffffffffffe0000,
+	end:	(unsigned long)0xffffffffffffffff,
+	flags:	IORESOURCE_MEM,
+};
 
-void __init start_parisc(unsigned arg0, unsigned arg1,
-			 unsigned arg2, unsigned arg3)
+int __init parisc_init_resources(void)
 {
-	register unsigned long ccr;
-	unsigned long memory_start;
-
-	/* Clear BSS */
+	int result;
 
-	{
-		char *p = &_edata, *q = &_end;
-
-		while (p < q) {
-			*p++ = 0;
-		}
+	result = request_resource(&iomem_resource, &central_bus);
+	if (result < 0) {
+		printk(KERN_ERR 
+		       "%s: failed to claim %s address space!\n", 
+		       __FILE__, central_bus.name);
+		return result;
 	}
 
-
-	pdc_console_init();
-
-#ifdef __LP64__
-	printk("The 64-bit Kernel has started...\n");
-#else
-	printk("The 32-bit Kernel has started...\n");
-#endif
-
-	/*
-	** Enable FP coprocessor
-	**
-	** REVISIT: ccr should be set by PDC_COPROC results to support PA1.0.
-	** Hardcoding works for PA1.1 processors.
-	**
-	** REVISIT: this could be done in the "code 22" trap handler.
-	** (frowands idea - that way we know which processes need FP
-	** registers saved on the interrupt stack.)
-	**
-	** NEWS FLASH: wide kernels need FP coprocessor enabled to handle
-	** formatted printing of %lx for example (double divides I think)
-	*/
-	ccr = 0xc0;
-	mtctl(ccr, 10);
-	printk("Enabled FP coprocessor\n");
-
-#ifdef __LP64__
-	printk( "If this is the LAST MESSAGE YOU SEE, you're probably using\n"
-		"32-bit millicode by mistake.\n");
-#endif
-
-	memory_start = (unsigned long) &_end;
-	memory_start = (memory_start + PAGE_SIZE) & PAGE_MASK;
-	printk("Free memory starts at: 0x%lx\n", memory_start);
-
-	/* Collect stuff passed in from the boot loader */
-	printk(KERN_WARNING  "%s(0x%x,0x%x,0x%x,0x%x)\n", 
-		    __FUNCTION__, arg0, arg1, arg2, arg3);
-
-	/* arg0 is free-mem start, arg1 is ptr to command line */
-	if (arg0 < 64) {
-		/* called from hpux boot loader */
-		saved_command_line[0] = '\0';
-	} else {
-		strcpy(saved_command_line, (char *)__va(arg1));
-		printk("PALO command line: '%s'\nPALO initrd %x-%x\n",
-		    saved_command_line, arg2, arg3);
-
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (arg2 != 0) /* did palo pass us a ramdisk? */
-		{
-		    initrd_start = (unsigned long)__va(arg2);
-		    initrd_end = (unsigned long)__va(arg3);
-		}
-#endif
+	result = request_resource(&iomem_resource, &local_broadcast);
+	if (result < 0) {
+		printk(KERN_ERR 
+		       "%s: failed to claim %saddress space!\n", 
+		       __FILE__, local_broadcast.name);
+		return result;
 	}
 
-	mem_start = __pa(memory_start);
-#define MAX_MEM (512*1024*1024)
-	mem_max = (PAGE0->imm_max_mem > MAX_MEM ? MAX_MEM : PAGE0->imm_max_mem);
-
-	collect_boot_cpu_data();
+	result = request_resource(&iomem_resource, &global_broadcast);
+	if (result < 0) {
+		printk(KERN_ERR 
+		       "%s: failed to claim %s address space!\n", 
+		       __FILE__, global_broadcast.name);
+		return result;
+	}
 
-	/* initialize the LCD/LED after boot_cpu_data is available ! */
-        led_init();				/* LCD/LED initialization */
+	return 0;
+}
 
-	do_inventory();				/* probe for hardware */
-        register_driver(cpu_drivers_for);	/* claim all the CPUs */
+extern void gsc_init(void);
+extern void processor_init(void);
+extern void ccio_init(void);
+extern void dino_init(void);
+extern void iosapic_init(void);
+extern void lba_init(void);
+extern void sba_init(void);
+extern void eisa_init(void);
 
-	if (boot_cpu_data.cpu_count == 0)
-	    register_fallback_cpu();
+void __init parisc_init(void)
+{
+	parisc_proc_mkdir();
+	parisc_init_resources();
+	do_device_inventory();                  /* probe for hardware */
 
-	printk("CPU(s): %d x %s at %d.%06d MHz\n", 
+	processor_init();
+	printk(KERN_INFO "CPU(s): %d x %s at %d.%06d MHz\n",
 			boot_cpu_data.cpu_count,
 			boot_cpu_data.cpu_name,
-			boot_cpu_data.cpu_hz / 1000000, 
+			boot_cpu_data.cpu_hz / 1000000,
 			boot_cpu_data.cpu_hz % 1000000	);
 
-	switch (boot_cpu_data.cpu_type) {
-	case pcx:
-	case pcxs:
-	case pcxt:
-		hppa_dma_ops = &pcx_dma_ops;
-		break;
-	case pcxl2:
-		pa7300lc_init();
-	case pcxl: /* falls through */
-		hppa_dma_ops = &pcxl_dma_ops;
-		break;
-	default:
-		break;
-	}
-
-#if 1
-	/* KLUGE! this really belongs in kernel/resource.c! */
-	iomem_resource.end = ~0UL;
-#endif
-	sysram_resource.end = mem_max - 1;
-	notifier_chain_register(&mach_notifier, &parisc_block);
-	start_kernel(); 	/* now back to arch-generic code... */
-}
-
-void __init setup_arch(char **cmdline_p)
-{
-	unsigned long bootmap_size;
-	unsigned long start_pfn;
-	unsigned long mem_free;
-
-	*cmdline_p = saved_command_line;
-
-	/* initialize bootmem */
-
-	start_pfn = PFN_UP(mem_start);
-	max_pfn = PFN_DOWN(mem_max);
-
-	bootmap_size = init_bootmem(start_pfn, max_pfn);
-
-	mem_start += bootmap_size;
-	mem_free = mem_max - mem_start;
-
-	/* free_bootmem handles rounding nicely */
-	printk("free_bootmem(0x%lx, 0x%lx)\n", (unsigned long)mem_start,
-			(unsigned long)mem_free);
-	free_bootmem(mem_start, mem_free);
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	printk("initrd: %08x-%08x\n", (int) initrd_start, (int) initrd_end);
-
-	if (initrd_end != 0) {
-		initrd_below_start_ok = 1;
-		reserve_bootmem(__pa(initrd_start), initrd_end - initrd_start);
-	}
+	/* These are in a non-obvious order, will fix when we have an iotree */
+#if defined(CONFIG_IOSAPIC)
+	iosapic_init();
 #endif
-
-	cache_init();
-
-	paging_init();
-
-	if((unsigned long)&init_task_union&(INIT_TASK_SIZE - 1)) {
-		printk("init_task_union not aligned.  Please recompile the kernel after changing the first line in arch/parisc/kernel/init_task.c from \n\"#define PAD 0\" to\n\"#define PAD 1\" or vice versa\n");
-		for(;;);
-	}
-
-
-#ifdef CONFIG_SERIAL_CONSOLE
-	/* nothing */
-#elif CONFIG_VT
-#if   defined(CONFIG_STI_CONSOLE)
-	conswitchp = &dummy_con;	/* we use take_over_console() later ! */
-#elif defined(CONFIG_IODC_CONSOLE)
-	conswitchp = &prom_con;		/* it's currently really "prom_con" */
-#elif defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
+#if defined(CONFIG_IOMMU_SBA)
+	sba_init();
 #endif
+#if defined(CONFIG_PCI_LBA)
+	lba_init();
 #endif
 
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- *	Get CPU information for use by procfs.
- */
-
-int get_cpuinfo(char *buffer)
-{
-	char		  *p = buffer;
-	int		  n;
+	/* CCIO before any potential subdevices */
+#if defined(CONFIG_IOMMU_CCIO)
+	ccio_init();
+#endif
 
-	for(n=0; n<boot_cpu_data.cpu_count; n++) {
-#ifdef CONFIG_SMP
-		if (!(cpu_online_map & (1<<n)))
-			continue;
-#endif
-		p += sprintf(p, "processor\t: %d\n"
-				"cpu family\t: PA-RISC %s\n",
-				n, boot_cpu_data.family_name);
-
-		p += sprintf(p, "cpu\t\t: %s\n",  boot_cpu_data.cpu_name );
-	
-		/* cpu MHz */
-		p += sprintf(p, "cpu MHz\t\t: %d.%06d\n",
-				 boot_cpu_data.cpu_hz / 1000000, 
-				 boot_cpu_data.cpu_hz % 1000000  );
-
-		p += sprintf(p, "model\t\t: %s\n"
-				"model name\t: %s\n",
-				boot_cpu_data.pdc.sys_model_name,
-				boot_cpu_data.model_name);
-
-		p += sprintf(p, "hversion\t: 0x%08x\n"
-			        "sversion\t: 0x%08x\n",
-				boot_cpu_data.hversion,
-				boot_cpu_data.sversion );
-
-		p += get_cache_info(p);
-		/* print cachesize info ? */
-		p += sprintf(p, "bogomips\t: %lu.%02lu\n",
-			     (loops_per_sec+2500)/500000,
-			     ((loops_per_sec+2500)/5000) % 100);
-	}
-	return p - buffer;
-}
+	/*
+	 * Need to register Asp & Wax before the EISA adapters for the IRQ
+	 * regions.  EISA must come before PCI to be sure it gets IRQ region
+	 * 0.
+	 */
+#if defined(CONFIG_GSC_LASI) || defined(CONFIG_GSC_WAX)
+	gsc_init();
+#endif
+#ifdef CONFIG_EISA
+	eisa_init();
+#endif
+#if defined(CONFIG_GSC_DINO)
+	dino_init();
 #endif
 
+#ifdef CONFIG_CHASSIS_LCD_LED
+	register_led_regions();	/* register LED port info in procfs */
+#endif
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/signal.c linux/arch/parisc/kernel/signal.c
--- linux.orig/arch/parisc/kernel/signal.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/parisc/kernel/signal.c	2002-08-12 22:14:18.000000000 +0000
@@ -26,20 +26,24 @@
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <asm/ucontext.h>
+#include <asm/rt_sigframe.h>
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 
 #define DEBUG_SIG 0
 
+#if DEBUG_SIG
+#define DBG(x)	printk x
+#else
+#define DBG(x)
+#endif
+
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-extern long sys_wait4 (int, int *, int, struct rusage *);
 int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
-		return -EFAULT;
 	if (from->si_code < 0)
 		return __copy_to_user(to, from, sizeof(siginfo_t));
 	else {
@@ -128,30 +132,15 @@
  * Do a signal return - restore sigcontext.
  */
 
-struct rt_sigframe {
-	unsigned int tramp[4];
-	struct siginfo info;
-	struct ucontext uc;
-};
-
 /* Trampoline for calling rt_sigreturn() */
 #define INSN_LDI_R25_0	 0x34190000 /* ldi  0,%r25 (in_syscall=0) */
 #define INSN_LDI_R25_1	 0x34190002 /* ldi  1,%r25 (in_syscall=1) */
 #define INSN_LDI_R20	 0x3414015a /* ldi  __NR_rt_sigreturn,%r20 */
 #define INSN_BLE_SR2_R0  0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
-#define INSN_NOP	 0x80000240 /* nop */
+#define INSN_NOP	 0x08000240 /* nop */
 /* For debugging */
 #define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
 
-/*
- * The 32-bit ABI wants at least 48 bytes for a function call frame:
- * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of
- * which Linux/parisc uses is sp-20 for the saved return pointer...)
- * Then, the stack pointer must be rounded to a cache line (64 bytes).
- */
-#define PARISC_RT_SIGFRAME_SIZE					\
-	(((sizeof(struct rt_sigframe) + 48) + 63) & -64)
-
 static long
 restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs)
 {
@@ -162,10 +151,7 @@
 	err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
 	err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
 	err |= __get_user(regs->sar, &sc->sc_sar);
-
-#if DEBUG_SIG
-	printk("restore_sigcontext: r28 is %ld\n", regs->gr[28]);
-#endif
+	DBG(("restore_sigcontext: r28 is %ld\n", regs->gr[28]));
 	return err;
 }
 
@@ -180,13 +166,8 @@
 	/* Unwind the user stack to get the rt_sigframe structure. */
 	frame = (struct rt_sigframe *)
 		(usp - PARISC_RT_SIGFRAME_SIZE);
-#if DEBUG_SIG
-	printk("in sys_rt_sigreturn, frame is %p\n", frame);
-#endif
+	DBG(("in sys_rt_sigreturn, frame is %p\n", frame));
 
-	/* Verify that it's a good sigcontext before using it */
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto give_sigsegv;
 	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 		goto give_sigsegv;
 
@@ -200,10 +181,7 @@
 	if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
 		goto give_sigsegv;
 
-#if DEBUG_SIG
-	printk("usp: %#08lx stack %p",
-	       usp, &frame->uc.uc_stack);
-#endif
+	DBG(("usp: %#08lx stack %p", usp, &frame->uc.uc_stack));
 
 	/* I don't know why everyone else assumes they can call this
            with a pointer to a stack_t on the kernel stack.  That
@@ -218,16 +196,14 @@
 	if (in_syscall)
 		regs->gr[31] = regs->iaoq[0];
 #if DEBUG_SIG
-	printk("returning to %#lx\n", regs->iaoq[0]);
-	printk("in sys_rt_sigreturn:\n");
+	DBG(("returning to %#lx\n", regs->iaoq[0]));
+	DBG(("in sys_rt_sigreturn:\n"));
 	show_regs(regs);
 #endif
 	return;
 
 give_sigsegv:
-#if DEBUG_SIG
-	printk("fuckup in sys_rt_sigreturn, sending SIGSEGV\n");
-#endif
+	DBG(("sys_rt_sigreturn sending SIGSEGV\n"));
 	si.si_signo = SIGSEGV;
 	si.si_errno = 0;
 	si.si_code = SI_KERNEL;
@@ -246,7 +222,7 @@
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
 	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
+		sp = current->sas_ss_sp; /* Stacks grow up! */
 
 	return (void *) sp; /* Stacks grow up.  Fun. */
 }
@@ -265,24 +241,22 @@
 		/* regs->iaoq is undefined in the syscall return path */
 		err |= __put_user(regs->gr[31], &sc->sc_iaoq[0]);
 		err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
-#if DEBUG_SIG
-		printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->gr[31], regs->gr[31]);
-#endif
+		err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
+		err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
+		DBG(("setup_sigcontext: iaoq %#lx/%#lx\n",
+			regs->gr[31], regs->gr[31]));
 	} else {
 		err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
 		err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
-#if DEBUG_SIG
-		printk("setup_sigcontext: iaoq %#lx/%#lx\n", regs->iaoq[0], regs->iaoq[1]);
-#endif
+		DBG(("setup_sigcontext: iaoq %#lx/%#lx\n", 
+			regs->iaoq[0], regs->iaoq[1]));
 	}
 
 	err |= __put_user(flags, &sc->sc_flags);
 	err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
 	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
 	err |= __put_user(regs->sar, &sc->sc_sar);
-#if DEBUG_SIG
-	printk("setup_sigcontext: r28 is %ld\n", regs->gr[28]);
-#endif
+	DBG(("setup_sigcontext: r28 is %ld\n", regs->gr[28]));
 
 	return err;
 }
@@ -297,22 +271,9 @@
 	int err = 0;
 
 	usp = regs->gr[30];
-	/* access_ok is broken, so do a simplistic "are we stomping on
-           kernel space" assertion. */
-	if (usp > PAGE_OFFSET) {
-		printk("setup_rt_frame: called on kernel space (usp=%#lx),  NOW YOU MUST DIE!!!\n",
-		       usp);
-		show_regs(regs);
-		while(1);
-	}
-		
 	frame = get_sigframe(ka, usp, sizeof(*frame));
-	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
 
-#if DEBUG_SIG
-	printk("setup_rt_frame 1: frame %p info %p\n", frame, info);
-#endif
+	DBG(("setup_rt_frame 1: frame %p info %p\n", frame, info));
 
 	err |= __copy_to_user(&frame->info, info, sizeof(siginfo_t));
 	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
@@ -337,8 +298,8 @@
 	{
 		int sid;
 		asm ("mfsp %%sr3,%0" : "=r" (sid));
-		printk("flushing 64 bytes at space %#x offset %p\n",
-		       sid, frame->tramp);
+		DBG(("flushing 64 bytes at space %#x offset %p\n",
+		       sid, frame->tramp));
 	}
 #endif
 
@@ -387,6 +348,7 @@
 	if (in_syscall)
 		regs->gr[31] = (HACK) haddr;
 	else {
+		regs->gr[0] = USER_PSW;
 		regs->iaoq[0] = (HACK) haddr | 3;
 		regs->iaoq[1] = regs->iaoq[0] + 4;
 	}
@@ -395,26 +357,20 @@
 	regs->gr[26] = sig;               /* signal number */
 	regs->gr[25] = (HACK) &frame->info; /* siginfo pointer */
 	regs->gr[24] = (HACK) &frame->uc;   /* ucontext pointer */
-#if DEBUG_SIG
-	printk("making sigreturn frame: %#lx + %#lx = %#lx\n",
+	DBG(("making sigreturn frame: %#lx + %#x = %#lx\n",
 	       regs->gr[30], PARISC_RT_SIGFRAME_SIZE,
-	       regs->gr[30] + PARISC_RT_SIGFRAME_SIZE);
-#endif
+	       regs->gr[30] + PARISC_RT_SIGFRAME_SIZE));
 	/* Raise the user stack pointer to make a proper call frame. */
 	regs->gr[30] = ((HACK) frame + PARISC_RT_SIGFRAME_SIZE);
 
-#if DEBUG_SIG
-	printk("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+	DBG(("SIG deliver (%s:%d): frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
 	       current->comm, current->pid, frame, regs->gr[30],
-	       regs->iaoq[0], regs->iaoq[1], rp);
-#endif
+	       regs->iaoq[0], regs->iaoq[1], rp));
 
 	return 1;
 
 give_sigsegv:
-#if DEBUG_SIG
-	printk("fuckup in setup_rt_frame, sending SIGSEGV\n");
-#endif
+	DBG(("setup_rt_frame sending SIGSEGV\n"));
 	if (sig == SIGSEGV)
 		ka->sa.sa_handler = SIG_DFL;
 	si.si_signo = SIGSEGV;
@@ -436,10 +392,9 @@
 	      siginfo_t *info, sigset_t *oldset,
 	      struct pt_regs *regs, int in_syscall)
 {
-#if DEBUG_SIG
-	printk("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",
-	       sig, ka, info, oldset, regs);
-#endif
+	DBG(("handle_signal(sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p)\n",
+	       sig, ka, info, oldset, regs));
+	
 	/* Set up the stack frame */
 	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
 		return 0;
@@ -468,16 +423,16 @@
  * registers).  As noted below, the syscall number gets restored for
  * us due to the magic of delayed branching.
  */
+
 asmlinkage int
 do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
 
-#if DEBUG_SIG
-	printk("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",
-	       oldset, regs, regs->sr[7], current->sigpending, in_syscall);
-#endif
+	DBG(("do_signal(oldset=0x%p, regs=0x%p, sr7 %#lx, pending %d, in_syscall=%d\n",
+	       oldset, regs, regs->sr[7], current->sigpending, in_syscall));
+
 	/* Everyone else checks to see if they are in kernel mode at
 	   this point and exits if that's the case.  I'm not sure why
 	   we would be called in that case, but for some reason we
@@ -486,9 +441,8 @@
 	if (!oldset)
 		oldset = &current->blocked;
 
-#if DEBUG_SIG
-	printk("do_signal: oldset %08lx:%08lx\n", oldset->sig[0], oldset->sig[1]);
-#endif
+	DBG(("do_signal: oldset %08lx:%08lx\n", 
+		oldset->sig[0], oldset->sig[1]));
 
 	for (;;) {
 		unsigned long signr;
@@ -496,10 +450,7 @@
 		spin_lock_irq(&current->sigmask_lock);
 		signr = dequeue_signal(&current->blocked, &info);
 		spin_unlock_irq(&current->sigmask_lock);
-#if DEBUG_SIG
-		printk("do_signal: signr=%ld, pid=%d\n", signr, current->pid);
-#endif
-
+		DBG(("do_signal: signr=%ld, pid=%d\n", signr, current->pid));
 		if (!signr)
 			break;
 
@@ -536,10 +487,9 @@
 		}
 
 		ka = &current->sig->action[signr-1];
-#if DEBUG_SIG
-		printk("sa_handler is %lx\n", ka->sa.sa_handler);
-#endif
-		if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_IGN) {
+		DBG(("sa_handler is %x\n", 
+			(unsigned int) ka->sa.sa_handler));
+		if (ka->sa.sa_handler == SIG_IGN) {
 			if (signr != SIGCHLD)
 				continue;
 			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
@@ -547,7 +497,7 @@
 			continue;
 		}
 
-		if ((unsigned long) ka->sa.sa_handler == (unsigned long) SIG_DFL) {
+		if (ka->sa.sa_handler == SIG_DFL) {
 			int exit_code = signr;
 
 			/* Init gets no signals it doesn't want.  */
@@ -591,17 +541,13 @@
 			/* Check the return code */
 			switch (regs->gr[28]) {
 			case -ERESTARTNOHAND:
-#if DEBUG_SIG
-				printk("ERESTARTNOHAND: returning -EINTR\n");
-#endif
+				DBG(("ERESTARTNOHAND: returning -EINTR\n"));
 				regs->gr[28] = -EINTR;
 				break;
 
 			case -ERESTARTSYS:
 				if (!(ka->sa.sa_flags & SA_RESTART)) {
-#if DEBUG_SIG
-					printk("ERESTARTSYS: putting -EINTR\n");
-#endif
+					DBG(("ERESTARTSYS: putting -EINTR\n"));
 					regs->gr[28] = -EINTR;
 					break;
 				}
@@ -620,9 +566,9 @@
 		   delivery failed, we need to continue to iterate in
 		   this loop so we can deliver the SIGSEGV... */
 		if (handle_signal(signr, ka, &info, oldset, regs, in_syscall)) {
-#if DEBUG_SIG
-			printk("Exiting do_signal (success), regs->gr[28] = %ld\n", regs->gr[28]);
-#endif
+			DBG((KERN_DEBUG
+				"Exiting do_signal (success), regs->gr[28] = %ld\n",
+				regs->gr[28]));
 			return 1;
 		}
 	}
@@ -642,8 +588,9 @@
 			regs->gr[28] = regs->orig_r28;
 		}
 	}
-#if DEBUG_SIG
-	printk("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", regs->gr[28]);
-#endif
+	
+	DBG(("Exiting do_signal (not delivered), regs->gr[28] = %ld\n", 
+		regs->gr[28]));
+
 	return 0;
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/signal32.c linux/arch/parisc/kernel/signal32.c
--- linux.orig/arch/parisc/kernel/signal32.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/signal32.c	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,213 @@
+/* mostly borrowed from kernel/signal.c */
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+
+#include <asm/uaccess.h>
+#include "sys32.h"
+
+struct k_sigaction32 {
+	struct sigaction32 sa;
+};
+
+typedef unsigned int old_sigset_t32;
+
+static int
+put_old_sigset32(old_sigset_t32 *up, old_sigset_t *set)
+{
+	old_sigset_t32 set32 = *set;
+	return put_user(set32, up);
+}
+
+static int
+get_old_segset32(old_sigset_t32 *up, old_sigset_t *set)
+{
+	old_sigset_t32 set32;
+	int r;
+
+	if ((r = get_user(set32, up)) == 0)
+		*set = set32;
+
+	return r;
+}
+
+long
+sys32_sigpending(old_sigset_t32 *set)
+{
+	extern long sys_sigpending(old_sigset_t *set);
+	old_sigset_t pending;
+	int ret;
+
+	KERNEL_SYSCALL(ret, sys_sigpending, &pending);
+
+	/* can't put_user an old_sigset_t -- it is too big */
+	if (put_old_sigset32(set, &pending))
+		return -EFAULT;
+
+	return ret;
+}
+
+int sys32_sigprocmask(int how, old_sigset_t32 *set, 
+				 old_sigset_t32 *oset)
+{
+	extern int sys_sigprocmask(int how, old_sigset_t *set, 
+				 old_sigset_t *oset);
+	old_sigset_t s;
+	int ret;
+
+	if (set && get_old_segset32 (set, &s))
+		return -EFAULT;
+	KERNEL_SYSCALL(ret, sys_sigprocmask, how, set ? &s : NULL, oset ? &s : NULL);
+	if (!ret && oset && put_old_sigset32(oset, &s))
+		return -EFAULT;
+	return ret;
+}
+
+static inline void
+sigset_32to64(sigset_t *s64, sigset_t32 *s32)
+{
+	s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
+}
+
+static inline void
+sigset_64to32(sigset_t32 *s32, sigset_t *s64)
+{
+	s32->sig[0] = s64->sig[0] & 0xffffffffUL;
+	s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
+}
+
+static int
+put_sigset32(sigset_t32 *up, sigset_t *set, size_t sz)
+{
+	sigset_t32 s;
+
+	if (sz != sizeof *set) panic("put_sigset32()");
+	sigset_64to32(&s, set);
+
+	return copy_to_user(up, &s, sizeof s);
+}
+
+static int
+get_sigset32(sigset_t32 *up, sigset_t *set, size_t sz)
+{
+	sigset_t32 s;
+	int r;
+
+	if (sz != sizeof *set) panic("put_sigset32()");
+
+	if ((r = copy_from_user(&s, up, sz)) == 0) {
+		sigset_32to64(set, &s);
+	}
+
+	return r;
+}
+
+int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset,
+				    unsigned int sigsetsize)
+{
+	extern long sys_rt_sigprocmask(int how,
+				    sigset_t *set, sigset_t *oset,
+				   size_t sigsetsize);
+	sigset_t old_set, new_set;
+	int ret;
+
+	if (set && get_sigset32(set, &new_set, sigsetsize))
+		return -EFAULT;
+	
+	KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? &new_set : NULL,
+				 oset ? &old_set : NULL, sigsetsize);
+
+	if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
+		return -EFAULT;
+
+	return ret;
+}
+
+
+int sys32_rt_sigpending(sigset_t32 *uset, unsigned int sigsetsize)
+{
+	int ret;
+	sigset_t set;
+	extern long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
+
+	KERNEL_SYSCALL(ret, sys_rt_sigpending, &set, sigsetsize);
+
+	if (!ret && put_sigset32(uset, &set, sigsetsize))
+		return -EFAULT;
+
+	return ret;
+}
+
+long
+sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact,
+                 size_t sigsetsize)
+{
+	struct k_sigaction32 new_sa32, old_sa32;
+	struct k_sigaction new_sa, old_sa;
+	int ret = -EINVAL;
+
+	if (act) {
+		if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
+			return -EFAULT;
+		new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
+		new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
+		sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
+
+	if (!ret && oact) {
+		sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
+		old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
+		old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
+		if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+typedef struct {
+	unsigned int ss_sp;
+	int ss_flags;
+	__kernel_size_t32 ss_size;
+} stack_t32;
+
+int 
+do_sigaltstack32 (const stack_t32 *uss32, stack_t32 *uoss32, unsigned long sp)
+{
+	stack_t32 ss32, oss32;
+	stack_t ss, oss;
+	stack_t *ssp = NULL, *ossp = NULL;
+	int ret;
+
+	if (uss32) {
+		if (copy_from_user(&ss32, uss32, sizeof ss32))
+			return -EFAULT;
+
+		ss.ss_sp = (void *)ss32.ss_sp;
+		ss.ss_flags = ss32.ss_flags;
+		ss.ss_size = ss32.ss_size;
+
+		ssp = &ss;
+	}
+
+	if (uoss32)
+		ossp = &oss;
+
+	KERNEL_SYSCALL(ret, do_sigaltstack, ssp, ossp, sp);
+
+	if (!ret && uoss32) {
+		oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
+		oss32.ss_flags = oss.ss_flags;
+		oss32.ss_size = oss.ss_size;
+		if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
+			return -EFAULT;
+	}
+
+	return ret;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/smp.c linux/arch/parisc/kernel/smp.c
--- linux.orig/arch/parisc/kernel/smp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/smp.c	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,794 @@
+/*
+** SMP Support
+**
+** Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+** Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
+** Copyright (C) 2001 Grant Grundler <grundler@parisc-linux.org>
+** 
+** Lots of stuff stolen from arch/alpha/kernel/smp.c
+** ...and then parisc stole from arch/ia64/kernel/smp.c. Thanks David! :^)
+**
+** Thanks to John Curry and Ullas Ponnadi. I learned alot from their work.
+** -grant (1/12/2001)
+**
+**	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.
+*/
+#define __KERNEL_SYSCALLS__
+#undef ENTRY_SYS_CPUS	/* syscall support for iCOD-like functionality */
+
+#include <linux/autoconf.h>
+
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/kernel_stat.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <asm/bitops.h>
+#include <asm/current.h>
+#include <asm/delay.h>
+#include <asm/pgalloc.h>	/* for flush_tlb_all() proto/macro */
+
+#include <asm/io.h>
+#include <asm/irq.h>		/* for CPU_IRQ_REGION and friends */
+#include <asm/mmu_context.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/processor.h>
+#include <asm/ptrace.h>
+#include <asm/unistd.h>
+
+#define kDEBUG 0
+
+spinlock_t pa_dbit_lock = SPIN_LOCK_UNLOCKED;
+
+spinlock_t smp_lock = SPIN_LOCK_UNLOCKED;
+
+volatile struct task_struct *smp_init_current_idle_task;
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+
+static volatile int smp_commenced = 0;   /* Set when the idlers are all forked */
+static volatile int cpu_now_booting = 0;      /* track which CPU is booting */
+volatile unsigned long cpu_online_map = 0;   /* Bitmap of online CPUs */
+#define IS_LOGGED_IN(cpunum) (test_bit(cpunum, (atomic_t *)&cpu_online_map))
+
+int smp_num_cpus = 1;
+int smp_threads_ready = 0;
+static int max_cpus = -1;			     /* Command line */
+struct smp_call_struct {
+	void (*func) (void *info);
+	void *info;
+	long wait;
+	atomic_t unstarted_count;
+	atomic_t unfinished_count;
+};
+static volatile struct smp_call_struct *smp_call_function_data;
+
+enum ipi_message_type {
+	IPI_NOP=0,
+	IPI_RESCHEDULE=1,
+	IPI_CALL_FUNC,
+	IPI_CPU_START,
+	IPI_CPU_STOP,
+	IPI_CPU_TEST
+};
+
+
+/********** SMP inter processor interrupt and communication routines */
+
+#undef PER_CPU_IRQ_REGION
+#ifdef PER_CPU_IRQ_REGION
+/* XXX REVISIT Ignore for now.
+**    *May* need this "hook" to register IPI handler
+**    once we have perCPU ExtIntr switch tables.
+*/
+static void
+ipi_init(int cpuid)
+{
+
+	/* If CPU is present ... */
+#ifdef ENTRY_SYS_CPUS
+	/* *and* running (not stopped) ... */
+#error iCOD support wants state checked here.
+#endif
+
+#error verify IRQ_OFFSET(IPI_IRQ) is ipi_interrupt() in new IRQ region
+
+	if(IS_LOGGED_IN(cpuid) )
+	{
+		switch_to_idle_task(current);
+	}
+
+	return;
+}
+#endif
+
+
+/*
+** Yoink this CPU from the runnable list... 
+**
+*/
+static void
+halt_processor(void) 
+{
+#ifdef ENTRY_SYS_CPUS
+#error halt_processor() needs rework
+/*
+** o migrate I/O interrupts off this CPU.
+** o leave IPI enabled - __cli() will disable IPI.
+** o leave CPU in online map - just change the state
+*/
+	cpu_data[this_cpu].state = STATE_STOPPED;
+	mark_bh(IPI_BH);
+#else
+	/* REVISIT : redirect I/O Interrupts to another CPU? */
+	/* REVISIT : does PM *know* this CPU isn't available? */
+	clear_bit(smp_processor_id(), (void *)&cpu_online_map);
+	__cli();
+	for (;;)
+		;
+#endif
+}
+
+
+void
+ipi_interrupt(int irq, void *dev_id, struct pt_regs *regs) 
+{
+	int this_cpu = smp_processor_id();
+	struct cpuinfo_parisc *p = &cpu_data[this_cpu];
+	unsigned long ops;
+	unsigned long flags;
+
+	/* Count this now; we may make a call that never returns. */
+	p->ipi_count++;
+
+	mb();	/* Order interrupt and bit testing. */
+
+	for (;;) {
+		spin_lock_irqsave(&(p->lock),flags);
+		ops = p->pending_ipi;
+		p->pending_ipi = 0;
+		spin_unlock_irqrestore(&(p->lock),flags);
+
+		mb(); /* Order bit clearing and data access. */
+
+		if (!ops)
+		    break;
+
+		while (ops) {
+			unsigned long which = ffz(~ops);
+
+			switch (which) {
+			case IPI_RESCHEDULE:
+#if (kDEBUG>=100)
+				printk(KERN_DEBUG "CPU%d IPI_RESCHEDULE\n",this_cpu);
+#endif /* kDEBUG */
+				ops &= ~(1 << IPI_RESCHEDULE);
+				/*
+				 * Reschedule callback.  Everything to be
+				 * done is done by the interrupt return path.
+				 */
+				break;
+
+			case IPI_CALL_FUNC:
+#if (kDEBUG>=100)
+				printk(KERN_DEBUG "CPU%d IPI_CALL_FUNC\n",this_cpu);
+#endif /* kDEBUG */
+				ops &= ~(1 << IPI_CALL_FUNC);
+				{
+					volatile struct smp_call_struct *data;
+					void (*func)(void *info);
+					void *info;
+					int wait;
+
+					data = smp_call_function_data;
+					func = data->func;
+					info = data->info;
+					wait = data->wait;
+
+					mb();
+					atomic_dec ((atomic_t *)&data->unstarted_count);
+
+					/* At this point, *data can't
+					 * be relied upon.
+					 */
+
+					(*func)(info);
+
+					/* Notify the sending CPU that the
+					 * task is done.
+					 */
+					mb();
+					if (wait)
+						atomic_dec ((atomic_t *)&data->unfinished_count);
+				}
+				break;
+
+			case IPI_CPU_START:
+#if (kDEBUG>=100)
+				printk(KERN_DEBUG "CPU%d IPI_CPU_START\n",this_cpu);
+#endif /* kDEBUG */
+				ops &= ~(1 << IPI_CPU_START);
+#ifdef ENTRY_SYS_CPUS
+				p->state = STATE_RUNNING;
+#endif
+				break;
+
+			case IPI_CPU_STOP:
+#if (kDEBUG>=100)
+				printk(KERN_DEBUG "CPU%d IPI_CPU_STOP\n",this_cpu);
+#endif /* kDEBUG */
+				ops &= ~(1 << IPI_CPU_STOP);
+#ifdef ENTRY_SYS_CPUS
+#else
+				halt_processor();
+#endif
+				break;
+
+			case IPI_CPU_TEST:
+#if (kDEBUG>=100)
+				printk(KERN_DEBUG "CPU%d is alive!\n",this_cpu);
+#endif /* kDEBUG */
+				ops &= ~(1 << IPI_CPU_TEST);
+				break;
+
+			default:
+				printk(KERN_CRIT "Unknown IPI num on CPU%d: %lu\n",
+					this_cpu, which);
+				ops &= ~(1 << which);
+				return;
+			} /* Switch */
+		} /* while (ops) */
+	}
+	return;
+}
+
+
+static inline void
+ipi_send(int cpu, enum ipi_message_type op)
+{
+	struct cpuinfo_parisc *p = &cpu_data[cpu];
+	unsigned long flags;
+
+	spin_lock_irqsave(&(p->lock),flags);
+	p->pending_ipi |= 1 << op;
+	__raw_writel(IRQ_OFFSET(IPI_IRQ), cpu_data[cpu].hpa);
+	spin_unlock_irqrestore(&(p->lock),flags);
+}
+
+
+static inline void
+send_IPI_single(int dest_cpu, enum ipi_message_type op)
+{
+	if (dest_cpu == NO_PROC_ID) {
+		BUG();
+		return;
+	}
+
+	ipi_send(dest_cpu, op);
+}
+
+static inline void
+send_IPI_allbutself(enum ipi_message_type op)
+{
+	int i;
+	
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (i != smp_processor_id())
+			send_IPI_single(i, op);
+	}
+}
+
+inline void 
+smp_send_stop(void)	{ send_IPI_allbutself(IPI_CPU_STOP); }
+
+static inline void
+smp_send_start(void)	{ send_IPI_allbutself(IPI_CPU_START); }
+
+void 
+smp_send_reschedule(int cpu) { send_IPI_single(cpu, IPI_RESCHEDULE); }
+
+
+/**
+ * Run a function on all other CPUs.
+ *  <func>	The function to run. This must be fast and non-blocking.
+ *  <info>	An arbitrary pointer to pass to the function.
+ *  <retry>	If true, keep retrying until ready.
+ *  <wait>	If true, wait until function has completed on other CPUs.
+ *  [RETURNS]   0 on success, else a negative status code.
+ *
+ * Does not return until remote CPUs are nearly ready to execute <func>
+ * or have executed.
+ */
+
+int
+smp_call_function (void (*func) (void *info), void *info, int retry, int wait)
+{
+	struct smp_call_struct data;
+	long timeout;
+	static spinlock_t lock = SPIN_LOCK_UNLOCKED;
+	
+	data.func = func;
+	data.info = info;
+	data.wait = wait;
+	atomic_set(&data.unstarted_count, smp_num_cpus - 1);
+	atomic_set(&data.unfinished_count, smp_num_cpus - 1);
+
+	if (retry) {
+		spin_lock (&lock);
+		while (smp_call_function_data != 0)
+			barrier();
+	}
+	else {
+		spin_lock (&lock);
+		if (smp_call_function_data) {
+			spin_unlock (&lock);
+			return -EBUSY;
+		}
+	}
+
+	smp_call_function_data = &data;
+	spin_unlock (&lock);
+	
+	/*  Send a message to all other CPUs and wait for them to respond  */
+	send_IPI_allbutself(IPI_CALL_FUNC);
+
+	/*  Wait for response  */
+	timeout = jiffies + HZ;
+	while ( (atomic_read (&data.unstarted_count) > 0) &&
+		time_before (jiffies, timeout) )
+		barrier ();
+
+	/* We either got one or timed out. Release the lock */
+
+	mb();
+	smp_call_function_data = NULL;
+	if (atomic_read (&data.unstarted_count) > 0) {
+		printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d)\n",
+		      smp_processor_id());
+		return -ETIMEDOUT;
+	}
+
+	while (wait && atomic_read (&data.unfinished_count) > 0)
+			barrier ();
+
+	return 0;
+}
+
+
+
+/*
+ *	Setup routine for controlling SMP activation
+ *
+ *	Command-line option of "nosmp" or "maxcpus=0" will disable SMP
+ *	activation entirely (the MPS table probe still happens, though).
+ *
+ *	Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
+ *	greater than 0, limits the maximum number of CPUs activated in
+ *	SMP mode to <NUM>.
+ */
+
+static int __init nosmp(char *str)
+{
+	max_cpus = 0;
+	return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
+{
+	get_option(&str, &max_cpus);
+	return 1;
+}
+
+__setup("maxcpus=", maxcpus);
+
+/*
+ * Flush all other CPU's tlb and then mine.  Do this with smp_call_function()
+ * as we want to ensure all TLB's flushed before proceeding.
+ */
+
+extern void flush_tlb_all_local(void);
+
+void
+smp_flush_tlb_all(void)
+{
+	smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
+	flush_tlb_all_local();
+}
+
+
+void 
+smp_do_timer(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	struct cpuinfo_parisc *data = &cpu_data[cpu];
+
+        if (!--data->prof_counter) {
+		data->prof_counter = data->prof_multiplier;
+		update_process_times(user_mode(regs));
+	}
+}
+
+/*
+ * Called by secondaries to update state and initialize CPU registers.
+ */
+static void __init
+smp_cpu_init(int cpunum)
+{
+	extern int init_per_cpu(int);  /* arch/parisc/kernel/setup.c */
+	extern void init_IRQ(void);    /* arch/parisc/kernel/irq.c */
+
+	/* Set modes and Enable floating point coprocessor */
+	(void) init_per_cpu(cpunum);
+
+	disable_sr_hashing();
+
+	mb();
+
+	/* Well, support 2.4 linux scheme as well. */
+	if (test_and_set_bit(cpunum, (unsigned long *) (&cpu_online_map)))
+	{
+		extern void machine_halt(void); /* arch/parisc.../process.c */
+
+		printk(KERN_CRIT "CPU#%d already initialized!\n", cpunum);
+		machine_halt();
+	}  
+
+	/* Initialise the idle task for this CPU */
+	atomic_inc(&init_mm.mm_count);
+	current->active_mm = &init_mm;
+	if(current->mm)
+		BUG();
+	enter_lazy_tlb(&init_mm, current, cpunum);
+
+	init_IRQ();   /* make sure no IRQ's are enabled or pending */
+}
+
+
+/*
+ * Slaves start using C here. Indirectly called from smp_slave_stext.
+ * Do what start_kernel() and main() do for boot strap processor (aka monarch)
+ */
+void __init smp_callin(void)
+{
+	extern void cpu_idle(void);	/* arch/parisc/kernel/process.c */
+	int slave_id = cpu_now_booting;
+#if 0
+	void *istack;
+#endif
+
+	smp_cpu_init(slave_id);
+
+#if 0	/* NOT WORKING YET - see entry.S */
+	istack = (void *)__get_free_pages(GFP_KERNEL,ISTACK_ORDER);
+	if (istack == NULL) {
+	    printk(KERN_CRIT "Failed to allocate interrupt stack for cpu %d\n",slave_id);
+	    BUG();
+	}
+	mtctl(istack,31);
+#endif
+
+	flush_cache_all_local(); /* start with known state */
+	flush_tlb_all_local();
+
+	local_irq_enable();  /* Interrupts have been off until now */
+
+	/* Slaves wait here until Big Poppa daddy say "jump" */
+	mb();	/* PARANOID */
+	while (!smp_commenced) ;
+	mb();	/* PARANOID */
+
+	cpu_idle();      /* Wait for timer to schedule some work */
+
+	/* NOTREACHED */
+	panic("smp_callin() AAAAaaaaahhhh....\n");
+}
+
+/*
+ * Create the idle task for a new Slave CPU.  DO NOT use kernel_thread()
+ * because that could end up calling schedule(). If it did, the new idle
+ * task could get scheduled before we had a chance to remove it from the
+ * run-queue...
+ */
+static int fork_by_hand(void)
+{
+	struct pt_regs regs;  
+
+	/*
+	 * don't care about the regs settings since
+	 * we'll never reschedule the forked task.
+	 */
+	return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+}
+
+
+/*
+ * Bring one cpu online.
+ */
+static int smp_boot_one_cpu(int cpuid, int cpunum)
+{
+	struct task_struct *idle;
+	long timeout;
+
+	/* 
+	 * Create an idle task for this CPU.  Note the address wed* give 
+	 * to kernel_thread is irrelevant -- it's going to start
+	 * where OS_BOOT_RENDEVZ vector in SAL says to start.  But
+	 * this gets all the other task-y sort of data structures set
+	 * up like we wish.   We need to pull the just created idle task 
+	 * off the run queue and stuff it into the init_tasks[] array.  
+	 * Sheesh . . .
+	 */
+
+	if (fork_by_hand() < 0) 
+		panic("SMP: fork failed for CPU:%d", cpuid);
+	
+	idle = init_task.prev_task;
+	if (!idle)
+		panic("SMP: No idle process for CPU:%d", cpuid);
+
+	task_set_cpu(idle, cpunum);	/* manually schedule idle task */
+	del_from_runqueue(idle);
+	unhash_process(idle);
+	init_tasks[cpunum] = idle;
+
+	/* Let _start know what logical CPU we're booting
+	** (offset into init_tasks[],cpu_data[])
+	*/
+	cpu_now_booting = cpunum;
+
+	/* 
+	** boot strap code needs to know the task address since
+	** it also contains the process stack.
+	*/
+	smp_init_current_idle_task = idle ;
+	mb();
+
+	/*
+	** This gets PDC to release the CPU from a very tight loop.
+	** See MEM_RENDEZ comments in head.S.
+	*/
+	__raw_writel(IRQ_OFFSET(TIMER_IRQ), cpu_data[cpunum].hpa);
+	mb();
+
+	/* 
+	 * OK, wait a bit for that CPU to finish staggering about. 
+	 * Slave will set a bit when it reaches smp_cpu_init() and then
+	 * wait for smp_commenced to be 1.
+	 * Once we see the bit change, we can move on.
+	 */
+	for (timeout = 0; timeout < 10000; timeout++) {
+		if(IS_LOGGED_IN(cpunum)) {
+			/* Which implies Slave has started up */
+			cpu_now_booting = 0;
+			smp_init_current_idle_task = NULL;
+			goto alive ;
+		}
+		udelay(100);
+		barrier();
+	}
+
+	init_tasks[cpunum] = NULL;
+	free_task_struct(idle);
+
+	printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid);
+	return -1;
+
+alive:
+	/* Remember the Slave data */
+#if (kDEBUG>=100)
+	printk(KERN_DEBUG "SMP: CPU:%d (num %d) came alive after %ld _us\n",
+		cpuid,  cpunum, timeout * 100);
+#endif /* kDEBUG */
+#ifdef ENTRY_SYS_CPUS
+	cpu_data[cpunum].state = STATE_RUNNING;
+#endif
+	return 0;
+}
+
+
+
+
+/*
+** inventory.c:do_inventory() has already 'discovered' the additional CPU's.
+** We are ready to wrest them from PDC's control now.
+** Called by smp_init bring all the secondaries online and hold them.  
+**
+** o Setup of the IPI irq handler is done in irq.c.
+** o MEM_RENDEZ is initialzed in head.S:stext()
+**
+*/
+void __init smp_boot_cpus(void)
+{
+	int i, cpu_count = 1;
+	unsigned long bogosum = loops_per_jiffy; /* Count Monarch */
+
+	/* REVISIT - assumes first CPU reported by PAT PDC is BSP */
+	int bootstrap_processor=cpu_data[0].cpuid;	/* CPU ID of BSP */
+
+	/* Setup BSP mappings */
+	printk(KERN_DEBUG "SMP: bootstrap CPU ID is %d\n",bootstrap_processor);
+	init_task.processor = bootstrap_processor; 
+	current->processor = bootstrap_processor;
+	cpu_online_map = 1 << bootstrap_processor; /* Mark Boostrap processor as present */
+	current->active_mm = &init_mm;
+
+#ifdef ENTRY_SYS_CPUS
+	cpu_data[0].state = STATE_RUNNING;
+#endif
+
+	/* Nothing to do when told not to.  */
+	if (max_cpus == 0) {
+		printk(KERN_INFO "SMP mode deactivated.\n");
+		return;
+	}
+
+	if (max_cpus != -1) 
+		printk(KERN_INFO "Limiting CPUs to %d\n", max_cpus);
+
+	/* We found more than one CPU.... */
+	if (boot_cpu_data.cpu_count > 1) {
+
+		for (i = 0; i < NR_CPUS; i++) {
+			if (cpu_data[i].cpuid == NO_PROC_ID || 
+			    cpu_data[i].cpuid == bootstrap_processor)
+				continue;
+
+			if (smp_boot_one_cpu(cpu_data[i].cpuid, cpu_count) < 0)
+				continue;
+
+			bogosum += loops_per_jiffy;
+			cpu_count++; /* Count good CPUs only... */
+
+			/* Bail when we've started as many CPUS as told to */
+			if (cpu_count == max_cpus)
+				break;
+		}
+	}
+	if (cpu_count == 1) {
+		printk(KERN_INFO "SMP: Bootstrap processor only.\n");
+	}
+
+	printk(KERN_INFO "SMP: Total %d of %d processors activated "
+	       "(%lu.%02lu BogoMIPS noticed).\n",
+	       cpu_count, boot_cpu_data.cpu_count, (bogosum + 25) / 5000,
+	       ((bogosum + 25) / 50) % 100);
+
+	smp_num_cpus = cpu_count;
+#ifdef PER_CPU_IRQ_REGION
+	ipi_init();
+#endif
+	return;
+}
+
+/* 
+ * Called from main.c by Monarch Processor.
+ * After this, any CPU can schedule any task.
+ */
+void smp_commence(void)
+{
+	smp_commenced = 1;
+	mb();
+	return;
+}
+
+#ifdef ENTRY_SYS_CPUS
+/* Code goes along with:
+**    entry.s:        ENTRY_NAME(sys_cpus)   / * 215, for cpu stat * /
+*/
+int sys_cpus(int argc, char **argv)
+{
+	int i,j=0;
+	extern int current_pid(int cpu);
+
+	if( argc > 2 ) {
+		printk("sys_cpus:Only one argument supported\n");
+		return (-1);
+	}
+	if ( argc == 1 ){
+	
+#ifdef DUMP_MORE_STATE
+		for(i=0; i<NR_CPUS; i++) {
+			int cpus_per_line = 4;
+			if(IS_LOGGED_IN(i)) {
+				if (j++ % cpus_per_line)
+					printk(" %3d",i);
+				else
+					printk("\n %3d",i);
+			}
+		}
+		printk("\n"); 
+#else
+	    	printk("\n 0\n"); 
+#endif
+	} else if((argc==2) && !(strcmp(argv[1],"-l"))) {
+		printk("\nCPUSTATE  TASK CPUNUM CPUID HARDCPU(HPA)\n");
+#ifdef DUMP_MORE_STATE
+		for(i=0;i<NR_CPUS;i++) {
+			if (!IS_LOGGED_IN(i))
+				continue;
+			if (cpu_data[i].cpuid != NO_PROC_ID) {
+				switch(cpu_data[i].state) {
+					case STATE_RENDEZVOUS:
+						printk("RENDEZVS ");
+						break;
+					case STATE_RUNNING:
+						printk((current_pid(i)!=0) ? "RUNNING  " : "IDLING   ");
+						break;
+					case STATE_STOPPED:
+						printk("STOPPED  ");
+						break;
+					case STATE_HALTED:
+						printk("HALTED   ");
+						break;
+					default:
+						printk("%08x?", cpu_data[i].state);
+						break;
+				}
+				if(IS_LOGGED_IN(i)) {
+					printk(" %4d",current_pid(i));
+				}	
+				printk(" %6d",cpu_number_map(i));
+				printk(" %5d",i);
+				printk(" 0x%lx\n",cpu_data[i].hpa);
+			}	
+		}
+#else
+		printk("\n%s  %4d      0     0 --------",
+			(current->pid)?"RUNNING ": "IDLING  ",current->pid); 
+#endif
+	} else if ((argc==2) && !(strcmp(argv[1],"-s"))) { 
+#ifdef DUMP_MORE_STATE
+     		printk("\nCPUSTATE   CPUID\n");
+		for (i=0;i<NR_CPUS;i++) {
+			if (!IS_LOGGED_IN(i))
+				continue;
+			if (cpu_data[i].cpuid != NO_PROC_ID) {
+				switch(cpu_data[i].state) {
+					case STATE_RENDEZVOUS:
+						printk("RENDEZVS");break;
+					case STATE_RUNNING:
+						printk((current_pid(i)!=0) ? "RUNNING " : "IDLING");
+						break;
+					case STATE_STOPPED:
+						printk("STOPPED ");break;
+					case STATE_HALTED:
+						printk("HALTED  ");break;
+					default:
+				}
+				printk("  %5d\n",i);
+			}	
+		}
+#else
+		printk("\n%s    CPU0",(current->pid==0)?"RUNNING ":"IDLING  "); 
+#endif
+	} else {
+		printk("sys_cpus:Unknown request\n");
+		return (-1);
+	}
+	return 0;
+}
+#endif /* ENTRY_SYS_CPUS */
+
+#ifdef CONFIG_PROC_FS
+int __init
+setup_profiling_timer(unsigned int multiplier)
+{
+	return -EINVAL;
+}
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/superio.c linux/arch/parisc/kernel/superio.c
--- linux.orig/arch/parisc/kernel/superio.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/superio.c	2002-08-12 22:14:21.000000000 +0000
@@ -0,0 +1,543 @@
+/*      National Semiconductor NS87560UBD Super I/O controller used in
+ *      HP [BCJ]x000 workstations.
+ *
+ *      This chip is a horrid piece of engineering, and National
+ *      denies any knowledge of its existence. Thus no datasheet is
+ *      available off www.national.com. 
+ *
+ *	(C) Copyright 2000 Linuxcare, Inc.
+ * 	(C) Copyright 2000 Linuxcare Canada, Inc.
+ *	(C) Copyright 2000 Martin K. Petersen <mkp@linuxcare.com>
+ * 	(C) Copyright 2000 Alex deVries <alex@linuxcare.com>
+ *      (C) Copyright 2001 John Marvin <jsm@fc.hp.com>
+ *
+ *	This program is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU General Public License as
+ *	published by the Free Software Foundation; either version 2 of
+ *	the License, or (at your option) any later version.  
+ *
+ *	The initial version of this is by Martin Peterson.  Alex deVries
+ *	has spent a bit of time trying to coax it into working.
+ *
+ *      Major changes to get basic interrupt infrastructure working to
+ *      hopefully be able to support all SuperIO devices. Currently
+ *      works with serial. -- John Marvin <jsm@fc.hp.com>
+ */
+
+
+/* NOTES:
+ * 
+ * Function 0 is an IDE controller. It is identical to a PC87415 IDE
+ * controller (and identifies itself as such).
+ *
+ * Function 1 is a "Legacy I/O" controller. Under this function is a
+ * whole mess of legacy I/O peripherals. Of course, HP hasn't enabled
+ * all the functionality in hardware, but the following is available:
+ *
+ *      Two 16550A compatible serial controllers
+ *      An IEEE 1284 compatible parallel port
+ *      A floppy disk controller
+ *
+ * Function 2 is a USB controller.
+ *
+ * We must be incredibly careful during initialization.  Since all
+ * interrupts are routed through function 1 (which is not allowed by
+ * the PCI spec), we need to program the PICs on the legacy I/O port
+ * *before* we attempt to set up IDE and USB.  @#$!&
+ *
+ * According to HP, devices are only enabled by firmware if they have
+ * a physical device connected.
+ *
+ * Configuration register bits:
+ *     0x5A: FDC, SP1, IDE1, SP2, IDE2, PAR, Reserved, P92
+ *     0x5B: RTC, 8259, 8254, DMA1, DMA2, KBC, P61, APM
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/serial.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/parport.h>
+#include <linux/parport_pc.h>
+#include <linux/serial_reg.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/gsc.h>
+#include <asm/irq.h>
+#include <asm/superio.h>
+
+static struct superio_device sio_dev = {
+	iosapic_irq: -1
+};
+
+
+#undef DEBUG_INIT
+
+void
+superio_inform_irq(int irq)
+{
+    if (sio_dev.iosapic_irq != -1) {
+	printk(KERN_ERR "SuperIO: superio_inform_irq called twice! (more than one SuperIO?)\n");
+	BUG();
+	return;
+    }
+
+    sio_dev.iosapic_irq = irq;
+}
+
+static void
+superio_interrupt(int irq, void *devp, struct pt_regs *regs)
+{
+	struct superio_device *sio = (struct superio_device *)devp;
+	u8 results;
+	u8 local_irq;
+
+	/* Poll the 8259 to see if there's an interrupt. */
+	outb (OCW3_POLL,IC_PIC1+0);
+
+	results = inb(IC_PIC1+0);
+
+	if ((results & 0x80) == 0) {
+#ifndef CONFIG_SMP
+		/* HACK: need to investigate why this happens if SMP enabled */
+		BUG(); /* This shouldn't happen */
+#endif
+		return;
+	}
+
+	/* Check to see which device is interrupting */
+
+	local_irq = results & 0x0f;
+
+	if (local_irq == 2 || local_irq > 7) {
+		printk(KERN_ERR "SuperIO: slave interrupted!\n");
+		BUG();
+		return;
+	}
+
+	if (local_irq == 7) {
+
+		/* Could be spurious. Check in service bits */
+
+		outb(OCW3_ISR,IC_PIC1+0);
+		results = inb(IC_PIC1+0);
+		if ((results & 0x80) == 0) { /* if ISR7 not set: spurious */
+			printk(KERN_WARNING "SuperIO: spurious interrupt!\n");
+			return;
+		}
+	}
+
+	/* Call the appropriate device's interrupt */
+
+	do_irq(&sio->irq_region->action[local_irq],
+		sio->irq_region->data.irqbase + local_irq,
+		regs);
+
+	/* set EOI */
+
+	outb((OCW2_SEOI|local_irq),IC_PIC1 + 0);
+	return;
+}
+
+/* Initialize Super I/O device */
+
+static void __devinit
+superio_init(struct superio_device *sio)
+{
+	struct pci_dev *pdev = sio->lio_pdev;
+	u16 word;
+	u8  i;
+
+	if (!pdev || sio->iosapic_irq == -1) {
+		printk(KERN_ERR "All SuperIO functions not found!\n");
+		BUG();
+		return;
+	}
+
+	printk (KERN_INFO "SuperIO: Found NS87560 Legacy I/O device at %s (IRQ %i) \n",
+		pdev->slot_name,sio->iosapic_irq);
+
+	/* Find our I/O devices */
+	pci_read_config_word (pdev, SIO_SP1BAR, &sio->sp1_base);
+	sio->sp1_base &= ~1;
+	printk (KERN_INFO "SuperIO: Serial port 1 at 0x%x\n", sio->sp1_base);
+
+	pci_read_config_word (pdev, SIO_SP2BAR, &sio->sp2_base);
+	sio->sp2_base &= ~1;
+	printk (KERN_INFO "SuperIO: Serial port 2 at 0x%x\n", sio->sp2_base);
+
+	pci_read_config_word (pdev, SIO_PPBAR, &sio->pp_base);
+	sio->pp_base &= ~1;
+	printk (KERN_INFO "SuperIO: Parallel port at 0x%x\n", sio->pp_base);
+
+	pci_read_config_word (pdev, SIO_FDCBAR, &sio->fdc_base);
+	sio->fdc_base &= ~1;
+	printk (KERN_INFO "SuperIO: Floppy controller at 0x%x\n", sio->fdc_base);
+	pci_read_config_word (pdev, SIO_ACPIBAR, &sio->acpi_base);
+	sio->acpi_base &= ~1;
+	printk (KERN_INFO "SuperIO: ACPI at 0x%x\n", sio->acpi_base);
+
+	request_region (IC_PIC1, 0x1f, "pic1");
+	request_region (IC_PIC2, 0x1f, "pic2");
+	request_region (sio->acpi_base, 0x1f, "acpi");
+
+	/* Enable the legacy I/O function */
+        pci_read_config_word (pdev, PCI_COMMAND, &word);
+	word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO;
+	pci_write_config_word (pdev, PCI_COMMAND, word);
+	pci_set_master (pdev);
+
+	/* Next project is programming the onboard interrupt
+	 * controllers.  PDC hasn't done this for us, since it's using
+	 * polled I/O.
+	 */
+
+	/* Set PIC interrupts to edge triggered */
+	pci_write_config_byte (pdev, TRIGGER_1, 0x0);
+	pci_write_config_byte (pdev, TRIGGER_2, 0x0);
+
+	/* Disable all interrupt routing */
+	for (i = IR_LOW ; i < IR_HIGH ; i++)
+		pci_write_config_byte (pdev, i, 0x0);
+
+	/* PIC1 Initialization Command Word register programming */
+	outb (0x11,IC_PIC1+0);	/* ICW1: ICW4 write req | ICW1 */
+	outb (0x00,IC_PIC1+1);	/* ICW2: N/A */
+	outb (0x04,IC_PIC1+1);	/* ICW3: Cascade */
+	outb (0x01,IC_PIC1+1);	/* ICW4: x86 mode */
+
+	/* PIC1 Program Operational Control Words */
+	outb (0xff,IC_PIC1+1);	/* OCW1: Mask all interrupts */
+	outb (0xc2,IC_PIC1+0);  /* OCW2: priority (3-7,0-2) */
+
+	/* PIC2 Initialization Command Word register programming */
+	outb (0x11,IC_PIC2+0);	/* ICW1: ICW4 write req | ICW1 */
+	outb (0x00,IC_PIC2+1);	/* ICW2: N/A */
+	outb (0x02,IC_PIC2+1);	/* ICW3: Slave ID code */
+	outb (0x01,IC_PIC2+1);	/* ICW4: x86 mode */
+		
+	/* Program Operational Control Words */
+	outb (0xff,IC_PIC1+1);	/* OCW1: Mask all interrupts */
+	outb (0x68,IC_PIC1+0);	/* OCW3: OCW3 select | ESMM | SMM */
+
+	/* Write master mask reg */
+
+	outb (0xff,IC_PIC1+1);
+
+	/* Set up interrupt routing */
+
+	pci_write_config_byte (pdev, IR_USB, 0x10); /* USB on IRQ1 */
+	pci_write_config_byte (pdev, IR_SER, 0x43); /* SP1 on IRQ3, SP2 on IRQ4 */
+	pci_write_config_byte (pdev, IR_PFD, 0x65); /* PAR on IRQ5, FDC on IRQ6 */
+	pci_write_config_byte (pdev, IR_IDE, 0x07); /* IDE1 on IRQ7 */
+	
+	/* Set USB and IDE to level triggered interrupts, rest to edge */
+	pci_write_config_byte (pdev, TRIGGER_1, 0x82); /* IRQ 1 and 7 */
+
+	/* Setup USB power regulation */
+	outb(1, sio->acpi_base + USB_REG_CR);
+	if (inb(sio->acpi_base + USB_REG_CR) & 1)
+		printk(KERN_INFO "SuperIO: USB regulator enabled\n");
+	else
+		printk(KERN_ERR "USB regulator not initialized!\n");
+
+	pci_enable_device(pdev);
+
+	if (request_irq(sio->iosapic_irq,superio_interrupt,SA_INTERRUPT,
+			"SuperIO",(void *)sio)) {
+
+		printk(KERN_ERR "SuperIO: could not get irq\n");
+		BUG();
+		return;
+	}
+
+	sio->iosapic_irq_enabled = 1;
+	
+}
+
+static void
+superio_disable_irq(void *dev, int local_irq)
+{
+	u8 r8;
+
+	if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) {
+	    printk(KERN_ERR "SuperIO: Illegal irq number.\n");
+	    BUG();
+	    return;
+	}
+
+	/* Mask interrupt */
+
+	r8 = inb(IC_PIC1+1);
+	r8 |= (1 << local_irq);
+	outb (r8,IC_PIC1+1);
+}
+
+static void
+superio_enable_irq(void *dev, int local_irq)
+{
+	struct superio_device *sio = (struct superio_device *)dev;
+	u8 r8;
+
+	if ((local_irq < 1) || (local_irq == 2) || (local_irq > 7)) {
+	    printk(KERN_ERR "SuperIO: Illegal irq number.\n");
+	    BUG();
+	    return;
+	}
+
+	/*
+	 * It's possible that we haven't initialized the legacy IO
+	 * function yet. If not, do it now.
+	 */
+
+	if (!sio->iosapic_irq_enabled)
+		superio_init(sio);
+
+	/* Unmask interrupt */
+
+	r8 = inb(IC_PIC1+1);
+	r8 &= ~(1 << local_irq);
+	outb (r8,IC_PIC1+1);
+}
+
+static void
+superio_mask_irq(void *dev, int local_irq)
+{
+	BUG();
+}
+
+static void
+superio_unmask_irq(void *dev, int local_irq)
+{
+	BUG();
+}
+
+static struct irq_region_ops superio_irq_ops = {
+	disable_irq:	superio_disable_irq,
+	enable_irq:	superio_enable_irq,
+	mask_irq:	superio_mask_irq,
+	unmask_irq:	superio_unmask_irq
+};
+
+#ifdef DEBUG_INIT
+static unsigned short expected_device[3] = {
+	PCI_DEVICE_ID_NS_87415,
+	PCI_DEVICE_ID_NS_87560_LIO,
+	PCI_DEVICE_ID_NS_87560_USB
+};
+#endif
+
+int superio_fixup_irq(struct pci_dev *pcidev)
+{
+	int local_irq;
+
+#ifdef DEBUG_INIT
+	int fn;
+	fn = PCI_FUNC(pcidev->devfn);
+
+	/* Verify the function number matches the expected device id. */
+	if (expected_device[fn] != pcidev->device) {
+		BUG();
+		return -1;
+	}
+	printk("superio_fixup_irq(%s) ven 0x%x dev 0x%x from %p\n",
+		pcidev->slot_name,
+		pcidev->vendor, pcidev->device,
+		__builtin_return_address(0));
+#endif
+
+	if (!sio_dev.irq_region) {
+		/* Allocate an irq region for SuperIO devices */
+		sio_dev.irq_region = alloc_irq_region(SUPERIO_NIRQS,
+						&superio_irq_ops,
+						"SuperIO", (void *) &sio_dev);
+		if (!sio_dev.irq_region) {
+			printk(KERN_WARNING "SuperIO: alloc_irq_region failed\n");
+			return -1;
+		}
+	}
+
+	/*
+	 * We don't allocate a SuperIO irq for the legacy IO function,
+	 * since it is a "bridge". Instead, we will allocate irq's for
+	 * each legacy device as they are initialized.
+	 */
+
+	switch(pcidev->device) {
+	case PCI_DEVICE_ID_NS_87415:		/* Function 0 */
+		local_irq = IDE_IRQ;
+		break;
+	case PCI_DEVICE_ID_NS_87560_LIO:	/* Function 1 */
+		sio_dev.lio_pdev = pcidev; /* save for later initialization */
+		return -1;
+	case PCI_DEVICE_ID_NS_87560_USB:	/* Function 2 */
+		local_irq = USB_IRQ;
+		break;
+	default:
+		local_irq = -1;
+		BUG();
+		break;
+	}
+
+	return(sio_dev.irq_region->data.irqbase + local_irq);
+}
+
+void __devinit
+superio_serial_init(void)
+{
+#ifdef CONFIG_SERIAL
+	struct serial_struct *serial;
+	int retval;
+	
+	if (!sio_dev.irq_region)
+		return; /* superio not present */
+
+	if (!sio_dev.iosapic_irq_enabled)
+		superio_init(&sio_dev);
+
+	serial = kmalloc(2 * sizeof (struct serial_struct), GFP_KERNEL);
+
+	if (!serial) {
+		printk(KERN_WARNING "SuperIO: Could not get memory for serial struct.\n");
+		return;
+	}
+
+	memset(serial, 0, 2 * sizeof (struct serial_struct));
+
+	serial->type = PORT_16550A;
+	serial->line = 0;
+	serial->port = sio_dev.sp1_base;
+	serial->port_high = 0;
+	serial->irq = sio_dev.irq_region->data.irqbase + SP1_IRQ;
+	serial->io_type = SERIAL_IO_PORT;
+	serial->flags = 0;
+	serial->xmit_fifo_size = 16;
+	serial->custom_divisor = 0;
+	serial->baud_base = 115200;
+
+	retval = register_serial(serial);
+	if (retval < 0) {
+		printk(KERN_WARNING "SuperIO: Register Serial #0 failed.\n");
+		kfree (serial);
+		return;
+	}
+
+	serial++;
+
+	serial->type = PORT_16550A;
+	serial->line = 1;
+	serial->port = sio_dev.sp2_base;
+	serial->port_high = 0;
+	serial->irq = sio_dev.irq_region->data.irqbase + SP2_IRQ;
+	serial->io_type = SERIAL_IO_PORT;
+	serial->flags = 0;
+	serial->xmit_fifo_size = 16;
+	serial->custom_divisor = 0;
+	serial->baud_base = 115200;
+
+	retval = register_serial(serial);
+	if (retval < 0)
+		printk(KERN_WARNING "SuperIO: Register Serial #1 failed.\n");
+#endif /* CONFIG_SERIAL */
+}
+
+EXPORT_SYMBOL(superio_serial_init);
+
+
+#ifdef CONFIG_PARPORT_PC
+void __devinit
+superio_parport_init(void)
+{
+	if (!sio_dev.irq_region)
+		return; /* superio not present */
+
+	if (!sio_dev.iosapic_irq_enabled)
+		superio_init(&sio_dev);
+
+	if (!parport_pc_probe_port(sio_dev.pp_base, 
+		0 /*base_hi*/,
+		sio_dev.irq_region->data.irqbase + PAR_IRQ, 
+		PARPORT_DMA_NONE /* dma */,
+		NULL /*struct pci_dev* */))
+
+		printk(KERN_WARNING "SuperIO: Probing parallel port failed.\n");
+}
+
+EXPORT_SYMBOL(superio_parport_init);
+#endif	/* CONFIG_PARPORT_PC */
+
+
+int
+superio_get_ide_irq(void)
+{
+	if (sio_dev.irq_region)
+		return sio_dev.irq_region->data.irqbase + IDE_IRQ;
+	else
+		return 0;
+}
+
+EXPORT_SYMBOL(superio_get_ide_irq);
+
+static int __devinit superio_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+#ifdef DEBUG_INIT
+	printk("superio_probe(%s) ven 0x%x dev 0x%x sv 0x%x sd 0x%x class 0x%x\n",
+		dev->slot_name,
+		dev->vendor, dev->device,
+		dev->subsystem_vendor, dev->subsystem_device,
+		dev->class);
+/*
+** superio_probe(00:0e.0) ven 0x100b dev 0x2 sv 0x0 sd 0x0 class 0x1018a
+** superio_probe(00:0e.1) ven 0x100b dev 0xe sv 0x0 sd 0x0 class 0x68000
+** superio_probe(00:0e.2) ven 0x100b dev 0x12 sv 0x0 sd 0x0 class 0xc0310
+*/
+#endif
+
+	/* superio_fixup_irq(dev); */
+
+	if (dev->device == PCI_DEVICE_ID_NS_87560_LIO) {
+#ifdef CONFIG_PARPORT_PC
+		superio_parport_init();
+#endif
+		/* Don't call superio_serial_init() - see rs_init() */
+		/* REVISIT : superio_fdc_init() ? */
+		return 0;
+	}
+	else
+	{
+		/* don't claim this device; let whatever either driver
+		 * do it 
+		 */ 
+		return -1;
+	}
+}
+
+static struct pci_device_id superio_tbl[] __devinitdata = {
+	{ PCI_VENDOR_ID_NS, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0, }
+};
+
+static struct pci_driver superio_driver = {
+	name:		"SuperIO",
+	id_table:	superio_tbl,
+	probe:		superio_probe,
+};
+
+static int __init superio_modinit(void)
+{
+	return pci_module_init(&superio_driver);
+}
+
+static void __exit superio_exit(void)
+{
+	pci_unregister_driver(&superio_driver);
+}
+
+module_init(superio_modinit);
+module_exit(superio_exit);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/sys32.h linux/arch/parisc/kernel/sys32.h
--- linux.orig/arch/parisc/kernel/sys32.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/sys32.h	2002-08-12 22:14:09.000000000 +0000
@@ -0,0 +1,33 @@
+#ifndef _PARISC64_KERNEL_SYS32_H
+#define _PARISC64_KERNEL_SYS32_H
+
+/* Call a kernel syscall which will use kernel space instead of user
+ * space for its copy_to/from_user.
+ */
+#define KERNEL_SYSCALL(ret, syscall, args...) \
+{ \
+    mm_segment_t old_fs = get_fs(); \
+    set_fs(KERNEL_DS); \
+    ret = syscall(args); \
+    set_fs (old_fs); \
+}
+
+struct timeval32 {
+	int tv_sec;
+	int tv_usec;
+};
+
+typedef __u32 __sighandler_t32;
+
+#include <linux/signal.h>
+typedef struct {
+	unsigned int sig[_NSIG_WORDS * 2];
+} sigset_t32;
+
+struct sigaction32 {
+	__sighandler_t32 sa_handler;
+	unsigned int sa_flags;
+	sigset_t32 sa_mask;		/* mask last for extensibility */
+};
+
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/sys_parisc.c linux/arch/parisc/kernel/sys_parisc.c
--- linux.orig/arch/parisc/kernel/sys_parisc.c	2001-03-19 20:35:11.000000000 +0000
+++ linux/arch/parisc/kernel/sys_parisc.c	2002-08-12 22:14:25.000000000 +0000
@@ -1,7 +1,7 @@
 /*
  * linux/arch/parisc/kernel/sys_parisc.c
  *
- * this implements the missing syscalls.
+ * this implements syscalls which are handled per-arch.
  */
 
 #include <asm/uaccess.h>
@@ -10,26 +10,15 @@
 #include <linux/linkage.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/shm.h>
 #include <linux/smp_lock.h>
 
-/* for some reason, "old_readdir" is the only syscall which does not begin
- * with "sys_", which breaks the ENTRY_* macros in syscall.S so I "fixed"
- * it here.
- */
-
-int sys_old_readdir(unsigned int fd, void *dirent, unsigned int count)
-{
-    return old_readdir(fd, dirent, count);
-}
-
 int sys_pipe(int *fildes)
 {
 	int fd[2];
 	int error;
 
-	lock_kernel();
 	error = do_pipe(fd);
-	unlock_kernel();
 	if (!error) {
 		if (copy_to_user(fildes, fd, 2*sizeof(int)))
 			error = -EFAULT;
@@ -44,40 +33,117 @@
 	return -ERESTARTNOHAND;
 }
 
-int sys_mmap(unsigned long addr, unsigned long len,
-		unsigned long prot, unsigned long flags, unsigned long fd,
-		unsigned long offset)
+static unsigned long get_unshared_area(unsigned long addr, unsigned long len)
 {
-	struct file * file = NULL;
-	int error;
+	struct vm_area_struct *vma;
 
-	down_write(&current->mm->mmap_sem);
-	lock_kernel();
+	if (!addr)
+		addr = TASK_UNMAPPED_BASE;
+	addr = PAGE_ALIGN(addr);
+
+	for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+		/* At this point:  (!vma || addr < vma->vm_end). */
+		if (TASK_SIZE - len < addr)
+			return -ENOMEM;
+		if (!vma || addr + len <= vma->vm_start)
+			return addr;
+		addr = vma->vm_end;
+	}
+}
+
+#define DCACHE_ALIGN(addr) (((addr) + (SHMLBA - 1)) &~ (SHMLBA - 1))
+
+static unsigned long get_shared_area(struct inode *inode, unsigned long addr,
+		unsigned long len, unsigned long pgoff)
+{
+	struct vm_area_struct *vma, *first_vma;
+	int offset;
+
+	first_vma = inode->i_mapping->i_mmap_shared;
+	offset = (first_vma->vm_start + ((pgoff - first_vma->vm_pgoff) << PAGE_SHIFT)) & (SHMLBA - 1);
+
+	if (!addr)
+		addr = TASK_UNMAPPED_BASE;
+	addr = DCACHE_ALIGN(addr - offset) + offset;
+
+	for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
+		/* At this point:  (!vma || addr < vma->vm_end). */
+		if (TASK_SIZE - len < addr)
+			return -ENOMEM;
+		if (!vma || addr + len <= vma->vm_start)
+			return addr;
+		addr = DCACHE_ALIGN(vma->vm_end - offset) + offset;
+		if (addr < vma->vm_end) /* handle wraparound */
+			return -ENOMEM;
+	}
+}
+
+unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct inode *inode = NULL;
+
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (filp) {
+		inode = filp->f_dentry->d_inode;
+	}
+
+	if (inode && (flags & MAP_SHARED) && (inode->i_mapping->i_mmap_shared)) {
+		addr = get_shared_area(inode, addr, len, pgoff);
+	} else {
+		addr = get_unshared_area(addr, len);
+	}
+	return addr;
+}
+
+static unsigned long do_mmap2(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags, unsigned long fd,
+	unsigned long pgoff)
+{
+	struct file * file = NULL;
+	unsigned long error = -EBADF;
 	if (!(flags & MAP_ANONYMOUS)) {
-		error = -EBADF;
 		file = fget(fd);
 		if (!file)
 			goto out;
 	}
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
-	error = do_mmap(file, addr, len, prot, flags, offset);
+
+	down_write(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up_write(&current->mm->mmap_sem);
+
 	if (file != NULL)
 		fput(file);
 out:
-	unlock_kernel();
-	up_write(&current->mm->mmap_sem);
 	return error;
 }
 
-int sys_ioperm(unsigned long from, unsigned long num, int on)
+asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags, unsigned long fd,
+	unsigned long pgoff)
 {
-	return -ENOSYS;
+	/* Make sure the shift for mmap2 is constant (12), no matter what PAGE_SIZE
+	   we have. */
+	return do_mmap2(addr, len, prot, flags, fd, pgoff >> (PAGE_SHIFT - 12));
 }
 
-long sys_shmat_wrapper(int shmid, void *shmaddr, int shmflag)
+asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
+		unsigned long prot, unsigned long flags, unsigned long fd,
+		unsigned long offset)
+{
+	if (!(offset & ~PAGE_MASK)) {
+		return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+	} else {
+		return -EINVAL;
+	}
+}
+
+long sys_shmat_wrapper(int shmid, char *shmaddr, int shmflag)
 {
-	extern int sys_shmat(int shmid, char *shmaddr, int shmflg,
-			     unsigned long * raddr);
 	unsigned long raddr;
 	int r;
 
@@ -86,3 +152,107 @@
 		return r;
 	return raddr;
 }
+
+
+/*
+ * FIXME, please remove this crap as soon as possible
+ *
+ * This is here to fix up broken glibc structures, 
+ * which are already fixed in newer glibcs
+ */
+#include <linux/msg.h>
+#include <linux/sem.h>
+#include <linux/shm.h>
+#include "sys32.h"
+
+struct broken_ipc_perm
+{
+    key_t key;			/* Key.  */
+    uid_t uid;			/* Owner's user ID.  */
+    gid_t gid;			/* Owner's group ID.  */
+    uid_t cuid;			/* Creator's user ID.  */
+    gid_t cgid;			/* Creator's group ID.  */
+    unsigned short int mode;		/* Read/write permission.  */
+    unsigned short int __pad1;
+    unsigned short int seq;		/* Sequence number.  */
+    unsigned short int __pad2;
+    unsigned long int __unused1;
+    unsigned long int __unused2;
+};
+		    
+struct broken_shmid64_ds {
+	struct broken_ipc_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+#ifndef __LP64__
+	unsigned int		__pad1;
+#endif
+	__kernel_time_t		shm_atime;	/* last attach time */
+#ifndef __LP64__
+	unsigned int		__pad2;
+#endif
+	__kernel_time_t		shm_dtime;	/* last detach time */
+#ifndef __LP64__
+	unsigned int		__pad3;
+#endif
+	__kernel_time_t		shm_ctime;	/* last change time */
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned int		shm_nattch;	/* no. of current attaches */
+	unsigned int		__unused1;
+	unsigned int		__unused2;
+};
+
+static void convert_broken_perm (struct broken_ipc_perm *out, struct ipc64_perm *in)
+{
+	out->key  = in->key;
+	out->uid  = in->uid;
+	out->gid  = in->gid;
+	out->cuid = in->cuid;
+	out->cgid = in->cgid;
+	out->mode = in->mode;
+	out->seq  = in->seq;
+}
+
+static int copyout_broken_shmid64(struct broken_shmid64_ds *buf, struct shmid64_ds *sbuf)
+{
+	struct broken_shmid64_ds tbuf;
+	
+	memset(&tbuf, 0, sizeof tbuf);
+	convert_broken_perm (&tbuf.shm_perm, &sbuf->shm_perm);
+	tbuf.shm_segsz = sbuf->shm_segsz;
+	tbuf.shm_atime = sbuf->shm_atime;
+	tbuf.shm_dtime = sbuf->shm_dtime;
+	tbuf.shm_ctime = sbuf->shm_ctime;
+	tbuf.shm_cpid = sbuf->shm_cpid;
+	tbuf.shm_lpid = sbuf->shm_lpid;
+	tbuf.shm_nattch = sbuf->shm_nattch;
+	return copy_to_user(buf, &tbuf, sizeof tbuf);
+}
+
+int sys_msgctl_broken(int msqid, int cmd, struct msqid_ds *buf)
+{
+	return sys_msgctl (msqid, cmd & ~IPC_64, buf);
+}
+
+int sys_semctl_broken(int semid, int semnum, int cmd, union semun arg)
+{
+	return sys_semctl (semid, semnum, cmd & ~IPC_64, arg);
+}
+
+int sys_shmctl_broken(int shmid, int cmd, struct shmid64_ds *buf)
+{
+	struct shmid64_ds sbuf;
+	int err;
+
+	if (cmd & IPC_64) {
+		cmd &= ~IPC_64;
+		if (cmd == IPC_STAT || cmd == SHM_STAT) {
+			KERNEL_SYSCALL(err, sys_shmctl, shmid, cmd, (struct shmid_ds *)&sbuf);
+			if (err == 0)
+				err = copyout_broken_shmid64((struct broken_shmid64_ds *)buf, &sbuf);
+			return err;
+		}
+	}
+	return sys_shmctl (shmid, cmd, (struct shmid_ds *)buf);
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/sys_parisc32.c linux/arch/parisc/kernel/sys_parisc32.c
--- linux.orig/arch/parisc/kernel/sys_parisc32.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/sys_parisc32.c	2002-08-12 22:14:12.000000000 +0000
@@ -0,0 +1,3117 @@
+/*
+ * sys_parisc32.c: Conversion between 32bit and 64bit native syscalls.
+ *
+ * Copyright (C) 2000-2001 Hewlett Packard Company
+ * Copyright (C) 2000 John Marvin
+ * Copyright (C) 2001 Matthew Wilcox
+ *
+ * These routines maintain argument size conversion between 32bit and 64bit
+ * environment. Based heavily on sys_ia32.c and sys_sparc32.c.
+ */
+
+#include <linux/config.h>
+#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>
+#include <linux/resource.h>
+#include <linux/times.h>
+#include <linux/utsname.h>
+#include <linux/timex.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/slab.h>
+#include <linux/uio.h>
+#include <linux/nfs_fs.h>
+#include <linux/smb_fs.h>
+#include <linux/smb_mount.h>
+#include <linux/ncp_fs.h>
+#include <linux/quota.h>
+#include <linux/module.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr.h>
+#include <linux/nfsd/syscall.h>
+#include <linux/poll.h>
+#include <linux/personality.h>
+#include <linux/stat.h>
+#include <linux/filter.h>			/* for setsockopt() */
+#include <linux/icmpv6.h>			/* for setsockopt() */
+#include <linux/netfilter_ipv4/ip_queue.h>	/* for setsockopt() */
+#include <linux/netfilter_ipv4/ip_tables.h>	/* for setsockopt() */
+#include <linux/netfilter_ipv6/ip6_tables.h>	/* for setsockopt() */
+#include <linux/highmem.h>
+#include <linux/highuid.h>
+#include <linux/mman.h>
+
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include "sys32.h"
+
+#define A(__x) ((unsigned long)(__x))
+
+
+#undef DEBUG
+
+#ifdef DEBUG
+#define DBG(x)	printk x
+#else
+#define DBG(x)
+#endif
+
+
+/*
+ * count32() counts the number of arguments/envelopes. It is basically
+ *           a copy of count() from fs/exec.c, except that it works
+ *           with 32 bit argv and envp pointers.
+ */
+
+static int count32(u32 *argv, int max)
+{
+	int i = 0;
+
+	if (argv != NULL) {
+		for (;;) {
+			u32 p;
+			int error;
+
+			error = get_user(p,argv);
+			if (error)
+				return error;
+			if (!p)
+				break;
+			argv++;
+			if(++i > max)
+				return -E2BIG;
+		}
+	}
+	return i;
+}
+
+
+/*
+ * copy_strings32() is basically a copy of copy_strings() from fs/exec.c
+ *                  except that it works with 32 bit argv and envp pointers.
+ */
+
+
+static int copy_strings32(int argc, u32 *argv, struct linux_binprm *bprm)
+{
+	while (argc-- > 0) {
+		u32 str;
+		int len;
+		unsigned long pos;
+
+		if (get_user(str, argv + argc) ||
+		    !str ||
+		    !(len = strnlen_user((char *)A(str), bprm->p)))
+			return -EFAULT;
+
+		if (bprm->p < len) 
+			return -E2BIG; 
+
+		bprm->p -= len;
+
+		pos = bprm->p;
+		while (len > 0) {
+			char *kaddr;
+			int i, new, err;
+			struct page *page;
+			int offset, bytes_to_copy;
+
+			offset = pos % PAGE_SIZE;
+			i = pos/PAGE_SIZE;
+			page = bprm->page[i];
+			new = 0;
+			if (!page) {
+				page = alloc_page(GFP_HIGHUSER);
+				bprm->page[i] = 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) {
+				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_dcache_page(page);
+			flush_page_to_ram(page);
+			kunmap(page);
+
+			if (err)
+				return -EFAULT; 
+
+			pos += bytes_to_copy;
+			str += bytes_to_copy;
+			len -= bytes_to_copy;
+		}
+	}
+	return 0;
+}
+
+/*
+ * do_execve32() is mostly a copy of do_execve(), with the exception
+ * that it processes 32 bit argv and envp pointers.
+ */
+
+static inline int 
+do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
+{
+	struct linux_binprm bprm;
+	struct file *file;
+	int retval;
+	int i;
+
+	file = open_exec(filename);
+
+	retval = PTR_ERR(file);
+	if (IS_ERR(file))
+		return retval;
+
+	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
+
+	DBG(("do_execve32(%s, %p, %p, %p)\n", filename, argv, envp, regs));
+
+	bprm.file = file;
+	bprm.filename = filename;
+	bprm.sh_bang = 0;
+	bprm.loader = 0;
+	bprm.exec = 0;
+	if ((bprm.argc = count32(argv, bprm.p / sizeof(u32))) < 0) {
+		allow_write_access(file);
+		fput(file);
+		return bprm.argc;
+	}
+	if ((bprm.envc = count32(envp, bprm.p / sizeof(u32))) < 0) {
+		allow_write_access(file);
+		fput(file);
+		return bprm.envc;
+	}
+
+	retval = prepare_binprm(&bprm);
+	if (retval < 0)
+		goto out;
+	
+	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	if (retval < 0)
+		goto out;
+
+	bprm.exec = bprm.p;
+	retval = copy_strings32(bprm.envc, envp, &bprm);
+	if (retval < 0)
+		goto out;
+
+	retval = copy_strings32(bprm.argc, argv, &bprm);
+	if (retval < 0)
+		goto out;
+
+	retval = search_binary_handler(&bprm,regs);
+	if (retval >= 0)
+		/* execve success */
+		return retval;
+
+out:
+	/* Something went wrong, return the inode and free the argument pages*/
+	allow_write_access(bprm.file);
+	if (bprm.file)
+		fput(bprm.file);
+
+	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+		struct page * page = bprm.page[i];
+		if (page)
+			__free_page(page);
+	}
+
+	return retval;
+}
+
+/*
+ * sys32_execve() executes a new program.
+ */
+
+asmlinkage int sys32_execve(struct pt_regs *regs)
+{
+	int error;
+	char *filename;
+
+	DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
+	filename = getname((char *) regs->gr[26]);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		goto out;
+	error = do_execve32(filename, (u32 *) regs->gr[25],
+		(u32 *) regs->gr[24], regs);
+	if (error == 0)
+		current->ptrace &= ~PT_DTRACE;
+	putname(filename);
+out:
+
+	return error;
+}
+
+asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,
+	int r22, int r21, int r20)
+{
+    printk(KERN_ERR "%s(%d): Unimplemented 32 on 64 syscall #%d!\n", 
+    	current->comm, current->pid, r20);
+    return -ENOSYS;
+}
+
+/* 32-bit user apps use struct statfs which uses 'long's */
+struct statfs32 {
+	__s32 f_type;
+	__s32 f_bsize;
+	__s32 f_blocks;
+	__s32 f_bfree;
+	__s32 f_bavail;
+	__s32 f_files;
+	__s32 f_ffree;
+	__kernel_fsid_t f_fsid;
+	__s32 f_namelen;
+	__s32 f_spare[6];
+};
+
+/* convert statfs struct to statfs32 struct and copy result to user */
+static unsigned long statfs32_to_user(struct statfs32 *ust32, struct statfs *st)
+{
+    struct statfs32 st32;
+#undef CP
+#define CP(a) st32.a = st->a
+    CP(f_type);
+    CP(f_bsize);
+    CP(f_blocks);
+    CP(f_bfree);
+    CP(f_bavail);
+    CP(f_files);
+    CP(f_ffree);
+    CP(f_fsid);
+    CP(f_namelen);
+    return copy_to_user(ust32, &st32, sizeof st32);
+}
+
+/* The following statfs calls are copies of code from linux/fs/open.c and
+ * should be checked against those from time to time */
+asmlinkage long sys32_statfs(const char * path, struct statfs32 * buf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk(path, &nd);
+	if (!error) {
+		struct statfs tmp;
+		error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
+		if (!error && statfs32_to_user(buf, &tmp))
+			error = -EFAULT;
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage long sys32_fstatfs(unsigned int fd, struct statfs32 * buf)
+{
+	struct file * file;
+	struct statfs tmp;
+	int error;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+	error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
+	if (!error && statfs32_to_user(buf, &tmp))
+		error = -EFAULT;
+	fput(file);
+out:
+	return error;
+}
+
+/* These may not work without my local types changes, but I wanted the
+ * code available in case it's useful to others. -PB
+ */
+
+/* from utime.h */
+struct utimbuf32 {
+	__kernel_time_t32 actime;
+	__kernel_time_t32 modtime;
+};
+
+asmlinkage long sys32_utime(char *filename, struct utimbuf32 *times)
+{
+    struct utimbuf32 times32;
+    struct utimbuf times64;
+    extern long sys_utime(char *filename, struct utimbuf *times);
+    char *fname;
+    long ret;
+
+    if (!times)
+    	return sys_utime(filename, NULL);
+
+    /* get the 32-bit struct from user space */
+    if (copy_from_user(&times32, times, sizeof times32))
+    	return -EFAULT;
+
+    /* convert it into the 64-bit one */
+    times64.actime = times32.actime;
+    times64.modtime = times32.modtime;
+
+    /* grab the file name */
+    fname = getname(filename);
+
+    KERNEL_SYSCALL(ret, sys_utime, fname, &times64);
+
+    /* free the file name */
+    putname(fname);
+
+    return ret;
+}
+
+struct tms32 {
+	__kernel_clock_t32 tms_utime;
+	__kernel_clock_t32 tms_stime;
+	__kernel_clock_t32 tms_cutime;
+	__kernel_clock_t32 tms_cstime;
+};
+                                
+asmlinkage long sys32_times(struct tms32 *tbuf)
+{
+	struct tms t;
+	long ret;
+	extern asmlinkage long sys_times(struct tms * tbuf);
+int err;
+	
+	KERNEL_SYSCALL(ret, sys_times, tbuf ? &t : NULL);
+	if (tbuf) {
+		err = put_user (t.tms_utime, &tbuf->tms_utime);
+		err |= __put_user (t.tms_stime, &tbuf->tms_stime);
+		err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
+		err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+		if (err)
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+struct flock32 {
+	short l_type;
+	short l_whence;
+	__kernel_off_t32 l_start;
+	__kernel_off_t32 l_len;
+	__kernel_pid_t32 l_pid;
+};
+
+
+static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
+{
+	int err;
+	
+	err = get_user(kfl->l_type, &ufl->l_type);
+	err |= __get_user(kfl->l_whence, &ufl->l_whence);
+	err |= __get_user(kfl->l_start, &ufl->l_start);
+	err |= __get_user(kfl->l_len, &ufl->l_len);
+	err |= __get_user(kfl->l_pid, &ufl->l_pid);
+	return err;
+}
+
+static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
+{
+	int err;
+	
+	err = __put_user(kfl->l_type, &ufl->l_type);
+	err |= __put_user(kfl->l_whence, &ufl->l_whence);
+	err |= __put_user(kfl->l_start, &ufl->l_start);
+	err |= __put_user(kfl->l_len, &ufl->l_len);
+	err |= __put_user(kfl->l_pid, &ufl->l_pid);
+	return err;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		{
+			struct flock f;
+			long ret;
+			
+			if(get_flock(&f, (struct flock32 *)arg))
+				return -EFAULT;
+			KERNEL_SYSCALL(ret, sys_fcntl, fd, cmd, (unsigned long)&f);
+			if (ret) return ret;
+			if (f.l_start >= 0x7fffffffUL ||
+			    f.l_len >= 0x7fffffffUL ||
+			    f.l_start + f.l_len >= 0x7fffffffUL)
+				return -EOVERFLOW;
+			if(put_flock(&f, (struct flock32 *)arg))
+				return -EFAULT;
+			return 0;
+		}
+	default:
+		return sys_fcntl(fd, cmd, (unsigned long)arg);
+	}
+}
+
+#ifdef CONFIG_SYSCTL
+
+struct __sysctl_args32 {
+	u32 name;
+	int nlen;
+	u32 oldval;
+	u32 oldlenp;
+	u32 newval;
+	u32 newlen;
+	u32 __unused[4];
+};
+
+asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+{
+	struct __sysctl_args32 tmp;
+	int error;
+	unsigned int oldlen32;
+	size_t oldlen, *oldlenp = NULL;
+	unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+	extern int do_sysctl(int *name, int nlen, void *oldval, size_t *oldlenp,
+	       void *newval, size_t newlen);
+
+	DBG(("sysctl32(%p)\n", args));
+
+	if (copy_from_user(&tmp, args, sizeof(tmp)))
+		return -EFAULT;
+
+	if (tmp.oldval && tmp.oldlenp) {
+		/* Duh, this is ugly and might not work if sysctl_args
+		   is in read-only memory, but do_sysctl does indirectly
+		   a lot of uaccess in both directions and we'd have to
+		   basically copy the whole sysctl.c here, and
+		   glibc's __sysctl uses rw memory for the structure
+		   anyway.  */
+		/* a possibly better hack than this, which will avoid the
+		 * problem if the struct is read only, is to push the
+		 * 'oldlen' value out to the user's stack instead. -PB
+		 */
+		if (get_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
+			return -EFAULT;
+		oldlen = oldlen32;
+		if (put_user(oldlen, (size_t *)addr))
+			return -EFAULT;
+		oldlenp = (size_t *)addr;
+	}
+
+	lock_kernel();
+	error = do_sysctl((int *)(u64)tmp.name, tmp.nlen, (void *)(u64)tmp.oldval,
+			  oldlenp, (void *)(u64)tmp.newval, tmp.newlen);
+	unlock_kernel();
+	if (oldlenp) {
+		if (!error) {
+			if (get_user(oldlen, (size_t *)addr)) {
+				error = -EFAULT;
+			} else {
+				oldlen32 = oldlen;
+				if (put_user(oldlen32, (u32 *)(u64)tmp.oldlenp))
+					error = -EFAULT;
+			}
+		}
+		if (copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused)))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+#else /* CONFIG_SYSCTL */
+
+asmlinkage long sys32_sysctl(struct __sysctl_args *args)
+{
+	return -ENOSYS;
+}
+#endif /* CONFIG_SYSCTL */
+
+struct timespec32 {
+	s32    tv_sec;
+	s32    tv_nsec;
+};
+                
+static int
+put_timespec32(struct timespec32 *u, struct timespec *t)
+{
+	struct timespec32 t32;
+	t32.tv_sec = t->tv_sec;
+	t32.tv_nsec = t->tv_nsec;
+	return copy_to_user(u, &t32, sizeof t32);
+}
+
+asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
+{
+	struct timespec t;
+	struct timespec32 t32;
+	int ret;
+	extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+	
+	if (copy_from_user(&t32, rqtp, sizeof t32))
+		return -EFAULT;
+	t.tv_sec = t32.tv_sec;
+	t.tv_nsec = t32.tv_nsec;
+
+	DBG(("sys32_nanosleep({%d, %d})\n", t32.tv_sec, t32.tv_nsec));
+
+	KERNEL_SYSCALL(ret, sys_nanosleep, &t, rmtp ? &t : NULL);
+	if (rmtp && ret == -EINTR) {
+		if (put_timespec32(rmtp, &t))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+asmlinkage long sys32_sched_rr_get_interval(pid_t pid,
+	struct timespec32 *interval)
+{
+	struct timespec t;
+	int ret;
+	extern asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
+	
+	KERNEL_SYSCALL(ret, sys_sched_rr_get_interval, pid, &t);
+	if (put_timespec32(interval, &t))
+		return -EFAULT;
+	return ret;
+}
+
+typedef __kernel_time_t32 time_t32;
+
+static int
+put_timeval32(struct timeval32 *u, struct timeval *t)
+{
+	struct timeval32 t32;
+	t32.tv_sec = t->tv_sec;
+	t32.tv_usec = t->tv_usec;
+	return copy_to_user(u, &t32, sizeof t32);
+}
+
+static int
+get_timeval32(struct timeval32 *u, struct timeval *t)
+{
+	int err;
+	struct timeval32 t32;
+
+	if ((err = copy_from_user(&t32, u, sizeof t32)) == 0)
+	{
+	    t->tv_sec = t32.tv_sec;
+	    t->tv_usec = t32.tv_usec;
+	}
+	return err;
+}
+
+asmlinkage long sys32_time(time_t32 *tloc)
+{
+    time_t now = CURRENT_TIME;
+    time_t32 now32 = now;
+
+    if (tloc)
+    	if (put_user(now32, tloc))
+		now32 = -EFAULT;
+
+    return now32;
+}
+
+asmlinkage int
+sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+    extern void do_gettimeofday(struct timeval *tv);
+
+    if (tv) {
+	    struct timeval ktv;
+	    do_gettimeofday(&ktv);
+	    if (put_timeval32(tv, &ktv))
+		    return -EFAULT;
+    }
+    if (tz) {
+	    extern struct timezone sys_tz;
+	    if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+		    return -EFAULT;
+    }
+    return 0;
+}
+
+asmlinkage int
+sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+    struct timeval ktv;
+    struct timezone ktz;
+    extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+
+    if (tv) {
+	    if (get_timeval32(tv, &ktv))
+		    return -EFAULT;
+    }
+    if (tz) {
+	    if (copy_from_user(&ktz, tz, sizeof(ktz)))
+		    return -EFAULT;
+    }
+
+    return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
+}
+
+struct	itimerval32 {
+	struct	timeval32 it_interval;	/* timer interval */
+	struct	timeval32 it_value;	/* current value */
+};
+
+asmlinkage long sys32_getitimer(int which, struct itimerval32 *ov32)
+{
+	int error = -EFAULT;
+	struct itimerval get_buffer;
+	extern int do_getitimer(int which, struct itimerval *value);
+
+	if (ov32) {
+		error = do_getitimer(which, &get_buffer);
+		if (!error) {
+			struct itimerval32 gb32;
+			gb32.it_interval.tv_sec = get_buffer.it_interval.tv_sec;
+			gb32.it_interval.tv_usec = get_buffer.it_interval.tv_usec;
+			gb32.it_value.tv_sec = get_buffer.it_value.tv_sec;
+			gb32.it_value.tv_usec = get_buffer.it_value.tv_usec;
+			if (copy_to_user(ov32, &gb32, sizeof(gb32)))
+				error = -EFAULT; 
+		}
+	}
+	return error;
+}
+
+asmlinkage long sys32_setitimer(int which, struct itimerval32 *v32,
+			      struct itimerval32 *ov32)
+{
+	struct itimerval set_buffer, get_buffer;
+	struct itimerval32 sb32, gb32;
+	extern int do_setitimer(int which, struct itimerval *value, struct itimerval *ov32);
+	int error;
+
+	if (v32) {
+		if(copy_from_user(&sb32, v32, sizeof(sb32)))
+			return -EFAULT;
+
+		set_buffer.it_interval.tv_sec = sb32.it_interval.tv_sec;
+		set_buffer.it_interval.tv_usec = sb32.it_interval.tv_usec;
+		set_buffer.it_value.tv_sec = sb32.it_value.tv_sec;
+		set_buffer.it_value.tv_usec = sb32.it_value.tv_usec;
+	} else
+		memset((char *) &set_buffer, 0, sizeof(set_buffer));
+
+	error = do_setitimer(which, &set_buffer, ov32 ? &get_buffer : 0);
+	if (error || !ov32)
+		return error;
+
+	gb32.it_interval.tv_sec = get_buffer.it_interval.tv_sec;
+	gb32.it_interval.tv_usec = get_buffer.it_interval.tv_usec;
+	gb32.it_value.tv_sec = get_buffer.it_value.tv_sec;
+	gb32.it_value.tv_usec = get_buffer.it_value.tv_usec;
+	if (copy_to_user(ov32, &gb32, sizeof(gb32)))
+		return -EFAULT; 
+	return 0;
+}
+
+struct rusage32 {
+        struct timeval32 ru_utime;
+        struct timeval32 ru_stime;
+        int    ru_maxrss;
+        int    ru_ixrss;
+        int    ru_idrss;
+        int    ru_isrss;
+        int    ru_minflt;
+        int    ru_majflt;
+        int    ru_nswap;
+        int    ru_inblock;
+        int    ru_oublock;
+        int    ru_msgsnd; 
+        int    ru_msgrcv; 
+        int    ru_nsignals;
+        int    ru_nvcsw;
+        int    ru_nivcsw;
+};
+
+static int
+put_rusage32(struct rusage32 *ru32p, struct rusage *r)
+{
+	struct rusage32 r32;
+#undef CP
+#define CP(t) r32.t = r->t;
+	CP(ru_utime.tv_sec); CP(ru_utime.tv_usec);
+	CP(ru_stime.tv_sec); CP(ru_stime.tv_usec);
+	CP(ru_maxrss);
+	CP(ru_ixrss);
+	CP(ru_idrss);
+	CP(ru_isrss);
+	CP(ru_minflt);
+	CP(ru_majflt);
+	CP(ru_nswap);
+	CP(ru_inblock);
+	CP(ru_oublock);
+	CP(ru_msgsnd);
+	CP(ru_msgrcv);
+	CP(ru_nsignals);
+	CP(ru_nvcsw);
+	CP(ru_nivcsw);
+	return copy_to_user(ru32p, &r32, sizeof r32);
+}
+
+asmlinkage int
+sys32_getrusage(int who, struct rusage32 *ru)
+{
+	struct rusage r;
+	int ret;
+	extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
+		
+	KERNEL_SYSCALL(ret, sys_getrusage, who, &r);
+	if (put_rusage32(ru, &r)) return -EFAULT;
+	return ret;
+}
+
+asmlinkage int
+sys32_wait4(__kernel_pid_t32 pid, unsigned int * stat_addr, int options,
+	    struct rusage32 * ru)
+{
+	if (!ru)
+		return sys_wait4(pid, stat_addr, options, NULL);
+	else {
+		struct rusage r;
+		int ret;
+		unsigned int status;
+	
+		KERNEL_SYSCALL(ret, sys_wait4, pid, stat_addr ? &status : NULL, options, &r);
+		if (put_rusage32(ru, &r)) return -EFAULT;
+		if (stat_addr && put_user(status, stat_addr))
+			return -EFAULT;
+		return ret;
+	}
+}
+
+struct stat32 {
+	__kernel_dev_t32		st_dev;		/* dev_t is 32 bits on parisc */
+	__kernel_ino_t32		st_ino;		/* 32 bits */
+	__kernel_mode_t32	st_mode;	/* 16 bits */
+	__kernel_nlink_t32		st_nlink;	/* 16 bits */
+	unsigned short	st_reserved1;	/* old st_uid */
+	unsigned short	st_reserved2;	/* old st_gid */
+	__kernel_dev_t32		st_rdev;
+	__kernel_off_t32		st_size;
+	__kernel_time_t32	st_atime;
+	unsigned int	st_spare1;
+	__kernel_time_t32	st_mtime;
+	unsigned int	st_spare2;
+	__kernel_time_t32	st_ctime;
+	unsigned int	st_spare3;
+	int		st_blksize;
+	int		st_blocks;
+	unsigned int	__unused1;	/* ACL stuff */
+	__kernel_dev_t32		__unused2;	/* network */
+	__kernel_ino_t32		__unused3;	/* network */
+	unsigned int	__unused4;	/* cnodes */
+	unsigned short	__unused5;	/* netsite */
+	short		st_fstype;
+	__kernel_dev_t32		st_realdev;
+	unsigned short	st_basemode;
+	unsigned short	st_spareshort;
+	__kernel_uid_t32		st_uid;
+	__kernel_gid_t32		st_gid;
+	unsigned int	st_spare4[3];
+};
+
+/*
+ * Revalidate the inode. This is required for proper NFS attribute caching.
+ */
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+	struct inode * inode = dentry->d_inode;
+	if (inode->i_op && inode->i_op->revalidate)
+		return inode->i_op->revalidate(dentry);
+	return 0;
+}
+
+
+static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
+{
+	struct stat32 tmp;
+	unsigned int blocks, indirect;
+
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.st_dev = kdev_t_to_nr(inode->i_dev);
+	tmp.st_ino = inode->i_ino;
+	tmp.st_mode = inode->i_mode;
+	tmp.st_nlink = inode->i_nlink;
+	SET_STAT_UID(tmp, inode->i_uid);
+	SET_STAT_GID(tmp, inode->i_gid);
+	tmp.st_rdev = kdev_t_to_nr(inode->i_rdev);
+#if BITS_PER_LONG == 32
+	if (inode->i_size > 0x7fffffff)
+		return -EOVERFLOW;
+#endif	
+	tmp.st_size = inode->i_size;
+	tmp.st_atime = inode->i_atime;
+	tmp.st_mtime = inode->i_mtime;
+	tmp.st_ctime = inode->i_ctime;
+/*
+ * st_blocks and st_blksize are approximated with a simple algorithm if
+ * they aren't supported directly by the filesystem. The minix and msdos
+ * filesystems don't keep track of blocks, so they would either have to
+ * be counted explicitly (by delving into the file itself), or by using
+ * this simple algorithm to get a reasonable (although not 100% accurate)
+ * value.
+ */
+
+/*
+ * Use minix fs values for the number of direct and indirect blocks.  The
+ * count is now exact for the minix fs except that it counts zero blocks.
+ * Everything is in units of BLOCK_SIZE until the assignment to
+ * tmp.st_blksize.
+ */
+#define D_B   7
+#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
+
+	if (!inode->i_blksize) {
+		blocks = (tmp.st_size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+		if (blocks > D_B) {
+			indirect = (blocks - D_B + I_B - 1) / I_B;
+			blocks += indirect;
+			if (indirect > 1) {
+				indirect = (indirect - 1 + I_B - 1) / I_B;
+				blocks += indirect;
+				if (indirect > 1)
+					blocks++;
+			}
+		}
+		tmp.st_blocks = (BLOCK_SIZE / 512) * blocks;
+		tmp.st_blksize = BLOCK_SIZE;
+	} else {
+		tmp.st_blocks = inode->i_blocks;
+		tmp.st_blksize = inode->i_blksize;
+	}
+	return copy_to_user(statbuf,&tmp,sizeof(tmp)) ? -EFAULT : 0;
+}
+
+asmlinkage long sys32_newstat(char * filename, struct stat32 *statbuf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk(filename, &nd);
+	if (!error) {
+		error = do_revalidate(nd.dentry);
+		if (!error)
+			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage long sys32_newlstat(char * filename, struct stat32 *statbuf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk_link(filename, &nd);
+	if (!error) {
+		error = do_revalidate(nd.dentry);
+		if (!error)
+			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage long sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
+{
+	struct file * f;
+	int err = -EBADF;
+
+	f = fget(fd);
+	if (f) {
+		struct dentry * dentry = f->f_dentry;
+
+		err = do_revalidate(dentry);
+		if (!err)
+			err = cp_new_stat32(dentry->d_inode, statbuf);
+		fput(f);
+	}
+	return err;
+}
+
+struct linux32_dirent {
+	u32	d_ino;
+	__kernel_off_t32	d_off;
+	u16	d_reclen;
+	char	d_name[1];
+};
+
+struct old_linux32_dirent {
+	u32	d_ino;
+	u32	d_offset;
+	u16	d_namlen;
+	char	d_name[1];
+};
+
+struct getdents32_callback {
+	struct linux32_dirent * current_dir;
+	struct linux32_dirent * previous;
+	int count;
+	int error;
+};
+
+struct readdir32_callback {
+	struct old_linux32_dirent * dirent;
+	int count;
+};
+
+#define ROUND_UP(x,a)	((__typeof__(x))(((unsigned long)(x) + ((a) - 1)) & ~((a) - 1)))
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+static int
+filldir32 (void *__buf, const char *name, int namlen, loff_t offset, ino_t ino,
+	   unsigned int d_type)
+{
+	struct linux32_dirent * dirent;
+	struct getdents32_callback * buf = (struct getdents32_callback *) __buf;
+	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1, 4);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent)
+		put_user(offset, &dirent->d_off);
+	dirent = buf->current_dir;
+	buf->previous = dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user(reclen, &dirent->d_reclen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	((char *) dirent) += reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+}
+
+asmlinkage long
+sys32_getdents (unsigned int fd, void * dirent, unsigned int count)
+{
+	struct file * file;
+	struct linux32_dirent * lastdirent;
+	struct getdents32_callback buf;
+	int error;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = (struct linux32_dirent *) dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdir(file, filldir32, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.error;
+	lastdirent = buf.previous;
+	if (lastdirent) {
+		put_user(file->f_pos, &lastdirent->d_off);
+		error = count - buf.count;
+	}
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+
+static int
+fillonedir32 (void * __buf, const char * name, int namlen, loff_t offset, ino_t ino,
+	      unsigned int d_type)
+{
+	struct readdir32_callback * buf = (struct readdir32_callback *) __buf;
+	struct old_linux32_dirent * dirent;
+
+	if (buf->count)
+		return -EINVAL;
+	buf->count++;
+	dirent = buf->dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user(offset, &dirent->d_offset);
+	put_user(namlen, &dirent->d_namlen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	return 0;
+}
+
+asmlinkage long
+sys32_readdir (unsigned int fd, void * dirent, unsigned int count)
+{
+	int error;
+	struct file * file;
+	struct readdir32_callback buf;
+
+	error = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.count = 0;
+	buf.dirent = dirent;
+
+	error = vfs_readdir(file, fillonedir32, &buf);
+	if (error >= 0)
+		error = buf.count;
+	fput(file);
+out:
+	return error;
+}
+
+struct rlimit32 {
+	__u32	rlim_cur;
+	__u32	rlim_max;
+};
+
+#define RLIM32_INFINITY 0xffffffff
+
+asmlinkage long sys32_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit32 rlim32;
+	struct rlimit *rlimip;
+
+	if (resource >= RLIM_NLIMITS)
+		return -EINVAL;
+	rlimip = current->rlim + resource;
+	if (rlimip->rlim_cur >= RLIM32_INFINITY) {
+		rlim32.rlim_cur = RLIM32_INFINITY;
+	} else {
+		rlim32.rlim_cur = rlimip->rlim_cur;
+	}
+	if (rlimip->rlim_max >= RLIM32_INFINITY) {
+		rlim32.rlim_max = RLIM32_INFINITY;
+	} else {
+		rlim32.rlim_max = rlimip->rlim_max;
+	}
+	return copy_to_user(rlim, &rlim32, sizeof (struct rlimit32));
+}
+
+asmlinkage long sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit32 rlim32;
+	struct rlimit new_rlim, *old_rlim;
+
+	if (resource >= RLIM_NLIMITS)
+		return -EINVAL;
+	if (copy_from_user(&rlim32, rlim, sizeof(rlim)))
+		return -EFAULT;
+	if (rlim32.rlim_cur == RLIM32_INFINITY) {
+		new_rlim.rlim_cur = RLIM_INFINITY;
+	} else {
+		new_rlim.rlim_cur = rlim32.rlim_cur;
+	}
+	if (rlim32.rlim_max == RLIM32_INFINITY) {
+		new_rlim.rlim_max = RLIM_INFINITY;
+	} else {
+		new_rlim.rlim_max = rlim32.rlim_max;
+	}
+
+	old_rlim = current->rlim + resource;
+	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
+	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
+	    !capable(CAP_SYS_RESOURCE))
+		return -EPERM;
+	if (resource == RLIMIT_NOFILE) {
+		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
+			return -EPERM;
+	}
+	if (resource == RLIMIT_STACK) {
+		if (new_rlim.rlim_max > 1024 * 1024 * 1024) {
+			new_rlim.rlim_max = 1024 * 1024 * 1024;
+		}
+		new_rlim.rlim_max = PAGE_ALIGN(new_rlim.rlim_max);
+	}
+	
+	*old_rlim = new_rlim;
+	return 0;
+}
+
+static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
+{
+	int i;
+	unsigned long page;
+	struct vm_area_struct *vma;
+
+	*kernel = 0;
+	if(!user)
+		return 0;
+	vma = find_vma(current->mm, (unsigned long)user);
+	if(!vma || (unsigned long)user < vma->vm_start)
+		return -EFAULT;
+	if(!(vma->vm_flags & VM_READ))
+		return -EFAULT;
+	i = vma->vm_end - (unsigned long) user;
+	if(PAGE_SIZE <= (unsigned long) i)
+		i = PAGE_SIZE - 1;
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	if(copy_from_user((void *) page, user, i)) {
+		free_page(page);
+		return -EFAULT;
+	}
+	*kernel = page;
+	return 0;
+}
+
+#define SMBFS_NAME	"smbfs"
+#define NCPFS_NAME	"ncpfs"
+
+asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
+{
+	unsigned long type_page = 0;
+	unsigned long data_page = 0;
+	unsigned long dev_page = 0;
+	unsigned long dir_page = 0;
+	int err, is_smb, is_ncp;
+
+	is_smb = is_ncp = 0;
+
+	err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
+	if (err)
+		goto out;
+
+	if (!type_page) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+	is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+
+	err = copy_mount_stuff_to_kernel((const void *)(unsigned long)data, &data_page);
+	if (err)
+		goto type_out;
+
+	err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
+	if (err)
+		goto data_out;
+
+	err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
+	if (err)
+		goto dev_out;
+
+	if (!is_smb && !is_ncp) {
+		lock_kernel();
+		err = do_mount((char*)dev_page, (char*)dir_page,
+				(char*)type_page, new_flags, (char*)data_page);
+		unlock_kernel();
+	} else {
+		if (is_ncp)
+			panic("NCP mounts not yet supported 32/64 parisc");
+			/* do_ncp_super_data_conv((void *)data_page); */
+		else {
+			panic("SMB mounts not yet supported 32/64 parisc");
+			/* do_smb_super_data_conv((void *)data_page); */
+		}
+
+		lock_kernel();
+		err = do_mount((char*)dev_page, (char*)dir_page,
+				(char*)type_page, new_flags, (char*)data_page);
+		unlock_kernel();
+	}
+	free_page(dir_page);
+
+dev_out:
+	free_page(dev_page);
+
+data_out:
+	free_page(data_page);
+
+type_out:
+	free_page(type_page);
+
+out:
+	return err;
+}
+
+
+#ifdef CONFIG_MODULES
+
+struct module_info32 {
+	u32 addr;
+	u32 size;
+	u32 flags;
+	s32 usecount;
+};
+
+/* Query various bits about modules.  */
+
+static inline long
+get_mod_name(const char *user_name, char **buf)
+{
+	unsigned long page;
+	long retval;
+
+	if ((unsigned long)user_name >= TASK_SIZE
+	    && !segment_eq(get_fs (), KERNEL_DS))
+		return -EFAULT;
+
+	page = __get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
+	if (retval > 0) {
+		if (retval < PAGE_SIZE) {
+			*buf = (char *)page;
+			return retval;
+		}
+		retval = -ENAMETOOLONG;
+	} else if (!retval)
+		retval = -EINVAL;
+
+	free_page(page);
+	return retval;
+}
+
+static inline void
+put_mod_name(char *buf)
+{
+	free_page((unsigned long)buf);
+}
+
+static __inline__ struct module *find_module(const char *name)
+{
+	struct module *mod;
+
+	for (mod = module_list; mod ; mod = mod->next) {
+		if (mod->flags & MOD_DELETED)
+			continue;
+		if (!strcmp(mod->name, name))
+			break;
+	}
+
+	return mod;
+}
+
+static int
+qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	struct module *mod;
+	size_t nmod, space, len;
+
+	nmod = space = 0;
+
+	for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
+		len = strlen(mod->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, mod->name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nmod, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((mod = mod->next)->next != NULL)
+		space += strlen(mod->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+	if (!MOD_CAN_QUERY(mod))
+		return put_user(0, ret);
+
+	space = 0;
+	for (i = 0; i < mod->ndeps; ++i) {
+		const char *dep_name = mod->deps[i].dep->name;
+
+		len = strlen(dep_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, dep_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	return put_user(i, ret);
+
+calc_space_needed:
+	space += len;
+	while (++i < mod->ndeps)
+		space += strlen(mod->deps[i].dep->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t nrefs, space, len;
+	struct module_ref *ref;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+	if (!MOD_CAN_QUERY(mod))
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
+		const char *ref_name = ref->ref->name;
+
+		len = strlen(ref_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, ref_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nrefs, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((ref = ref->next_ref) != NULL)
+		space += strlen(ref->ref->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+	struct module_symbol *s;
+	char *strings;
+	unsigned *vals;
+
+	if (!MOD_CAN_QUERY(mod))
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = mod->nsyms * 2*sizeof(u32);
+
+	i = len = 0;
+	s = mod->syms;
+
+	if (space > bufsize)
+		goto calc_space_needed;
+
+	if (!access_ok(VERIFY_WRITE, buf, space))
+		return -EFAULT;
+
+	bufsize -= space;
+	vals = (unsigned *)buf;
+	strings = buf+space;
+
+	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
+		len = strlen(s->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+
+		if (copy_to_user(strings, s->name, len)
+		    || __put_user(s->value, vals+0)
+		    || __put_user(space, vals+1))
+			return -EFAULT;
+
+		strings += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (; i < mod->nsyms; ++i, ++s)
+		space += strlen(s->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	int error = 0;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+
+	if (sizeof(struct module_info32) <= bufsize) {
+		struct module_info32 info;
+		info.addr = (unsigned long)mod;
+		info.size = mod->size;
+		info.flags = mod->flags;
+		info.usecount =
+			((mod_member_present(mod, can_unload)
+			  && mod->can_unload)
+			 ? -1 : atomic_read(&mod->uc.usecount));
+
+		if (copy_to_user(buf, &info, sizeof(struct module_info32)))
+			return -EFAULT;
+	} else
+		error = -ENOSPC;
+
+	if (put_user(sizeof(struct module_info32), ret))
+		return -EFAULT;
+
+	return error;
+}
+
+asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, __kernel_size_t32 *ret)
+{
+	struct module *mod;
+	int err;
+
+	lock_kernel();
+	if (name_user == 0) {
+		/* This finds "kernel_module" which is not exported. */
+		for(mod = module_list; mod->next != NULL; mod = mod->next)
+			;
+	} else {
+		long namelen;
+		char *name;
+
+		if ((namelen = get_mod_name(name_user, &name)) < 0) {
+			err = namelen;
+			goto out;
+		}
+		err = -ENOENT;
+		if (namelen == 0) {
+			/* This finds "kernel_module" which is not exported. */
+			for(mod = module_list; mod->next != NULL; mod = mod->next)
+				;
+		} else if ((mod = find_module(name)) == NULL) {
+			put_mod_name(name);
+			goto out;
+		}
+		put_mod_name(name);
+	}
+
+	switch (which)
+	{
+	case 0:
+		err = 0;
+		break;
+	case QM_MODULES:
+		err = qm_modules(buf, bufsize, ret);
+		break;
+	case QM_DEPS:
+		err = qm_deps(mod, buf, bufsize, ret);
+		break;
+	case QM_REFS:
+		err = qm_refs(mod, buf, bufsize, ret);
+		break;
+	case QM_SYMBOLS:
+		err = qm_symbols(mod, buf, bufsize, ret);
+		break;
+	case QM_INFO:
+		err = qm_info(mod, buf, bufsize, ret);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+out:
+	unlock_kernel();
+	return err;
+}
+
+struct kernel_sym32 {
+	u32 value;
+	char name[60];
+};
+		 
+extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
+
+asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
+{
+	int len, i;
+	struct kernel_sym *tbl;
+	mm_segment_t old_fs;
+	
+	len = sys_get_kernel_syms(NULL);
+	if (!table) return len;
+	tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
+	if (!tbl) return -ENOMEM;
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	sys_get_kernel_syms(tbl);
+	set_fs (old_fs);
+	for (i = 0; i < len; i++, table++) {
+		if (put_user (tbl[i].value, &table->value) ||
+		    copy_to_user (table->name, tbl[i].name, 60))
+			break;
+	}
+	kfree (tbl);
+	return i;
+}
+
+#else /* CONFIG_MODULES */
+
+asmlinkage int
+sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+		 size_t *ret)
+{
+	/* Let the program know about the new interface.  Not that
+	   it'll do them much good.  */
+	if (which == 0)
+		return 0;
+
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_get_kernel_syms(struct kernel_sym *table)
+{
+	return -ENOSYS;
+}
+
+#endif  /* CONFIG_MODULES */
+
+/* readv/writev stolen from mips64 */
+struct iovec32 { unsigned int iov_base; int iov_len; };
+
+typedef ssize_t (*IO_fn_t)(struct file *, char *, size_t, loff_t *);
+
+static long
+do_readv_writev32(int type, struct file *file, const struct iovec32 *vector,
+		  u32 count)
+{
+	unsigned long tot_len;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov=iovstack, *ivp;
+	struct inode *inode;
+	long retval, i;
+	IO_fn_t fn;
+
+	/* First get the "struct iovec" from user memory and
+	 * verify all the pointers
+	 */
+	if (!count)
+		return 0;
+	if(verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+		return -EFAULT;
+	if (count > UIO_MAXIOV)
+		return -EINVAL;
+	if (count > UIO_FASTIOV) {
+		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
+		if (!iov)
+			return -ENOMEM;
+	}
+
+	tot_len = 0;
+	i = count;
+	ivp = iov;
+	while (i > 0) {
+		u32 len;
+		u32 buf;
+
+		__get_user(len, &vector->iov_len);
+		__get_user(buf, &vector->iov_base);
+		tot_len += len;
+		ivp->iov_base = (void *)A(buf);
+		ivp->iov_len = (__kernel_size_t) len;
+		vector++;
+		ivp++;
+		i--;
+	}
+
+	inode = file->f_dentry->d_inode;
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	retval = locks_verify_area((type == VERIFY_WRITE
+				    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
+				   inode, file, file->f_pos, tot_len);
+	if (retval) {
+		if (iov != iovstack)
+			kfree(iov);
+		return retval;
+	}
+
+	/* Then do the actual IO.  Note that sockets need to be handled
+	 * specially as they have atomicity guarantees and can handle
+	 * iovec's natively
+	 */
+	if (inode->i_sock) {
+		int err;
+		err = sock_readv_writev(type, inode, file, iov, count, tot_len);
+		if (iov != iovstack)
+			kfree(iov);
+		return err;
+	}
+
+	if (!file->f_op) {
+		if (iov != iovstack)
+			kfree(iov);
+		return -EINVAL;
+	}
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	fn = file->f_op->read;
+	if (type == VERIFY_READ)
+		fn = (IO_fn_t) file->f_op->write;		
+	ivp = iov;
+	while (count > 0) {
+		void * base;
+		int len, nr;
+
+		base = ivp->iov_base;
+		len = ivp->iov_len;
+		ivp++;
+		count--;
+		nr = fn(file, base, len, &file->f_pos);
+		if (nr < 0) {
+			if (retval)
+				break;
+			retval = nr;
+			break;
+		}
+		retval += nr;
+		if (nr != len)
+			break;
+	}
+	if (iov != iovstack)
+		kfree(iov);
+
+	return retval;
+}
+
+asmlinkage long
+sys32_readv(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	ssize_t ret;
+
+	ret = -EBADF;
+	file = fget(fd);
+	if (!file)
+		goto bad_file;
+	if (file->f_op && (file->f_mode & FMODE_READ) &&
+	    (file->f_op->readv || file->f_op->read))
+		ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
+
+	fput(file);
+
+bad_file:
+	return ret;
+}
+
+asmlinkage long
+sys32_writev(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	ssize_t ret;
+
+	ret = -EBADF;
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+	    (file->f_op->writev || file->f_op->write))
+	        ret = do_readv_writev32(VERIFY_READ, file, vector, count);
+	fput(file);
+
+bad_file:
+	return ret;
+}
+
+/********** Borrowed from sparc64 -- hardly reviewed, not tested *****/
+#include <net/scm.h>
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+					   16 for IP, 16 for IPX,
+					   24 for IPv6,
+					   about 80 for AX.25 */
+
+extern struct socket *sockfd_lookup(int fd, int *err);
+
+/* XXX This as well... */
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+	fput(sock->file);
+}
+
+struct msghdr32 {
+        u32               msg_name;
+        int               msg_namelen;
+        u32               msg_iov;
+        __kernel_size_t32 msg_iovlen;
+        u32               msg_control;
+        __kernel_size_t32 msg_controllen;
+        unsigned          msg_flags;
+};
+
+struct cmsghdr32 {
+        __kernel_size_t32 cmsg_len;
+        int               cmsg_level;
+        int               cmsg_type;
+};
+
+/* Bleech... */
+#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
+#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
+#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
+
+#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
+				    (struct cmsghdr32 *)(ctl) : \
+				    (struct cmsghdr32 *)NULL)
+#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
+					      struct cmsghdr32 *__cmsg, int __cmsg_len)
+{
+	struct cmsghdr32 * __ptr;
+
+	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
+				     CMSG32_ALIGN(__cmsg_len));
+	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+		return NULL;
+
+	return __ptr;
+}
+
+__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
+					    struct cmsghdr32 *__cmsg,
+					    int __cmsg_len)
+{
+	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
+			       __cmsg, __cmsg_len);
+}
+
+static inline int iov_from_user32_to_kern(struct iovec *kiov,
+					  struct iovec32 *uiov32,
+					  int niov)
+{
+	int tot_len = 0;
+
+	while(niov > 0) {
+		u32 len, buf;
+
+		if(get_user(len, &uiov32->iov_len) ||
+		   get_user(buf, &uiov32->iov_base)) {
+			tot_len = -EFAULT;
+			break;
+		}
+		tot_len += len;
+		kiov->iov_base = (void *)A(buf);
+		kiov->iov_len = (__kernel_size_t) len;
+		uiov32++;
+		kiov++;
+		niov--;
+	}
+	return tot_len;
+}
+
+static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+					     struct msghdr32 *umsg)
+{
+	u32 tmp1, tmp2, tmp3;
+	int err;
+
+	err = get_user(tmp1, &umsg->msg_name);
+	err |= __get_user(tmp2, &umsg->msg_iov);
+	err |= __get_user(tmp3, &umsg->msg_control);
+	if (err)
+		return -EFAULT;
+
+	kmsg->msg_name = (void *)A(tmp1);
+	kmsg->msg_iov = (struct iovec *)A(tmp2);
+	kmsg->msg_control = (void *)A(tmp3);
+
+	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
+	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+	
+	return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
+			  char *kern_address, int mode)
+{
+	int tot_len;
+
+	if(kern_msg->msg_namelen) {
+		if(mode==VERIFY_READ) {
+			int err = move_addr_to_kernel(kern_msg->msg_name,
+						      kern_msg->msg_namelen,
+						      kern_address);
+			if(err < 0)
+				return err;
+		}
+		kern_msg->msg_name = kern_address;
+	} else
+		kern_msg->msg_name = NULL;
+
+	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+				   GFP_KERNEL);
+		if(!kern_iov)
+			return -ENOMEM;
+	}
+
+	tot_len = iov_from_user32_to_kern(kern_iov,
+					  (struct iovec32 *)kern_msg->msg_iov,
+					  kern_msg->msg_iovlen);
+	if(tot_len >= 0)
+		kern_msg->msg_iov = kern_iov;
+	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+		kfree(kern_iov);
+
+	return tot_len;
+}
+
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps.  -DaveM
+ */
+static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
+				       unsigned char *stackbuf, int stackbuf_size)
+{
+	struct cmsghdr32 *ucmsg;
+	struct cmsghdr *kcmsg, *kcmsg_base;
+	__kernel_size_t32 ucmlen;
+	__kernel_size_t kcmlen, tmp;
+
+	kcmlen = 0;
+	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+	ucmsg = CMSG32_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		if(get_user(ucmlen, &ucmsg->cmsg_len))
+			return -EFAULT;
+
+		/* Catch bogons. */
+		if(CMSG32_ALIGN(ucmlen) <
+		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
+			return -EINVAL;
+		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+				   + ucmlen) > kmsg->msg_controllen)
+			return -EINVAL;
+
+		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmlen += tmp;
+		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+	if(kcmlen == 0)
+		return -EINVAL;
+
+	/* The kcmlen holds the 64-bit version of the control length.
+	 * It may not be modified as we do not stick it into the kmsg
+	 * until we have successfully copied over all of the data
+	 * from the user.
+	 */
+	if(kcmlen > stackbuf_size)
+		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+	if(kcmsg == NULL)
+		return -ENOBUFS;
+
+	/* Now copy them over neatly. */
+	memset(kcmsg, 0, kcmlen);
+	ucmsg = CMSG32_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		__get_user(ucmlen, &ucmsg->cmsg_len);
+		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmsg->cmsg_len = tmp;
+		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+		/* Copy over the data. */
+		if(copy_from_user(CMSG_DATA(kcmsg),
+				  CMSG32_DATA(ucmsg),
+				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+			goto out_free_efault;
+
+		/* Advance. */
+		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+
+	/* Ok, looks like we made it.  Hook it up and return success. */
+	kmsg->msg_control = kcmsg_base;
+	kmsg->msg_controllen = kcmlen;
+	return 0;
+
+out_free_efault:
+	if(kcmsg_base != (struct cmsghdr *)stackbuf)
+		kfree(kcmsg_base);
+	return -EFAULT;
+}
+
+static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+		       int len, void *data)
+{
+	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+	struct cmsghdr32 cmhdr;
+	int cmlen = CMSG32_LEN(len);
+
+	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		return;
+	}
+
+	if(kmsg->msg_controllen < cmlen) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		cmlen = kmsg->msg_controllen;
+	}
+	cmhdr.cmsg_level = level;
+	cmhdr.cmsg_type = type;
+	cmhdr.cmsg_len = cmlen;
+
+	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+		return;
+	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
+		return;
+	cmlen = CMSG32_SPACE(len);
+	kmsg->msg_control += cmlen;
+	kmsg->msg_controllen -= cmlen;
+}
+
+static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
+	int fdnum = scm->fp->count;
+	struct file **fp = scm->fp->fp;
+	int *cmfptr;
+	int err = 0, i;
+
+	if (fdnum < fdmax)
+		fdmax = fdnum;
+
+	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
+		int new_fd;
+		err = get_unused_fd();
+		if (err < 0)
+			break;
+		new_fd = err;
+		err = put_user(new_fd, cmfptr);
+		if (err) {
+			put_unused_fd(new_fd);
+			break;
+		}
+		/* Bump the usage count and install the file. */
+		get_file(fp[i]);
+		fd_install(new_fd, fp[i]);
+	}
+
+	if (i > 0) {
+		int cmlen = CMSG32_LEN(i * sizeof(int));
+		if (!err)
+			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		if (!err)
+			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+		if (!err)
+			err = put_user(cmlen, &cm->cmsg_len);
+		if (!err) {
+			cmlen = CMSG32_SPACE(i * sizeof(int));
+			kmsg->msg_control += cmlen;
+			kmsg->msg_controllen -= cmlen;
+		}
+	}
+	if (i < fdnum)
+		kmsg->msg_flags |= MSG_CTRUNC;
+
+	/*
+	 * All of the files that fit in the message have had their
+	 * usage counts incremented, so we just free the list.
+	 */
+	__scm_destroy(scm);
+}
+
+/* In these cases we (currently) can just copy to data over verbatim
+ * because all CMSGs created by the kernel have well defined types which
+ * have the same layout in both the 32-bit and 64-bit API.  One must add
+ * some special cased conversions here if we start sending control messages
+ * with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
+ * we do our work.  The remaining cases are:
+ *
+ * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
+ *		IP_TTL		int			32-bit clean
+ *		IP_TOS		__u8			32-bit clean
+ *		IP_RECVOPTS	variable length		32-bit clean
+ *		IP_RETOPTS	variable length		32-bit clean
+ *		(these last two are clean because the types are defined
+ *		 by the IPv4 protocol)
+ *		IP_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in	32-bit clean
+ * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in6	32-bit clean
+ *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
+ *		IPV6_HOPLIMIT	int			32-bit clean
+ *		IPV6_FLOWINFO	u32			32-bit clean
+ *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
+ *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
+ *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
+ *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
+ */
+static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+	unsigned char *workbuf, *wp;
+	unsigned long bufsz, space_avail;
+	struct cmsghdr *ucmsg;
+
+	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+	space_avail = kmsg->msg_controllen + bufsz;
+	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+	if(workbuf == NULL)
+		goto fail;
+
+	/* To make this more sane we assume the kernel sends back properly
+	 * formatted control messages.  Because of how the kernel will truncate
+	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+	 */
+	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+	while(((unsigned long)ucmsg) <=
+	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
+		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
+		int clen64, clen32;
+
+		/* UCMSG is the 64-bit format CMSG entry in user-space.
+		 * KCMSG32 is within the kernel space temporary buffer
+		 * we use to convert into a 32-bit style CMSG.
+		 */
+		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
+		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
+
+		clen64 = kcmsg32->cmsg_len;
+		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
+			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+		kcmsg32->cmsg_len = clen32;
+
+		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
+		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
+	}
+
+	/* Copy back fixed up data, and adjust pointers. */
+	bufsz = (wp - workbuf);
+	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
+
+	kmsg->msg_control = (struct cmsghdr *)
+		(((char *)orig_cmsg_uptr) + bufsz);
+	kmsg->msg_controllen = space_avail - bufsz;
+
+	kfree(workbuf);
+	return;
+
+fail:
+	/* If we leave the 64-bit format CMSG chunks in there,
+	 * the application could get confused and crash.  So to
+	 * ensure greater recovery, we report no CMSGs.
+	 */
+	kmsg->msg_controllen += bufsz;
+	kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
+asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
+{
+	struct socket *sock;
+	char address[MAX_SOCK_ADDR];
+	struct iovec iov[UIO_FASTIOV];
+	unsigned char ctl[sizeof(struct cmsghdr) + 20];
+	unsigned char *ctl_buf = ctl;
+	struct msghdr kern_msg;
+	int err, total_len;
+
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+		return -EFAULT;
+	if(kern_msg.msg_iovlen > UIO_MAXIOV)
+		return -EINVAL;
+	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+	if (err < 0)
+		goto out;
+	total_len = err;
+
+	if(kern_msg.msg_controllen) {
+		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
+		if(err)
+			goto out_freeiov;
+		ctl_buf = kern_msg.msg_control;
+	}
+	kern_msg.msg_flags = user_flags;
+
+	sock = sockfd_lookup(fd, &err);
+	if (sock != NULL) {
+		if (sock->file->f_flags & O_NONBLOCK)
+			kern_msg.msg_flags |= MSG_DONTWAIT;
+		err = sock_sendmsg(sock, &kern_msg, total_len);
+		sockfd_put(sock);
+	}
+
+	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
+	if(ctl_buf != ctl)
+		kfree(ctl_buf);
+out_freeiov:
+	if(kern_msg.msg_iov != iov)
+		kfree(kern_msg.msg_iov);
+out:
+	return err;
+}
+
+asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
+{
+	struct iovec iovstack[UIO_FASTIOV];
+	struct msghdr kern_msg;
+	char addr[MAX_SOCK_ADDR];
+	struct socket *sock;
+	struct iovec *iov = iovstack;
+	struct sockaddr *uaddr;
+	int *uaddr_len;
+	unsigned long cmsg_ptr;
+	int err, total_len, len = 0;
+
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+		return -EFAULT;
+	if(kern_msg.msg_iovlen > UIO_MAXIOV)
+		return -EINVAL;
+
+	uaddr = kern_msg.msg_name;
+	uaddr_len = &user_msg->msg_namelen;
+	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+	if (err < 0)
+		goto out;
+	total_len = err;
+
+	cmsg_ptr = (unsigned long) kern_msg.msg_control;
+	kern_msg.msg_flags = 0;
+
+	sock = sockfd_lookup(fd, &err);
+	if (sock != NULL) {
+		struct scm_cookie scm;
+
+		if (sock->file->f_flags & O_NONBLOCK)
+			user_flags |= MSG_DONTWAIT;
+		memset(&scm, 0, sizeof(scm));
+		err = sock->ops->recvmsg(sock, &kern_msg, total_len,
+					 user_flags, &scm);
+		if(err >= 0) {
+			len = err;
+			if(!kern_msg.msg_control) {
+				if(sock->passcred || scm.fp)
+					kern_msg.msg_flags |= MSG_CTRUNC;
+				if(scm.fp)
+					__scm_destroy(&scm);
+			} else {
+				/* If recvmsg processing itself placed some
+				 * control messages into user space, it's is
+				 * using 64-bit CMSG processing, so we need
+				 * to fix it up before we tack on more stuff.
+				 */
+				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
+					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
+
+				/* Wheee... */
+				if(sock->passcred)
+					put_cmsg32(&kern_msg,
+						   SOL_SOCKET, SCM_CREDENTIALS,
+						   sizeof(scm.creds), &scm.creds);
+				if(scm.fp != NULL)
+					scm_detach_fds32(&kern_msg, &scm);
+			}
+		}
+		sockfd_put(sock);
+	}
+
+	if(uaddr != NULL && err >= 0)
+		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
+	if(cmsg_ptr != 0 && err >= 0) {
+		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
+		__kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
+		err |= __put_user(uclen, &user_msg->msg_controllen);
+	}
+	if(err >= 0)
+		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
+	if(kern_msg.msg_iov != iov)
+		kfree(kern_msg.msg_iov);
+out:
+	if(err < 0)
+		return err;
+	return len;
+}
+
+
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+				     char *optval, int optlen);
+
+static int do_set_attach_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	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;
+}
+
+static int do_set_icmpv6_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct icmp6_filter kfilter;
+	mm_segment_t old_fs;
+	int ret, i;
+
+	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
+		return -EFAULT;
+
+
+	for (i = 0; i < 8; i += 2) {
+		u32 tmp = kfilter.data[i];
+
+		kfilter.data[i] = kfilter.data[i + 1];
+		kfilter.data[i + 1] = tmp;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *) &kfilter, sizeof(kfilter));
+	set_fs(old_fs);
+
+	return ret;
+}
+
+
+static int do_ipv4_set_replace(int fd, int level, int optname,
+				char *optval, int optlen)
+#if 1
+/* Fields happen to be padded such that this works.
+** Don't need to change iptables.h:struct ipt_replace
+*/
+{
+	struct ipt_replace *repl = (struct ipt_replace *) optval;
+	unsigned long ptr64;
+	unsigned int ptr32;
+	int ret;
+
+	if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32)))
+		return -EFAULT;
+	ptr64 = (unsigned long) ptr32;
+	if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64)))
+		return -EFAULT;
+
+	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);
+
+	/* Restore 32-bit ptr */
+	if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32)))
+		return -EFAULT;
+
+	return ret;
+}
+#else
+/* This version tries to "do it right". ie allocate kernel buffers for
+** everything and copy data in/out. Way too complicated.
+** NOT TESTED for correctness!
+*/
+{
+	struct ipt_replace  *kern_repl;
+	struct ipt_counters *kern_counters;
+	unsigned int user_counters;
+	mm_segment_t old_fs;
+	int ret = 0;
+
+	kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL);
+	if (!kern_repl)
+		return -ENOMEM;
+
+	if (copy_from_user(kern_repl, optval, optlen)) {
+		ret = -EFAULT;
+		goto err02;
+	}
+
+	/* 32-bit ptr is in the MSB's */
+	user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32);
+	/*
+	** We are going to set_fs() to kernel space - and thus need
+	** "relocate" the counters buffer to the kernel space.
+	*/
+	kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL);
+	if (!user_counters) {
+		ret = -ENOMEM;
+		goto err02;
+	}
+
+	if (copy_from_user(kern_counters, (char *) user_counters, optlen)) {
+		ret = -EFAULT;
+		goto err01;
+	}
+
+	/* We can update the kernel ptr now that we have the data. */
+	kern_repl->counters = kern_counters;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);
+
+	set_fs(old_fs);
+
+	/* Copy counters back out to user space */
+	if (copy_to_user((char *) user_counters, kern_counters,
+			kern_repl->num_counters * sizeof(struct ipt_counters)))
+	{
+		ret = -EFAULT;
+		goto err01;
+	}
+
+	/* restore counters so userspace can consume it */
+	kern_repl->counters = NULL;
+	(unsigned int) kern_repl->counters = user_counters;
+
+	/* Copy repl back out to user space */
+	if (copy_to_user(optval, kern_repl, optlen))
+	{
+		ret = -EFAULT;
+	}
+
+err01:
+	kfree(kern_counters);
+err02:
+	kfree(kern_repl);
+	return ret;
+}
+#endif
+
+
+asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	if (optname == SO_ATTACH_FILTER)
+		return do_set_attach_filter(fd, level, optname, optval, optlen);
+
+	if (level == SOL_ICMPV6   && optname == ICMPV6_FILTER)
+		return do_set_icmpv6_filter(fd, level, optname, optval, optlen);
+
+	/*
+	** Beware:    IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE
+	*/
+	if (level == IPPROTO_IP   && optname == IPT_SO_SET_REPLACE)
+		return do_ipv4_set_replace(fd, level, optname, optval, optlen);
+
+	if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE)
+#if 0
+		/* FIXME: I don't (yet) use IPV6. -ggg */
+		return do_ipv6_set_replace(fd, level, optname, optval, optlen);
+#else
+	{
+		BUG();
+		return -ENXIO;
+	}
+#endif
+
+	return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
+
+/*** copied from mips64 ***/
+/*
+ * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
+
+static inline int
+get_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+	if (ufdset) {
+		unsigned long odd;
+
+		if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+			return -EFAULT;
+
+		odd = n & 1UL;
+		n &= ~1UL;
+		while (n) {
+			unsigned long h, l;
+			__get_user(l, ufdset);
+			__get_user(h, ufdset+1);
+			ufdset += 2;
+			*fdset++ = h << 32 | l;
+			n -= 2;
+		}
+		if (odd)
+			__get_user(*fdset, ufdset);
+	} else {
+		/* Tricky, must clear full unsigned long in the
+		 * kernel fdset at the end, this makes sure that
+		 * actually happens.
+		 */
+		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
+	}
+	return 0;
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+	unsigned long odd;
+	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+
+	if (!ufdset)
+		return;
+
+	odd = n & 1UL;
+	n &= ~1UL;
+	while (n) {
+		unsigned long h, l;
+		l = *fdset++;
+		h = l >> 32;
+		__put_user(l, ufdset);
+		__put_user(h, ufdset+1);
+		ufdset += 2;
+		n -= 2;
+	}
+	if (odd)
+		__put_user(*fdset, ufdset);
+}
+
+/*** This is a virtual copy of sys_select from fs/select.c and probably
+ *** should be compared to it from time to time
+ ***/
+static inline void *select_bits_alloc(int size)
+{
+	return kmalloc(6 * size, GFP_KERNEL);
+}
+
+static inline void select_bits_free(void *bits, int size)
+{
+	kfree(bits);
+}
+
+/*
+ * We can actually return ERESTARTSYS instead of EINTR, but I'd
+ * like to be certain this leads to no problems. So I return
+ * EINTR just for safety.
+ *
+ * Update: ERESTARTSYS breaks at least the xview clock binary, so
+ * I'm trying ERESTARTNOHAND which restart only when you want to.
+ */
+#define MAX_SELECT_SECONDS \
+	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+#define DIVIDE_ROUND_UP(x,y) (((x)+(y)-1)/(y))
+
+asmlinkage long
+sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct timeval32 *tvp)
+{
+	fd_set_bits fds;
+	char *bits;
+	long timeout;
+	int ret, size, err;
+
+	timeout = MAX_SCHEDULE_TIMEOUT;
+	if (tvp) {
+		struct timeval32 tv32;
+		time_t sec, usec;
+
+		if ((ret = copy_from_user(&tv32, tvp, sizeof tv32)))
+			goto out_nofds;
+
+		sec = tv32.tv_sec;
+		usec = tv32.tv_usec;
+
+		ret = -EINVAL;
+		if (sec < 0 || usec < 0)
+			goto out_nofds;
+
+		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+			timeout = DIVIDE_ROUND_UP(usec, 1000000/HZ);
+			timeout += sec * (unsigned long) HZ;
+		}
+	}
+
+	ret = -EINVAL;
+	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),
+	 * since we used fdset we need to allocate memory in units of
+	 * long-words. 
+	 */
+	ret = -ENOMEM;
+	size = FDS_BYTES(n);
+	bits = select_bits_alloc(size);
+	if (!bits)
+		goto out_nofds;
+	fds.in      = (unsigned long *)  bits;
+	fds.out     = (unsigned long *) (bits +   size);
+	fds.ex      = (unsigned long *) (bits + 2*size);
+	fds.res_in  = (unsigned long *) (bits + 3*size);
+	fds.res_out = (unsigned long *) (bits + 4*size);
+	fds.res_ex  = (unsigned long *) (bits + 5*size);
+
+	if ((ret = get_fd_set32(n, inp, fds.in)) ||
+	    (ret = get_fd_set32(n, outp, fds.out)) ||
+	    (ret = get_fd_set32(n, exp, fds.ex)))
+		goto out;
+	zero_fd_set(n, fds.res_in);
+	zero_fd_set(n, fds.res_out);
+	zero_fd_set(n, fds.res_ex);
+
+	ret = do_select(n, &fds, &timeout);
+
+	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
+		time_t sec = 0, usec = 0;
+		if (timeout) {
+			sec = timeout / HZ;
+			usec = timeout % HZ;
+			usec *= (1000000/HZ);
+		}
+		err = put_user(sec, &tvp->tv_sec);
+		err |= __put_user(usec, &tvp->tv_usec);
+		if (err)
+			ret = -EFAULT;
+	}
+
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
+		if (signal_pending(current))
+			goto out;
+		ret = 0;
+	}
+
+	set_fd_set32(n, inp, fds.res_in);
+	set_fd_set32(n, outp, fds.res_out);
+	set_fd_set32(n, exp, fds.res_ex);
+
+out:
+	select_bits_free(bits, size);
+out_nofds:
+	return ret;
+}
+
+struct msgbuf32 {
+    int mtype;
+    char mtext[1];
+};
+
+asmlinkage long sys32_msgsnd(int msqid,
+				struct msgbuf32 *umsgp32,
+				size_t msgsz, int msgflg)
+{
+	struct msgbuf *mb;
+	struct msgbuf32 mb32;
+	int err;
+
+	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	err = get_user(mb32.mtype, &umsgp32->mtype);
+	mb->mtype = mb32.mtype;
+	err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz);
+
+	if (err)
+		err = -EFAULT;
+	else
+		KERNEL_SYSCALL(err, sys_msgsnd, msqid, mb, msgsz, msgflg);
+
+	kfree(mb);
+	return err;
+}
+
+asmlinkage long sys32_msgrcv(int msqid,
+				struct msgbuf32 *umsgp32,
+				size_t msgsz, long msgtyp, int msgflg)
+{
+	struct msgbuf *mb;
+	struct msgbuf32 mb32;
+	int err, len;
+
+	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)
+		return -ENOMEM;
+
+	KERNEL_SYSCALL(err, sys_msgrcv, msqid, mb, msgsz, msgtyp, msgflg);
+
+	if (err >= 0) {
+		len = err;
+		mb32.mtype = mb->mtype;
+		err = put_user(mb32.mtype, &umsgp32->mtype);
+		err |= copy_to_user(&umsgp32->mtext, mb->mtext, len);
+		if (err)
+			err = -EFAULT;
+		else
+			err = len;
+	}
+
+	kfree(mb);
+	return err;
+}
+
+/* LFS */
+
+extern asmlinkage long sys_truncate(const char *, loff_t);
+extern asmlinkage long sys_ftruncate(unsigned int, loff_t);
+extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
+extern asmlinkage ssize_t sys_pread(unsigned int, char *, size_t, loff_t);
+extern asmlinkage ssize_t sys_pwrite(unsigned int, char *, size_t, loff_t);
+
+asmlinkage long sys32_truncate64(const char * path, unsigned int high, unsigned int low)
+{
+	return sys_truncate(path, (loff_t)high << 32 | low);
+}
+
+asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned int high, unsigned int low)
+{
+	return sys_ftruncate(fd, (loff_t)high << 32 | low);
+}
+
+asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+		case F_GETLK64:
+			cmd = F_GETLK;
+			break;
+		case F_SETLK64:
+			cmd = F_SETLK;
+			break;
+		case F_SETLKW64:
+			cmd = F_SETLKW;
+			break;
+		default:
+			break;
+	}
+	return sys_fcntl(fd, cmd, arg);
+}
+
+asmlinkage int sys32_pread(int fd, void *buf, size_t count, unsigned int high, unsigned int low)
+{
+	return sys_pread(fd, buf, count, (loff_t)high << 32 | low);
+}
+
+asmlinkage int sys32_pwrite(int fd, void *buf, size_t count, unsigned int high, unsigned int low)
+{
+       return sys_pwrite(fd, buf, count, (loff_t)high << 32 | low);
+}
+
+/* EXPORT/UNEXPORT */
+struct nfsctl_export32 {
+	char			ex_client[NFSCLNT_IDMAX+1];
+	char			ex_path[NFS_MAXPATHLEN+1];
+	__kernel_dev_t		ex_dev;
+	__kernel_ino_t32	ex_ino;
+	int			ex_flags;
+	__kernel_uid_t		ex_anon_uid;
+	__kernel_gid_t		ex_anon_gid;
+};
+
+/* GETFH */
+struct nfsctl_fhparm32 {
+	struct sockaddr		gf_addr;
+	__kernel_dev_t		gf_dev;
+	__kernel_ino_t32	gf_ino;
+	int			gf_version;
+};
+
+/* UGIDUPDATE */
+struct nfsctl_uidmap32 {
+	__kernel_caddr_t32	ug_ident;
+	__kernel_uid_t		ug_uidbase;
+	int			ug_uidlen;
+	__kernel_caddr_t32	ug_udimap;
+	__kernel_gid_t		ug_gidbase;
+	int			ug_gidlen;
+	__kernel_caddr_t32	ug_gdimap;
+};
+
+struct nfsctl_arg32 {
+	int			ca_version;	/* safeguard */
+	/* wide kernel places this union on 8-byte boundary, narrow on 4 */
+	union {
+		struct nfsctl_svc	u_svc;
+		struct nfsctl_client	u_client;
+		struct nfsctl_export32	u_export;
+		struct nfsctl_uidmap32	u_umap;
+		struct nfsctl_fhparm32	u_getfh;
+		struct nfsctl_fdparm	u_getfd;
+		struct nfsctl_fsparm	u_getfs;
+	} u;
+};
+
+asmlinkage int sys32_nfsservctl(int cmd, void *argp, void *resp)
+{
+	int ret, tmp;
+	struct nfsctl_arg32 n32;
+	struct nfsctl_arg n;
+
+	ret = copy_from_user(&n, argp, sizeof n.ca_version);
+	if (ret != 0)
+		return ret;
+
+	/* adjust argp to point at the union inside the user's n32 struct */
+	tmp = (unsigned long)&n32.u - (unsigned long)&n32;
+	argp = (void *)((unsigned long)argp + tmp);
+	switch(cmd) {
+	case NFSCTL_SVC:
+		ret = copy_from_user(&n.u, argp, sizeof n.u.u_svc);
+		break;
+
+	case NFSCTL_ADDCLIENT:
+	case NFSCTL_DELCLIENT:
+		ret = copy_from_user(&n.u, argp, sizeof n.u.u_client);
+		break;
+
+	case NFSCTL_GETFD:
+		ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfd);
+		break;
+
+	case NFSCTL_GETFS:
+		ret = copy_from_user(&n.u, argp, sizeof n.u.u_getfs);
+		break;
+
+	case NFSCTL_GETFH:		/* nfsctl_fhparm */
+		ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_getfh);
+#undef CP
+#define CP(x)	n.u.u_getfh.gf_##x = n32.u.u_getfh.gf_##x
+		CP(addr);
+		CP(dev);
+		CP(ino);
+		CP(version);
+		break;
+
+	case NFSCTL_UGIDUPDATE:		/* nfsctl_uidmap */
+		ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_umap);
+#undef CP
+#define CP(x)	n.u.u_umap.ug_##x = n32.u.u_umap.ug_##x
+		n.u.u_umap.ug_ident = (char *)(u_long)n32.u.u_umap.ug_ident;
+		CP(uidbase);
+		CP(uidlen);
+		n.u.u_umap.ug_udimap = (__kernel_uid_t *)(u_long)n32.u.u_umap.ug_udimap;
+		CP(gidbase);
+		CP(gidlen);
+		n.u.u_umap.ug_gdimap = (__kernel_gid_t *)(u_long)n32.u.u_umap.ug_gdimap;
+		break;
+
+	case NFSCTL_UNEXPORT:		/* nfsctl_export */
+	case NFSCTL_EXPORT:		/* nfsctl_export */
+		ret = copy_from_user(&n32.u, argp, sizeof n32.u.u_export);
+#undef CP
+#define CP(x)	n.u.u_export.ex_##x = n32.u.u_export.ex_##x
+		memcpy(n.u.u_export.ex_client, n32.u.u_export.ex_client, sizeof n32.u.u_export.ex_client);
+		memcpy(n.u.u_export.ex_path, n32.u.u_export.ex_path, sizeof n32.u.u_export.ex_path);
+		CP(dev);
+		CP(ino);
+		CP(flags);
+		CP(anon_uid);
+		CP(anon_gid);
+		break;
+
+	default:
+		BUG(); /* new cmd values to be translated... */
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret == 0) {
+		unsigned char rbuf[NFS_FHSIZE + sizeof (struct knfsd_fh)];
+		KERNEL_SYSCALL(ret, sys_nfsservctl, cmd, &n, &rbuf);
+		if (cmd == NFSCTL_GETFH || cmd == NFSCTL_GETFD) {
+			ret = copy_to_user(resp, rbuf, NFS_FHSIZE);
+		} else if (cmd == NFSCTL_GETFS) {
+			ret = copy_to_user(resp, rbuf, sizeof (struct knfsd_fh));
+		}
+	}
+
+	return ret;
+}
+
+#include <linux/quota.h>
+
+struct dqblk32 {
+    __u32 dqb_bhardlimit;
+    __u32 dqb_bsoftlimit;
+    __u32 dqb_curblocks;
+    __u32 dqb_ihardlimit;
+    __u32 dqb_isoftlimit;
+    __u32 dqb_curinodes;
+    __kernel_time_t32 dqb_btime;
+    __kernel_time_t32 dqb_itime;
+};
+                                
+
+asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
+{
+	extern int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
+	int cmds = cmd >> SUBCMDSHIFT;
+	int err;
+	struct dqblk d;
+	char *spec;
+	
+	switch (cmds) {
+	case Q_GETQUOTA:
+		break;
+	case Q_SETQUOTA:
+	case Q_SETUSE:
+	case Q_SETQLIM:
+		if (copy_from_user (&d, (struct dqblk32 *)addr,
+				    sizeof (struct dqblk32)))
+			return -EFAULT;
+		d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
+		d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
+		break;
+	default:
+		return sys_quotactl(cmd, special,
+				    id, (caddr_t)addr);
+	}
+	spec = getname (special);
+	err = PTR_ERR(spec);
+	if (IS_ERR(spec)) return err;
+	KERNEL_SYSCALL(err, sys_quotactl, cmd, (const char *)spec, id, (caddr_t)&d);
+	putname (spec);
+	if (cmds == Q_GETQUOTA) {
+		__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
+		((struct dqblk32 *)&d)->dqb_itime = i;
+		((struct dqblk32 *)&d)->dqb_btime = b;
+		if (copy_to_user ((struct dqblk32 *)addr, &d,
+				  sizeof (struct dqblk32)))
+			return -EFAULT;
+	}
+	return err;
+}
+
+struct timex32 {
+	unsigned int modes;	/* mode selector */
+	int offset;		/* time offset (usec) */
+	int freq;		/* frequency offset (scaled ppm) */
+	int maxerror;		/* maximum error (usec) */
+	int esterror;		/* estimated error (usec) */
+	int status;		/* clock command/status */
+	int constant;		/* pll time constant */
+	int precision;		/* clock precision (usec) (read only) */
+	int tolerance;		/* clock frequency tolerance (ppm)
+				 * (read only)
+				 */
+	struct timeval32 time;	/* (read only) */
+	int tick;		/* (modified) usecs between clock ticks */
+
+	int ppsfreq;           /* pps frequency (scaled ppm) (ro) */
+	int jitter;            /* pps jitter (us) (ro) */
+	int shift;              /* interval duration (s) (shift) (ro) */
+	int stabil;            /* pps stability (scaled ppm) (ro) */
+	int jitcnt;            /* jitter limit exceeded (ro) */
+	int calcnt;            /* calibration intervals (ro) */
+	int errcnt;            /* calibration errors (ro) */
+	int stbcnt;            /* stability limit exceeded (ro) */
+
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+	int  :32; int  :32; int  :32; int  :32;
+};
+
+asmlinkage long sys32_adjtimex(struct timex32 *txc_p32)
+{
+	struct timex txc;
+	struct timex32 t32;
+	int ret;
+	extern int do_adjtimex(struct timex *txc);
+
+	if(copy_from_user(&t32, txc_p32, sizeof(struct timex32)))
+		return -EFAULT;
+#undef CP
+#define CP(x) txc.x = t32.x
+	CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
+	CP(status); CP(constant); CP(precision); CP(tolerance);
+	CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
+	CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
+	CP(stbcnt);
+	ret = do_adjtimex(&txc);
+#define CP(x) t32.x = txc.x
+	CP(modes); CP(offset); CP(freq); CP(maxerror); CP(esterror);
+	CP(status); CP(constant); CP(precision); CP(tolerance);
+	CP(time.tv_sec); CP(time.tv_usec); CP(tick); CP(ppsfreq); CP(jitter);
+	CP(shift); CP(stabil); CP(jitcnt); CP(calcnt); CP(errcnt);
+	CP(stbcnt);
+	return copy_to_user(txc_p32, &t32, sizeof(struct timex32)) ? -EFAULT : ret;
+}
+
+
+struct sysinfo32 {
+	s32 uptime;
+	u32 loads[3];
+	u32 totalram;
+	u32 freeram;
+	u32 sharedram;
+	u32 bufferram;
+	u32 totalswap;
+	u32 freeswap;
+	unsigned short procs;
+	u32 totalhigh;
+	u32 freehigh;
+	u32 mem_unit;
+	char _f[12];
+};
+
+/* We used to call sys_sysinfo and translate the result.  But sys_sysinfo
+ * undoes the good work done elsewhere, and rather than undoing the
+ * damage, I decided to just duplicate the code from sys_sysinfo here.
+ */
+
+asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
+{
+	struct sysinfo val;
+	int err;
+
+	/* We don't need a memset here because we copy the
+	 * struct to userspace once element at a time.
+	 */
+
+	cli();
+	val.uptime = jiffies / HZ;
+
+	val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
+	val.loads[1] = avenrun[1] << (SI_LOAD_SHIFT - FSHIFT);
+	val.loads[2] = avenrun[2] << (SI_LOAD_SHIFT - FSHIFT);
+
+	val.procs = nr_threads-1;
+	sti();
+
+	si_meminfo(&val);
+	si_swapinfo(&val);
+	
+	err = put_user (val.uptime, &info->uptime);
+	err |= __put_user (val.loads[0], &info->loads[0]);
+	err |= __put_user (val.loads[1], &info->loads[1]);
+	err |= __put_user (val.loads[2], &info->loads[2]);
+	err |= __put_user (val.totalram, &info->totalram);
+	err |= __put_user (val.freeram, &info->freeram);
+	err |= __put_user (val.sharedram, &info->sharedram);
+	err |= __put_user (val.bufferram, &info->bufferram);
+	err |= __put_user (val.totalswap, &info->totalswap);
+	err |= __put_user (val.freeswap, &info->freeswap);
+	err |= __put_user (val.procs, &info->procs);
+	err |= __put_user (val.totalhigh, &info->totalhigh);
+	err |= __put_user (val.freehigh, &info->freehigh);
+	err |= __put_user (val.mem_unit, &info->mem_unit);
+	return err ? -EFAULT : 0;
+}
+
+
+/* lseek() needs a wrapper because 'offset' can be negative, but the top
+ * half of the argument has been zeroed by syscall.S.
+ */
+
+extern asmlinkage off_t sys_lseek(unsigned int fd, off_t offset, unsigned int origin);
+
+asmlinkage int sys32_lseek(unsigned int fd, int offset, unsigned int origin)
+{
+	return sys_lseek(fd, offset, origin);
+}
+
+asmlinkage long sys32_semctl_broken(int semid, int semnum, int cmd, union semun arg)
+{
+        union semun u;
+	
+	cmd &= ~IPC_64; /* should be removed together with the _broken suffix */
+
+        if (cmd == SETVAL) {
+                /* Ugh.  arg is a union of int,ptr,ptr,ptr, so is 8 bytes.
+                 * The int should be in the first 4, but our argument
+                 * frobbing has left it in the last 4.
+                 */
+                u.val = *((int *)&arg + 1);
+                return sys_semctl (semid, semnum, cmd, u);
+	}
+	return sys_semctl (semid, semnum, cmd, arg);
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/syscall.S linux/arch/parisc/kernel/syscall.S
--- linux.orig/arch/parisc/kernel/syscall.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/parisc/kernel/syscall.S	2002-08-12 22:14:27.000000000 +0000
@@ -1,5 +1,5 @@
 /* 
- * Linux/PARISC Project (http://www.thepuffingroup.com/parisc)
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  * 
  * System call entry code Copyright (c) Matthew Wilcox 1999 <willy@bofh.ai>
  * Licensed under the GNU GPL.
@@ -12,7 +12,6 @@
 #include <asm/errno.h>
 #include <asm/psw.h>
 
-#define __ASSEMBLY__
 #include <asm/assembly.h>
 #include <asm/processor.h>
 #include <linux/version.h>
@@ -23,7 +22,13 @@
 	.level		1.1
 #endif
 	.text
-	
+
+#ifdef __LP64__
+#define FRAME_SIZE	128
+#else
+#define FRAME_SIZE	64
+#endif
+
 	.import syscall_exit,code
 	.import syscall_exit_rfi,code
 	.export linux_gateway_page
@@ -39,17 +44,30 @@
 	.align 4096
 linux_gateway_page:
 
+	.rept 56
 	break   0,0
+	.endr
 
+set_thread_pointer:
+	gate	.+8, %r0		/* increase privilege */
+	depi	3, 31, 2, %r31		/* Ensure we return into user mode. */
+	be	0(%sr7,%r31)		/* return to user space */
+	mtctl	%r26, %cr27		/* move arg0 to the control register */
+
+	.rept 4
+	break   0,0
+	.endr
+
+/* This address must remain fixed, or user binaries go splat. */
 	.align 256
 linux_gateway_entry:
-	mfsp	%sr7,%r1			/* we must set sr3 to the space */
-	mtsp	%r1,%sr3			/* of the user before the gate */
 	gate	.+8, %r0			/* become privileged */
 	mtsp	%r0,%sr4			/* get kernel space into sr4 */
 	mtsp	%r0,%sr5			/* get kernel space into sr5 */
 	mtsp	%r0,%sr6			/* get kernel space into sr6 */
-	mtsp	%r0,%sr7			/* get kernel space into sr7 */
+	mfsp    %sr7,%r1                        /* save user sr7 */
+	mtsp    %r1,%sr3                        /* and store it in sr3 */
+
 #ifdef __LP64__
 	/* for now we can *always* set the W bit on entry to the syscall
 	 * since we don't support wide userland processes.  We could
@@ -58,15 +76,38 @@
 	 * whether to do narrow or wide syscalls. -PB
 	 */
 	ssm	PSW_SM_W, %r0
+	/* The top halves of argument registers must be cleared on syscall
+	 * entry.
+	 */
+	depdi	0, 31, 32, %r26
+	depdi	0, 31, 32, %r25
+	depdi	0, 31, 32, %r24
+	depdi	0, 31, 32, %r23
+	depdi	0, 31, 32, %r22
+	depdi	0, 31, 32, %r21
 #endif
-	mtctl	%r28,%cr27
-	rsm	PSW_I, %r28			/* no ints for a bit  */
-	mfctl	%cr30,%r1			/* get the kernel task ptr */
-	mtctl	%r0,%cr30			/* zero it (flag) */
+	mfctl   %cr30,%r1
+	xor     %r1,%r30,%r30                   /* ye olde xor trick */
+	xor     %r1,%r30,%r1
+	xor     %r1,%r30,%r30
+	ldo     TASK_SZ_ALGN+FRAME_SIZE(%r30),%r30  /* set up kernel stack */
+
+	/* N.B.: It is critical that we don't set sr7 to 0 until r30
+	 *       contains a valid kernel stack pointer. It is also
+	 *       critical that we don't start using the kernel stack
+	 *       until after sr7 has been set to 0.
+	 */
+
+	mtsp	%r0,%sr7			/* get kernel space into sr7 */
+	STREG   %r1,TASK_PT_GR30-TASK_SZ_ALGN-FRAME_SIZE(%r30) /* save usp */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1   /* get task ptr in %r1 */
 
 	/* Save some registers for sigcontext and potential task
 	   switch (see entry.S for the details of which ones are
-	   saved/restored) */
+	   saved/restored).  TASK_PT_PSW is zeroed so we can see whether
+	   a process is on a syscall or not.  For an interrupt the real
+	   PSW value is stored.  This is needed for gdb and sys_ptrace. */
+	STREG	%r0,  TASK_PT_PSW(%r1)
 	STREG	%r2,  TASK_PT_GR2(%r1)		/* preserve rp */
 	STREG	%r19, TASK_PT_GR19(%r1)
 	STREG	%r20, TASK_PT_GR20(%r1)
@@ -77,11 +118,9 @@
 	STREG	%r25, TASK_PT_GR25(%r1)		/* 2nd argument */
 	STREG	%r26, TASK_PT_GR26(%r1)	 	/* 1st argument */
 	STREG	%r27, TASK_PT_GR27(%r1)		/* user dp */
-	mfctl	%cr27,%r19
-	STREG	%r19, TASK_PT_GR28(%r1)		/* return value 0 */
-	STREG	%r19, TASK_PT_ORIG_R28(%r1)	/* return value 0 (saved for signals) */
+	STREG   %r28, TASK_PT_GR28(%r1)         /* return value 0 */
+	STREG   %r28, TASK_PT_ORIG_R28(%r1)     /* return value 0 (saved for signals) */
 	STREG	%r29, TASK_PT_GR29(%r1)		/* return value 1 */
-	STREG	%r30, TASK_PT_GR30(%r1)		/* preserve userspace sp */
 	STREG	%r31, TASK_PT_GR31(%r1)		/* preserve syscall return ptr */
 	
 	ldo	TASK_PT_FR0(%r1), %r27		/* save fpregs from the kernel */
@@ -92,10 +131,10 @@
 
 	loadgp
 
-	ldo	TASK_SZ_ALGN+64(%r1),%r30	/* set up kernel stack */
-
-#ifndef __LP64__
-	/* no need to save these on stack because in wide mode the first 8
+#ifdef __LP64__
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#else
+	/* no need to save these on stack in wide mode because the first 8
 	 * args are passed in registers */
 	stw     %r22, -52(%r30)                 /* 5th argument */
 	stw     %r21, -56(%r30)                 /* 6th argument */
@@ -103,7 +142,6 @@
 
 	/* for some unknown reason, task_struct.ptrace is an unsigned long so use LDREG */
 	LDREG	TASK_PTRACE(%r1), %r19		/* Are we being ptraced? */
-	mtsm	%r28				/* irqs back  */
 
 	bb,<,n	%r19, 31, .Ltracesys		/* must match PT_PTRACE bit */
 	
@@ -112,7 +150,6 @@
 
 	ldil	L%sys_call_table, %r1
 	ldo     R%sys_call_table(%r1), %r19
-	LDIL_FIXUP(%r19)
 	
 	comiclr,>>=	__NR_Linux_syscalls, %r20, %r0
 	b,n	.Lsyscall_nosys
@@ -131,13 +168,11 @@
 	comb,=	%r2,%r20,.Lrt_sigreturn
 .Lin_syscall:
 	ldil	L%syscall_exit,%r2
-	LDIL_FIXUP(%r2)
 	be      0(%sr7,%r19)
 	ldo	R%syscall_exit(%r2),%r2
 .Lrt_sigreturn:
 	comib,<> 0,%r25,.Lin_syscall
 	ldil	L%syscall_exit_rfi,%r2
-	LDIL_FIXUP(%r2)
 	be      0(%sr7,%r19)
 	ldo	R%syscall_exit_rfi(%r2),%r2
 
@@ -149,7 +184,6 @@
 .Lsyscall_nosys:
 syscall_nosys:
 	ldil	L%syscall_exit,%r1
-	LDIL_FIXUP(%r1)
 	be	R%syscall_exit(%sr7,%r1)
 	ldo	-ENOSYS(%r0),%r28		   /* set errno */
 
@@ -159,12 +193,17 @@
 .Ltracesys:
 tracesys:
 	/* Need to save more registers so the debugger can see where we
-	 * are.
+	 * are.  This saves only the lower 8 bits of PSW, so that the C
+	 * bit is still clear on syscalls, and the D bit is set if this
+	 * full register save path has been executed.  We check the D
+	 * bit on syscall_return_rfi to determine which registers to
+	 * restore.  An interrupt results in a full PSW saved with the
+	 * C bit set, a non-straced syscall entry results in C and D clear
+	 * in the saved PSW.
 	 */
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
-	ssm	0,%r2				/* Lower 8 bits only!! */
-	STREG	%r2,TASK_PT_PSW(%r1)
-	STREG	%r1,TASK_PT_CR30(%r1)
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
+	ssm	0,%r2
+	STREG	%r2,TASK_PT_PSW(%r1)		/* Lower 8 bits only!! */
 	mfsp	%sr0,%r2
 	STREG	%r2,TASK_PT_SR0(%r1)
 	mfsp	%sr1,%r2
@@ -204,18 +243,15 @@
 	/* Finished saving things for the debugger */
 
 	ldil	L%syscall_trace,%r1
-	LDIL_FIXUP(%r1)
 	ldil	L%tracesys_next,%r2
-	LDIL_FIXUP(%r2)
 	be	R%syscall_trace(%sr7,%r1)
 	ldo	R%tracesys_next(%r2),%r2
 	
 tracesys_next:	
 	ldil	L%sys_call_table,%r1
-	LDIL_FIXUP(%r1)
 	ldo     R%sys_call_table(%r1), %r19
 
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	LDREG   TASK_PT_GR20(%r1), %r20
 	LDREG   TASK_PT_GR26(%r1), %r26		/* Restore the users args */
 	LDREG   TASK_PT_GR25(%r1), %r25
@@ -224,6 +260,7 @@
 #ifdef __LP64__
 	LDREG   TASK_PT_GR22(%r1), %r22
 	LDREG   TASK_PT_GR21(%r1), %r21
+	ldo	-16(%r30),%r29			/* Reference param save area */
 #endif
 
 	comiclr,>>=	__NR_Linux_syscalls, %r20, %r0
@@ -243,7 +280,6 @@
 	comb,=	%r2,%r20,.Ltrace_rt_sigreturn
 .Ltrace_in_syscall:
 	ldil	L%tracesys_exit,%r2
-	LDIL_FIXUP(%r2)
 	be      0(%sr7,%r19)
 	ldo	R%tracesys_exit(%r2),%r2
 
@@ -251,30 +287,33 @@
 	makes a direct call to syscall_trace. */
 	
 tracesys_exit:
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
+#ifdef __LP64__
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#endif
 	bl	syscall_trace, %r2
 	STREG   %r28,TASK_PT_GR28(%r1)          /* save return value now */
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
 	LDREG   TASK_PT_GR28(%r1), %r28		/* Restore return val. */
 
 	ldil	L%syscall_exit,%r1
-	LDIL_FIXUP(%r1)
 	be,n	R%syscall_exit(%sr7,%r1)
 
 .Ltrace_rt_sigreturn:
 	comib,<> 0,%r25,.Ltrace_in_syscall
 	ldil	L%tracesys_sigexit,%r2
-	LDIL_FIXUP(%r2)
 	be      0(%sr7,%r19)
 	ldo	R%tracesys_sigexit(%r2),%r2
 
 tracesys_sigexit:
-	ldo     -TASK_SZ_ALGN-64(%r30),%r1      /* get task ptr */
+	ldo     -TASK_SZ_ALGN-FRAME_SIZE(%r30),%r1      /* get task ptr */
+#ifdef __LP64__
+	ldo	-16(%r30),%r29			/* Reference param save area */
+#endif
 	bl	syscall_trace, %r2
 	nop
 
 	ldil	L%syscall_exit_rfi,%r1
-	LDIL_FIXUP(%r1)
 	be,n	R%syscall_exit_rfi(%sr7,%r1)
 
 #ifdef __LP64__
@@ -282,13 +321,13 @@
  * narrow palinux.  Use ENTRY_DIFF for those where a 32-bit specific
  * implementation is required on wide palinux.
  */
-#define ENTRY_SAME(_name_) .dword sys_##_name_
-#define ENTRY_DIFF(_name_) .dword sys32_##_name_
-#define ENTRY_UHOH(_name_) .dword sys32_unimplemented
+#define ENTRY_SAME(_name_) .dword sys_/**/_name_
+#define ENTRY_DIFF(_name_) .dword sys32_/**/_name_
+#define ENTRY_UHOH(_name_) .dword sys32_/**/unimplemented
 #else
-#define ENTRY_SAME(_name_) .word sys_##_name_
-#define ENTRY_DIFF(_name_) .word sys_##_name_
-#define ENTRY_UHOH(_name_) .word sys_##_name_
+#define ENTRY_SAME(_name_) .word sys_/**/_name_
+#define ENTRY_DIFF(_name_) .word sys_/**/_name_
+#define ENTRY_UHOH(_name_) .word sys_/**/_name_
 #endif
 
 	.align 8
@@ -316,7 +355,7 @@
 	ENTRY_SAME(socket)
 	/* struct stat is MAYBE identical wide and narrow ?? */
 	ENTRY_DIFF(newstat)
-	ENTRY_SAME(lseek)
+	ENTRY_DIFF(lseek)
 	ENTRY_SAME(getpid)		/* 20 */
 	/* the 'void * data' parameter may need re-packing in wide */
 	ENTRY_DIFF(mount)
@@ -391,8 +430,8 @@
 	ENTRY_DIFF(getrlimit)
 	ENTRY_DIFF(getrusage)
 	/* struct timeval and timezone are maybe?? consistent wide and narrow */
-	ENTRY_SAME(gettimeofday)
-	ENTRY_SAME(settimeofday)
+	ENTRY_DIFF(gettimeofday)
+	ENTRY_DIFF(settimeofday)
 	ENTRY_SAME(getgroups)	/* 80 */
 	ENTRY_SAME(setgroups)
 	/* struct socketaddr... */
@@ -402,12 +441,12 @@
 	ENTRY_DIFF(newlstat)
 	ENTRY_SAME(readlink)	/* 85 */
 	/* suspect we'll need some work for narrow shlibs on wide kernel */
+	/* NOTE this doesn't get used when I boot 32-bit userspace */
+	/* containing working shlib apps -- can this be nuked? */
 	ENTRY_UHOH(uselib)
 	ENTRY_SAME(swapon)
 	ENTRY_SAME(reboot)
-	/* argh! struct dirent contains a long */
-	ENTRY_UHOH(old_readdir)
-	/* I'm not certain about off_t... */
+	ENTRY_SAME(mmap2)
 	ENTRY_SAME(mmap)		/* 90 */
 	ENTRY_SAME(munmap)
 	ENTRY_SAME(truncate)
@@ -419,28 +458,27 @@
 	ENTRY_SAME(recv)
 	ENTRY_DIFF(statfs)
 	ENTRY_DIFF(fstatfs)		/* 100 */
-	ENTRY_SAME(ni_syscall)
+	ENTRY_SAME(stat64)
 	/* don't think hppa glibc even provides an entry pt for this
 	 * so disable for now */
 	ENTRY_UHOH(socketcall)
 	ENTRY_SAME(syslog)
 	/* even though manpage says struct timeval contains longs, ours has
 	 * time_t and suseconds_t -- both of which are safe wide/narrow */
-	ENTRY_SAME(setitimer)
-	ENTRY_SAME(getitimer)	/* 105 */
+	ENTRY_DIFF(setitimer)
+	ENTRY_DIFF(getitimer)	/* 105 */
 	ENTRY_SAME(capget)
 	ENTRY_SAME(capset)
-	ENTRY_SAME(pread)
-	ENTRY_SAME(pwrite)
+	ENTRY_DIFF(pread)
+	ENTRY_DIFF(pwrite)
 	ENTRY_SAME(getcwd)		/* 110 */
 	ENTRY_SAME(vhangup)
-	ENTRY_SAME(ni_syscall)
+	ENTRY_SAME(fstat64)
 	ENTRY_SAME(vfork_wrapper)
 	/* struct rusage contains longs... */
 	ENTRY_DIFF(wait4)
 	ENTRY_SAME(swapoff)		/* 115 */
-	/* struct sysinfo contains longs */
-	ENTRY_SAME(sysinfo)
+	ENTRY_DIFF(sysinfo)
 	ENTRY_SAME(shutdown)
 	ENTRY_SAME(fsync)
 	ENTRY_SAME(madvise)
@@ -450,7 +488,7 @@
 	/* struct sockaddr... */
 	ENTRY_SAME(recvfrom)
 	/* struct timex contains longs */
-	ENTRY_UHOH(adjtimex)
+	ENTRY_DIFF(adjtimex)
 	ENTRY_SAME(mprotect)	/* 125 */
 	/* old_sigset_t forced to 32 bits.  Beware glibc sigset_t */
 	ENTRY_DIFF(sigprocmask)
@@ -461,12 +499,11 @@
 	ENTRY_SAME(delete_module)
 	/* struct kernel_sym contains a long. Linus never heard of size_t? */
 	ENTRY_DIFF(get_kernel_syms)	/* 130 */
-	ENTRY_SAME(quotactl)
+	/* time_t inside struct dqblk */
+	ENTRY_DIFF(quotactl)
 	ENTRY_SAME(getpgid)
 	ENTRY_SAME(fchdir)
-	/* bdflush(func, addr) where func has least-significant-bit set means
-	 * addr is a pointer to long :-( */
-	ENTRY_UHOH(bdflush)
+	ENTRY_SAME(bdflush)
 	ENTRY_SAME(sysfs)		/* 135 */
 	ENTRY_SAME(personality)
 	ENTRY_SAME(ni_syscall)	/* for afs_syscall */
@@ -479,12 +516,12 @@
 	ENTRY_DIFF(getdents)
 	/* it is POSSIBLE that select will be OK because even though fd_set
 	 * contains longs, the macros and sizes are clever. */
-	ENTRY_SAME(select)
+	ENTRY_DIFF(select)
 	ENTRY_SAME(flock)
 	ENTRY_SAME(msync)
 	/* struct iovec contains pointers */
-	ENTRY_UHOH(readv)		/* 145 */
-	ENTRY_UHOH(writev)
+	ENTRY_DIFF(readv)		/* 145 */
+	ENTRY_DIFF(writev)
 	ENTRY_SAME(getsid)
 	ENTRY_SAME(fdatasync)
 	/* struct __sysctl_args is a mess */
@@ -509,13 +546,12 @@
 	ENTRY_SAME(mremap)
 	ENTRY_SAME(setresuid)
 	ENTRY_SAME(getresuid)	/* 165 */
-	/* might work, but in general signals need a thorough review */
-	ENTRY_UHOH(sigaltstack_wrapper)
+	ENTRY_DIFF(sigaltstack_wrapper)
 	/* struct passed back to user can contain long symbol values */
 	ENTRY_DIFF(query_module)
 	ENTRY_SAME(poll)
 	/* structs contain pointers and an in_addr... */
-	ENTRY_UHOH(nfsservctl)
+	ENTRY_DIFF(nfsservctl)
 	ENTRY_SAME(setresgid)	/* 170 */
 	ENTRY_SAME(getresgid)
 	ENTRY_SAME(prctl)
@@ -525,35 +561,43 @@
 	ENTRY_DIFF(rt_sigprocmask)	/* 175 */
 	ENTRY_DIFF(rt_sigpending)
 	ENTRY_UHOH(rt_sigtimedwait)
-	ENTRY_UHOH(rt_sigqueueinfo)
+	/* even though the struct siginfo_t is different, it appears like
+	 * all the paths use values which should be same wide and narrow.
+	 * Also the struct is padded to 128 bytes which means we don't have
+	 * to worry about faulting trying to copy in a larger 64-bit
+	 * struct from a 32-bit user-space app.
+	 */
+	ENTRY_SAME(rt_sigqueueinfo)
 	ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
 	ENTRY_SAME(chown)		/* 180 */
-	/* *sockopt() might work... */
-	ENTRY_SAME(setsockopt)
+	/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
+	ENTRY_DIFF(setsockopt)
 	ENTRY_SAME(getsockopt)
-	/* struct msghdr contains pointers... */
-	ENTRY_UHOH(sendmsg)
-	ENTRY_UHOH(recvmsg)
+	ENTRY_DIFF(sendmsg)
+	ENTRY_DIFF(recvmsg)
 	ENTRY_SAME(semop)		/* 185 */
 	ENTRY_SAME(semget)
-	/* needs a more careful review */
-	ENTRY_UHOH(semctl)
-	/* struct msgbuf contains a long */
-	ENTRY_UHOH(msgsnd)
-	ENTRY_UHOH(msgrcv)
+	ENTRY_DIFF(semctl_broken)
+	ENTRY_DIFF(msgsnd)
+	ENTRY_DIFF(msgrcv)
 	ENTRY_SAME(msgget)		/* 190 */
-	/* struct msqid_ds contains pointers */
-	ENTRY_UHOH(msgctl)
+	ENTRY_SAME(msgctl_broken)
 	ENTRY_SAME(shmat_wrapper)
 	ENTRY_SAME(shmdt)
 	ENTRY_SAME(shmget)
-	/***************/
-	/* struct shmid_ds contains pointers */
-	ENTRY_UHOH(shmctl)		/* 195 */
+	ENTRY_SAME(shmctl_broken)		/* 195 */
 	ENTRY_SAME(ni_syscall)		/* streams1 */
 	ENTRY_SAME(ni_syscall)		/* streams2 */
+	ENTRY_SAME(lstat64)
+	ENTRY_DIFF(truncate64)
+	ENTRY_DIFF(ftruncate64)	/* 200 */
+	ENTRY_SAME(getdents64)
+	ENTRY_DIFF(fcntl64)
+	ENTRY_SAME(ni_syscall)		/* attrctl */
+	ENTRY_SAME(ni_syscall)		/* acl_get */
+	ENTRY_SAME(ni_syscall)		/* acl_set */
 	ENTRY_SAME(gettid)
-	ENTRY_SAME(tkill)
+	ENTRY_SAME(readahead)          
 
 .end
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/time.c linux/arch/parisc/kernel/time.c
--- linux.orig/arch/parisc/kernel/time.c	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/kernel/time.c	2002-08-12 22:14:16.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/kernel/time.c
+ *  linux/arch/parisc/kernel/time.c
  *
  *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
  *  Modifications for ARM (C) 1994, 1995, 1996,1997 Russell King
@@ -10,6 +10,7 @@
  * 1998-12-20  Updated NTP code according to technical memorandum Jan '96
  *             "A Kernel Model for Precision Timekeeping" by Dave Mills
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -30,69 +31,208 @@
 
 #include <linux/timex.h>
 
+/* xtime and wall_jiffies keep wall-clock time */
+extern unsigned long wall_jiffies;
 extern rwlock_t xtime_lock;
 
-static int timer_value;
-static int timer_delta;
-static struct pdc_tod tod_data __attribute__((aligned(8)));
+static long clocktick;	/* timer cycles per tick */
+static long halftick;
 
-void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+#ifdef CONFIG_SMP
+extern void smp_do_timer(struct pt_regs *regs);
+#endif
+
+static inline void
+parisc_do_profile(unsigned long pc)
 {
-	int old;
-	int lost = 0;
-	int cr16;
-	
-	old = timer_value;
+	extern char _stext;
 
-	cr16 = mfctl(16);
-	while((timer_value - cr16) < (timer_delta / 2)) {
-		timer_value += timer_delta;
-		lost++;
-	}
+	if (!prof_buffer)
+		return;
 
-	mtctl(timer_value ,16);
+	pc -= (unsigned long) &_stext;
+	pc >>= prof_shift;
+	/*
+	 * Don't ignore out-of-bounds PC values silently,
+	 * put them into the last histogram slot, so if
+	 * present, they will show up as a sharp peak.
+	 */
+	if (pc > prof_len - 1)
+		pc = prof_len - 1;
+	atomic_inc((atomic_t *)&prof_buffer[pc]);
+}
+
+void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	long now = mfctl(16);
+	long next_tick;
+	int nticks;
+	int cpu = smp_processor_id();
+
+	/* initialize next_tick to time at last clocktick */
+
+	next_tick = cpu_data[cpu].it_value;
+
+	/* since time passes between the interrupt and the mfctl()
+	 * above, it is never true that last_tick + clocktick == now.  If we
+	 * never miss a clocktick, we could set next_tick = last_tick + clocktick
+	 * but maybe we'll miss ticks, hence the loop.
+	 *
+	 * Variables are *signed*.
+	 */
+
+	nticks = 0;
+	while((next_tick - now) < halftick) {
+		next_tick += clocktick;
+		nticks++;
+	}
+	mtctl(next_tick, 16);
+	cpu_data[cpu].it_value = next_tick;
 
-	do_timer(regs);
+	while (nticks--) {
+#ifdef CONFIG_SMP
+		smp_do_timer(regs);
+#endif
+		if (cpu == 0) {
+			extern int pc_in_user_space;
+			write_lock(&xtime_lock);
+#ifndef CONFIG_SMP
+			if (!user_mode(regs))
+				parisc_do_profile(regs->iaoq[0]);
+			else
+				parisc_do_profile(&pc_in_user_space);
+#endif
+			do_timer(regs);
+			write_unlock(&xtime_lock);
+		}
+	}
     
-	led_interrupt_func();
+#ifdef CONFIG_CHASSIS_LCD_LED
+	/* Only schedule the led tasklet on cpu 0, and only if it
+	 * is enabled.
+	 */
+	if (cpu == 0 && !atomic_read(&led_tasklet.count))
+		tasklet_schedule(&led_tasklet);
+#endif
+
+	/* check soft power switch status */
+	if (cpu == 0 && !atomic_read(&power_tasklet.count))
+		tasklet_schedule(&power_tasklet);
 }
 
-void do_gettimeofday(struct timeval *tv)
+/*** converted from ia64 ***/
+/*
+ * Return the number of micro-seconds that elapsed since the last
+ * update to wall time (aka xtime aka wall_jiffies).  The xtime_lock
+ * must be at least read-locked when calling this routine.
+ */
+static inline unsigned long
+gettimeoffset (void)
 {
-	unsigned long flags;
-	
+#ifndef CONFIG_SMP
+	/*
+	 * FIXME: This won't work on smp because jiffies are updated by cpu 0.
+	 *    Once parisc-linux learns the cr16 difference between processors,
+	 *    this could be made to work.
+	 */
+	long last_tick;
+	long elapsed_cycles;
+
+	/* it_value is the intended time of the next tick */
+	last_tick = cpu_data[smp_processor_id()].it_value;
+
+	/* Subtract one tick and account for possible difference between
+	 * when we expected the tick and when it actually arrived.
+	 * (aka wall vs real)
+	 */
+	last_tick -= clocktick * (jiffies - wall_jiffies + 1);
+	elapsed_cycles = mfctl(16) - last_tick;
+
+	/* the precision of this math could be improved */
+	return elapsed_cycles / (PAGE0->mem_10msec / 10000);
+#else
+	return 0;
+#endif
+}
+
+void
+do_gettimeofday (struct timeval *tv)
+{
+	unsigned long flags, usec, sec;
+
 	read_lock_irqsave(&xtime_lock, flags);
-	tv->tv_sec = xtime.tv_sec;
-	tv->tv_usec = xtime.tv_usec;
+	{
+		usec = gettimeoffset();
+	
+		sec = xtime.tv_sec;
+		usec += xtime.tv_usec;
+	}
 	read_unlock_irqrestore(&xtime_lock, flags);
 
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		++sec;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
 }
 
-void do_settimeofday(struct timeval *tv)
+void
+do_settimeofday (struct timeval *tv)
 {
 	write_lock_irq(&xtime_lock);
-	xtime.tv_sec = tv->tv_sec;
-	xtime.tv_usec = tv->tv_usec;
+	{
+		/*
+		 * This is revolting. We need to set "xtime"
+		 * correctly. However, the value in this location is
+		 * the value at the most recent update of wall time.
+		 * Discover what correction gettimeofday would have
+		 * done, and then undo it!
+		 */
+		tv->tv_usec -= gettimeoffset();
+		tv->tv_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);
+
+		while (tv->tv_usec < 0) {
+			tv->tv_usec += 1000000;
+			tv->tv_sec--;
+		}
+
+		xtime = *tv;
+		time_adjust = 0;		/* stop active adjtime() */
+		time_status |= STA_UNSYNC;
+		time_maxerror = NTP_PHASE_LIMIT;
+		time_esterror = NTP_PHASE_LIMIT;
+	}
 	write_unlock_irq(&xtime_lock);
 }
 
+
 void __init time_init(void)
 {
-	timer_delta = (100 * PAGE0->mem_10msec) / HZ;
+	unsigned long next_tick;
+	static struct pdc_tod tod_data;
+
+	clocktick = (100 * PAGE0->mem_10msec) / HZ;
+	halftick = clocktick / 2;
 
-	/* make the first timer interrupt go off in one second */
-	timer_value = mfctl(16) + (HZ * timer_delta);
-	mtctl(timer_value, 16);
+	/* Setup clock interrupt timing */
 
+	next_tick = mfctl(16);
+	next_tick += clocktick;
+	cpu_data[smp_processor_id()].it_value = next_tick;
+
+	/* kick off Itimer (CR16) */
+	mtctl(next_tick, 16);
 
 	if(pdc_tod_read(&tod_data) == 0) {
+		write_lock_irq(&xtime_lock);
 		xtime.tv_sec = tod_data.tod_sec;
 		xtime.tv_usec = tod_data.tod_usec;
+		write_unlock_irq(&xtime_lock);
 	} else {
 		printk(KERN_ERR "Error reading tod clock\n");
 	        xtime.tv_sec = 0;
 		xtime.tv_usec = 0;
 	}
-
 }
-
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/traps.c linux/arch/parisc/kernel/traps.c
--- linux.orig/arch/parisc/kernel/traps.c	2002-02-25 19:37:53.000000000 +0000
+++ linux/arch/parisc/kernel/traps.c	2002-08-12 22:14:20.000000000 +0000
@@ -23,15 +23,20 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/console.h>
+
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/traps.h>
+#include <asm/unaligned.h>
 #include <asm/atomic.h>
-
 #include <asm/smp.h>
 #include <asm/pdc.h>
 
+#include "../math-emu/math-emu.h"	/* for handle_fpe() */
+
 #ifdef CONFIG_KWDB
 #include <kdb/break.h>		/* for BI2_KGDB_GDB */
 #include <kdb/kgdb_types.h>	/* for __() */
@@ -40,150 +45,205 @@
 #include <kdb/trap.h>		/* for I_BRK_INST */
 #endif /* CONFIG_KWDB */
 
+#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
+			  /*  dumped to the console via printk)          */
 
-static inline void console_verbose(void)
-{
-	console_loglevel = 15;
-}
-
-
-void page_exception(void);
-
-/*
- * These constants are for searching for possible module text
- * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
- */
-#define VMALLOC_OFFSET (8*1024*1024)
-#define MODULE_RANGE (8*1024*1024)
-
-int kstack_depth_to_print = 24;
-
-static void printbinary(unsigned long x, int nbits)
+static int printbinary(char *buf, unsigned long x, int nbits)
 {
 	unsigned long mask = 1UL << (nbits - 1);
 	while (mask != 0) {
-		printk(mask & x ? "1" : "0");
+		*buf++ = (mask & x ? '1' : '0');
 		mask >>= 1;
 	}
+	*buf = '\0';
+
+	return nbits;
 }
 
-void show_regs(struct pt_regs *regs)
-{
-	int i;
 #ifdef __LP64__
-#define RFMT " %016lx"
+#define RFMT "%016lx"
 #else
-#define RFMT " %08lx"
+#define RFMT "%08lx"
 #endif
 
-	printk("\n"); /* don't want to have that pretty register dump messed up */
-
-	printk("     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\nPSW: ");
-	printbinary(regs->gr[0], 32);
-	printk("    %s\n", print_tainted());
+void show_regs(struct pt_regs *regs)
+{
+	int i;
+	char buf[128], *p;
+	char *level;
+	unsigned long cr30;
+	unsigned long cr31;
+
+	level = user_mode(regs) ? KERN_DEBUG : KERN_CRIT;
+
+	printk("%s\n", level); /* don't want to have that pretty register dump messed up */
+
+	printk("%s     YZrvWESTHLNXBCVMcbcbcbcbOGFRQPDI\n", level);
+	printbinary(buf, regs->gr[0], 32);
+	printk("%sPSW: %s %s\n", level, buf, print_tainted());
 
 	for (i = 0; i < 32; i += 4) {
 		int j;
-		printk("r%d-%d\t", i, i + 3);
+		p = buf;
+		p += sprintf(p, "%sr%02d-%02d ", level, i, i + 3);
 		for (j = 0; j < 4; j++) {
-			printk(RFMT, i + j == 0 ? 0 : regs->gr[i + j]);
+			p += sprintf(p, " " RFMT, (i+j) == 0 ? 0 : regs->gr[i + j]);
 		}
-		printk("\n");
+		printk("%s\n", buf);
 	}
 
 	for (i = 0; i < 8; i += 4) {
 		int j;
-		printk("sr%d-%d\t", i, i + 4);
+		p = buf;
+		p += sprintf(p, "%ssr%d-%d  ", level, i, i + 3);
 		for (j = 0; j < 4; j++) {
-			printk(RFMT, regs->sr[i + j]);
+			p += sprintf(p, " " RFMT, regs->sr[i + j]);
 		}
-		printk("\n");
+		printk("%s\n", buf);
 	}
 
-#if REDICULOUSLY_VERBOSE
-	for (i = 0; i < 32; i++) {
-		printk("FR%2d : %016lx  ", i, regs->fr[i]);
-		if ((i & 1) == 1)
-			printk("\n");
-	}
+#if RIDICULOUSLY_VERBOSE
+	for (i = 0; i < 32; i += 2)
+		printk("%sFR%02d : %016lx  FR%2d : %016lx", level, i,
+				regs->fr[i], i+1, regs->fr[i+1]);
 #endif
 
-	printk("\nIASQ:" RFMT RFMT " IAOQ:" RFMT RFMT "\n",
-	       regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
-	printk(" IIR: %08lx    ISR:" RFMT "  IOR:" RFMT "\nORIG_R28:" RFMT
-	       "\n", regs->iir, regs->isr, regs->ior, regs->orig_r28);
+	cr30 = mfctl(30);
+	cr31 = mfctl(31);
+	printk("%s\n", level);
+	printk("%sIASQ: " RFMT " " RFMT " IAOQ: " RFMT " " RFMT "\n",
+	       level, regs->iasq[0], regs->iasq[1], regs->iaoq[0], regs->iaoq[1]);
+	printk("%s IIR: %08lx    ISR: " RFMT "  IOR: " RFMT "\n",
+	       level, regs->iir, regs->isr, regs->ior);
+	printk("%s CPU: %8d   CR30: " RFMT " CR31: " RFMT "\n",
+	       level, ((struct task_struct *)cr30)->processor, cr30, cr31);
+	printk("%s ORIG_R28: " RFMT "\n", level, regs->orig_r28);
 }
 
-void
-die_if_kernel (char *str, struct pt_regs *regs, long err)
+
+static void dump_stack(unsigned long from, unsigned long to, int istackflag)
+{
+	unsigned int *fromptr;
+	unsigned int *toptr;
+
+	fromptr = (unsigned int *)from;
+	toptr = (unsigned int *)to;
+
+	printk("\n");
+	printk(KERN_CRIT "Dumping %sStack from 0x%p to 0x%p:\n",
+			istackflag ? "Interrupt " : "",
+			fromptr, toptr);
+
+	while (fromptr < toptr) {
+		printk(KERN_CRIT "%04lx %08x %08x %08x %08x %08x %08x %08x %08x\n",
+		    ((unsigned long)fromptr) & 0xffff,
+		    fromptr[0], fromptr[1], fromptr[2], fromptr[3],
+		    fromptr[4], fromptr[5], fromptr[6], fromptr[7]);
+		fromptr += 8;
+	}
+}
+
+
+void show_stack(struct pt_regs *regs)
 {
-	if (user_mode(regs)) {
 #if 1
+	/* If regs->sr[7] == 0, we are on a kernel stack */
+	if (regs->sr[7] == 0) {
+
+		unsigned long sp = regs->gr[30];
+		unsigned long cr30;
+		unsigned long cr31;
+		unsigned long stack_start;
+		struct pt_regs *int_regs;
+
+		cr30 = mfctl(30);
+		cr31 = mfctl(31);
+		stack_start = sp & ~(ISTACK_SIZE - 1);
+		if (stack_start == cr31) {
+		    /*
+		     * We are on the interrupt stack, get the stack
+		     * pointer from the first pt_regs structure on
+		     * the interrupt stack, so we can dump the task
+		     * stack first.
+		     */
+
+		    int_regs = (struct pt_regs *)cr31;
+		    sp = int_regs->gr[30];
+		    stack_start = sp & ~(INIT_TASK_SIZE - 1);
+		    if (stack_start != cr30) {
+			printk(KERN_CRIT "WARNING! Interrupt-Stack pointer and cr30 do not correspond!\n");
+			printk(KERN_CRIT "Dumping virtual address stack instead\n");
+			dump_stack((unsigned long)__va(stack_start), (unsigned long)__va(sp), 0);
+		    } else {
+			dump_stack(stack_start, sp, 0);
+		    };
+
+		    printk("\n\n" KERN_DEBUG "Registers at Interrupt:\n");
+		    show_regs(int_regs);
+
+		    /* Now dump the interrupt stack */
+
+		    sp = regs->gr[30];
+		    stack_start = sp & ~(ISTACK_SIZE - 1);
+		    dump_stack(stack_start,sp,1);
+		}
+		else
+		{
+		    /* Stack Dump! */
+		    printk(KERN_CRIT "WARNING! Stack pointer and cr30 do not correspond!\n");
+		    printk(KERN_CRIT "Dumping virtual address stack instead\n");
+		    dump_stack((unsigned long)__va(stack_start), (unsigned long)__va(sp), 0);
+		}
+	}
+#endif
+}
+
+
+void die_if_kernel(char *str, struct pt_regs *regs, long err)
+{
+	if (user_mode(regs)) {
+#ifdef PRINT_USER_FAULTS
 		if (err == 0)
 			return; /* STFU */
 
 		/* XXX for debugging only */
-		printk ("!!die_if_kernel: %s(%d): %s %ld\n",
+		printk(KERN_DEBUG "%s (pid %d): %s (code %ld)\n",
 			current->comm, current->pid, str, err);
 		show_regs(regs);
 #endif
 		return;
 	}
+	
+	/* unlock the pdc lock if necessary */
+	pdc_emergency_unlock();
 
-	printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);
-
+	/* maybe the kernel hasn't booted very far yet and hasn't been able 
+	 * to initialize the serial or STI console. In that case we should 
+	 * re-enable the pdc console, so that the user will be able to 
+	 * identify the problem. */
+	if (!console_drivers)
+		pdc_console_restart();
+	
+	printk(KERN_CRIT "%s (pid %d): %s (code %ld)\n",
+		current->comm, current->pid, str, err);
 	show_regs(regs);
 
 	/* Wot's wrong wif bein' racy? */
 	if (current->thread.flags & PARISC_KERNEL_DEATH) {
-		printk("die_if_kernel recursion detected.\n");
+		printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__);
 		sti();
 		while (1);
 	}
+
 	current->thread.flags |= PARISC_KERNEL_DEATH;
 	do_exit(SIGSEGV);
 }
 
-asmlinkage void cache_flush_denied(struct pt_regs * regs, long error_code)
-{
-}
-
-asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
-{
-}
-
-#ifndef CONFIG_MATH_EMULATION
-
-asmlinkage void math_emulate(long arg)
-{
-}
-
-#endif /* CONFIG_MATH_EMULATION */
-
 int syscall_ipi(int (*syscall) (struct pt_regs *), struct pt_regs *regs)
 {
 	return syscall(regs);
 }
 
-struct {
-	int retval;
-
-	int (*func) (void *, struct pt_regs *);
-	void * data;
-} ipi_action[NR_CPUS];
-
-void ipi_interrupt(int irq, void *unused, struct pt_regs *regs)
-{
-	int cpu = smp_processor_id();
-
-	if(!ipi_action[cpu].func)
-		BUG();
-
-	ipi_action[cpu].retval =
-		ipi_action[cpu].func(ipi_action[cpu].data, regs);
-}
-
 /* gdb uses break 4,8 */
 #define GDB_BREAK_INSN 0x10004
 void handle_gdb_break(struct pt_regs *regs, int wot)
@@ -204,15 +264,16 @@
 	struct save_state ssp;
 #endif /* CONFIG_KWDB */   
 
-	flush_all_caches();
 	switch(iir) {
 	case 0x00:
-		/* show registers, halt */
-		cli();
-		printk("break 0,0: pid=%d command='%s'\n",
+#ifdef PRINT_USER_FAULTS
+		printk(KERN_DEBUG "break 0,0: pid=%d command='%s'\n",
 		       current->pid, current->comm);
+#endif
 		die_if_kernel("Breakpoint", regs, 0);
+#ifdef PRINT_USER_FAULTS
 		show_regs(regs);
+#endif
 		si.si_code = TRAP_BRKPT;
 		si.si_addr = (void *) (regs->iaoq[0] & ~3);
 		si.si_signo = SIGTRAP;
@@ -225,7 +286,6 @@
 		break;
 
 #ifdef CONFIG_KWDB
-
 	case KGDB_BREAK_INSN:
 		mtctl(0, 15);
 		pt_regs_to_ssp(regs, &ssp);
@@ -243,14 +303,14 @@
 		regs->iaoq[0] = regs->iaoq[1];
 		regs->iaoq[1] += 4;
 		break;
-
 #endif /* CONFIG_KWDB */
 
 	default:
-		set_eiem(0);
-		printk("break %#08x: pid=%d command='%s'\n",
+#ifdef PRINT_USER_FAULTS
+		printk(KERN_DEBUG "break %#08x: pid=%d command='%s'\n",
 		       iir, current->pid, current->comm);
 		show_regs(regs);
+#endif
 		si.si_signo = SIGTRAP;
 		si.si_code = TRAP_BRKPT;
 		si.si_addr = (void *) (regs->iaoq[0] & ~3);
@@ -259,252 +319,151 @@
 	}
 }
 
-/* Format of the floating-point exception registers. */
-struct exc_reg {
-	unsigned int exception : 6;
-	unsigned int ei : 26;
-};
-
-/* Macros for grabbing bits of the instruction format from the 'ei'
-   field above. */
-/* Major opcode 0c and 0e */
-#define FP0CE_UID(i) (((i) >> 6) & 3)
-#define FP0CE_CLASS(i) (((i) >> 9) & 3)
-#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
-#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
-#define FP0C_FORMAT(i) (((i) >> 11) & 3)
-#define FP0E_FORMAT(i) (((i) >> 11) & 1)
-
-/* Major opcode 0c, uid 2 (performance monitoring) */
-#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
-
-/* Major opcode 2e (fused operations).   */
-#define FP2E_SUBOP(i)  (((i) >> 5) & 1)
-#define FP2E_FORMAT(i) (((i) >> 11) & 1)
-
-/* Major opcode 26 (FMPYSUB) */
-/* Major opcode 06 (FMPYADD) */
-#define FPx6_FORMAT(i) ((i) & 0x1f)
-
-/* Flags and enable bits of the status word. */
-#define FPSW_FLAGS(w) ((w) >> 27)
-#define FPSW_ENABLE(w) ((w) & 0x1f)
-#define FPSW_V (1<<4)
-#define FPSW_Z (1<<3)
-#define FPSW_O (1<<2)
-#define FPSW_U (1<<1)
-#define FPSW_I (1<<0)
-
-/* Emulate a floating point instruction if necessary and possible
-   (this will be moved elsewhere eventually).  Return zero if
-   successful or if emulation was not required, -1 if the instruction
-   is actually illegal or unimplemented.  The status word passed as
-   the first parameter will be modified to signal exceptions, if
-   any. */
-
-/* FIXME!!!  This is really incomplete and, at the moment, most
-   illegal FP instructions will simply act as no-ops.  Obviously that
-   is *not* what we want.  Also we don't even try to handle exception
-   types other than the 'unimplemented' ones. */
-int
-fp_emul_insn(u32 *sw, struct exc_reg exc, struct pt_regs *regs)
-{
-	switch (exc.exception) {
-	case 0x3:  /* Unimplemented, opcode 06 */
-		break;
-	case 0x9:  /* Unimplemented, opcode 0c */
-		/* We do not support quadword operations, end of
-                   story.  There's no support for them in GCC. */
-		if (FP0C_FORMAT(exc.ei) == 3)
-			return -1; /* SIGILL */
-		/* Fall through. */
-	case 0xa:  /* Unimplemented, opcode 0e */
-		if (FP0CE_CLASS(exc.ei) == 1) {
-			/* FCNV instructions of various sorts. */
-		} else {
-			if (FP0CE_CLASS(exc.ei == 0)
-			    && FP0CE_SUBOP(exc.ei == 5)) {
-				/* FRND instructions should be
-                                   emulated, at some point, I
-                                   guess. */
-				return -1; /* SIGILL */
-			}
-		}
-		break;
-	case 0x23: /* Unimplemented, opcode 26 */
-		break;
-	case 0x2b: /* Unimplemented, opcode 2e */
-		break;
-	case 0x1:  /* Unimplemented, opcode 0e/0c */
-		/* FIXME: How the hell are we supposed to tell which
-                   opcode it is? */
-		break;
-	default:
-		return -1; /* Punt */
-	}
 
+int handle_toc(void)
+{
+	printk(KERN_CRIT "TOC call.\n");
 	return 0;
 }
 
-/* Handle a floating point exception.  Return zero if the faulting
-   instruction can be completed successfully. */
-int
-handle_fpe(struct pt_regs *regs)
+static void default_trap(int code, struct pt_regs *regs)
 {
-	struct siginfo si;
-	union {
-		struct fpsw {
-			/* flag bits */
-			unsigned int fv : 1;
-			unsigned int fz : 1;
-			unsigned int fo : 1;
-			unsigned int fu : 1;
-			unsigned int fi : 1;
-
-			unsigned int c : 1;
-			unsigned int pad1 : 4;
-			unsigned int cq : 11;
-			unsigned int rm : 2;
-			unsigned int pad2 : 2;
-			unsigned int t : 1;
-			unsigned int d : 1;
-
-			/* enable bits */
-			unsigned int ev : 1;
-			unsigned int ez : 1;
-			unsigned int eo : 1;
-			unsigned int eu : 1;
-			unsigned int ei : 1;
-		} status;
-		u32 word;
-	} sw;
-	struct exc_reg excepts[7];
-	unsigned int code = 0;
-	unsigned int throw;
-
-	/* Status word = FR0L. */
-	memcpy(&sw, regs->fr, sizeof(sw));
-	/* Exception words = FR0R-FR3R. */
-	memcpy(excepts, ((char *) regs->fr) + 4, sizeof(excepts));
-
-	/* This is all CPU dependent.  Since there is no public
-           documentation on the PA2.0 processors we will just assume
-           everything is like the 7100/7100LC/7300LC for now.
-
-	   Specifically: All exceptions are marked as "unimplemented"
-	   in the exception word, and the only exception word used is
-	   excepts[1]. */
-
-	/* Try to emulate the instruction.  Also determine if it is
-           really an illegal instruction in the process.
-
-	   FIXME: fp_emul_insn() only checks for the "unimplemented"
-	   exceptions at the moment.  So this may break horribly on
-	   PA2.0, where we may want to also check to see if we should
-	   just send SIGFPE (or maybe not, let's see the documentation
-	   first...) */
-	if (fp_emul_insn(&sw.word, excepts[1], regs) == -1)
-		goto send_sigill;
-
-	/* Take the intersection of the flag bits in the FPSW and the
-           enable bits in the FPSW. */
-	throw = FPSW_FLAGS(sw.word) & FPSW_ENABLE(sw.word);
-
-	/* Concoct an appropriate si_code.  Of course we don't know
-           what to do if multiple exceptions were enabled and multiple
-           flags were set.  Maybe that's why HP/UX doesn't implement
-           feenableexcept(). */
-
-	if (throw == 0)
-		goto success; /* Duh. */
-	else if (throw & FPSW_V)
-		code = FPE_FLTINV;
-	else if (throw & FPSW_Z)
-		code = FPE_FLTDIV;
-	else if (throw & FPSW_O)
-		code = FPE_FLTOVF;
-	else if (throw & FPSW_U)
-		code = FPE_FLTUND;
-	else if (throw & FPSW_I)
-		code = FPE_FLTRES;
-
-#if 1 /* Debugging... */
-	printk("Unemulated floating point exception, pid=%d (%s)\n",
-	       current->pid, current->comm);
+	printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id());
 	show_regs(regs);
-	{
-		int i;
-		printk("FP Status: %08x\n", sw.word);
-		printk("FP Exceptions:\n");
-		for (i = 0; i < 7; i++) {
-			printk("\tExcept%d: exception %03x insn %06x\n",
-			       i, excepts[i].exception, excepts[i].ei);
-		}
-	}
-#endif
+}
 
-	/* FIXME: Should we clear the flag bits, T bit, and exception
-           registers here? */
+void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
 
-	si.si_signo = SIGFPE;
-	si.si_errno = 0;
-	si.si_code = code;
-	si.si_addr = (void *) regs->iaoq[0];
-	force_sig_info(SIGFPE, &si, current);
-	return -1;
 
- send_sigill:
-	si.si_signo = SIGILL;
-	si.si_errno = 0;
-	si.si_code = ILL_COPROC;
-	si.si_addr = (void *) regs->iaoq[0];
-	force_sig_info(SIGILL, &si, current);
-	return -1;
-
- success:
-	/* We absolutely have to clear the T bit and exception
-           registers to allow the process to recover.  Otherwise every
-           subsequent floating point instruction will trap. */
-	sw.status.t = 0;
-	memset(excepts, 0, sizeof(excepts));
-
-	memcpy(regs->fr, &sw, sizeof(sw));
-	memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts));
-	return 0;
+#ifdef CONFIG_KWDB
+int debug_call (void)
+{
+    printk (KERN_DEBUG "Debug call.\n");
+    return 0;
 }
 
-int handle_toc(void)
+int debug_call_leaf (void)
 {
-	return 0;
+    return 0;
 }
+#endif /* CONFIG_KWDB */
+
 
-void default_trap(int code, struct pt_regs *regs)
+void transfer_pim_to_trap_frame(struct pt_regs *regs)
 {
-	printk("Trap %d on CPU %d\n", code, smp_processor_id());
+    register int i;
+    extern unsigned int hpmc_pim_data[];
+    struct pdc_hpmc_pim_11 *pim_narrow;
+    struct pdc_hpmc_pim_20 *pim_wide;
 
-	show_regs(regs);
-}
+    if (boot_cpu_data.cpu_type >= pcxu) {
 
-void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;
+	pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
 
+	/*
+	 * Note: The following code will probably generate a
+	 * bunch of truncation error warnings from the compiler.
+	 * Could be handled with an ifdef, but perhaps there
+	 * is a better way.
+	 */
 
-#ifdef CONFIG_KWDB
-int
-debug_call (void) {
-    printk ("Debug call.\n");
-    return 0;
-}
+	regs->gr[0] = pim_wide->cr[22];
 
-int
-debug_call_leaf (void) {
-    return 0;
+	for (i = 1; i < 32; i++)
+	    regs->gr[i] = pim_wide->gr[i];
+
+	for (i = 0; i < 32; i++)
+	    regs->fr[i] = pim_wide->fr[i];
+
+	for (i = 0; i < 8; i++)
+	    regs->sr[i] = pim_wide->sr[i];
+
+	regs->iasq[0] = pim_wide->cr[17];
+	regs->iasq[1] = pim_wide->iasq_back;
+	regs->iaoq[0] = pim_wide->cr[18];
+	regs->iaoq[1] = pim_wide->iaoq_back;
+
+	regs->sar  = pim_wide->cr[11];
+	regs->iir  = pim_wide->cr[19];
+	regs->isr  = pim_wide->cr[20];
+	regs->ior  = pim_wide->cr[21];
+    }
+    else {
+	pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
+
+	regs->gr[0] = pim_narrow->cr[22];
+
+	for (i = 1; i < 32; i++)
+	    regs->gr[i] = pim_narrow->gr[i];
+
+	for (i = 0; i < 32; i++)
+	    regs->fr[i] = pim_narrow->fr[i];
+
+	for (i = 0; i < 8; i++)
+	    regs->sr[i] = pim_narrow->sr[i];
+
+	regs->iasq[0] = pim_narrow->cr[17];
+	regs->iasq[1] = pim_narrow->iasq_back;
+	regs->iaoq[0] = pim_narrow->cr[18];
+	regs->iaoq[1] = pim_narrow->iaoq_back;
+
+	regs->sar  = pim_narrow->cr[11];
+	regs->iir  = pim_narrow->cr[19];
+	regs->isr  = pim_narrow->cr[20];
+	regs->ior  = pim_narrow->cr[21];
+    }
+
+    /*
+     * The following fields only have meaning if we came through
+     * another path. So just zero them here.
+     */
+
+    regs->ksp = 0;
+    regs->kpc = 0;
+    regs->orig_r28 = 0;
 }
-#endif /* CONFIG_KWDB */
 
-extern void do_page_fault(struct pt_regs *, int, unsigned long);
-extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
-extern void transfer_pim_to_trap_frame(struct pt_regs *);
-extern void pdc_console_restart(void);
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ */
+void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
+{
+	static spinlock_t terminate_lock = SPIN_LOCK_UNLOCKED;
+
+	set_eiem(0);
+	__cli();
+	spin_lock(&terminate_lock);
+
+	/* unlock the pdc lock if necessary */
+	pdc_emergency_unlock();
+
+	/* restart pdc console if necessary */
+	if (!console_drivers)
+		pdc_console_restart();
+
+	if (code == 1)
+	    transfer_pim_to_trap_frame(regs);
+
+	show_stack(regs);
+
+	printk("\n");
+	printk(KERN_CRIT "%s: Code=%d regs=%p (Addr=" RFMT ")\n",
+			msg, code, regs, offset);
+	show_regs(regs);
+
+	spin_unlock(&terminate_lock);
+
+	/* put soft power button back under hardware control;
+	 * if the user had pressed it once at any time, the 
+	 * system will shut down immediately right here. */
+	pdc_soft_power_button(0);
+	
+	for(;;)
+	    ;
+}
 
 void handle_interruption(int code, struct pt_regs *regs)
 {
@@ -520,75 +479,127 @@
 	else
 	    sti();
 
-#ifdef __LP64__
-
-	/*
-	 * FIXME:
-	 * For 32 bit processes we don't want the b bits (bits 0 & 1)
-	 * in the ior. This is more appropriately handled in the tlb
-	 * miss handlers. Changes need to be made to support addresses
-	 * >32 bits for 64 bit processes.
-	 */
-
-	regs->ior &= 0x3FFFFFFFFFFFFFFFUL;
-#endif
-
 #if 0
-	printk("interrupted with code %d, regs %p\n", code, regs);
-	show_regs(regs);
+	printk(KERN_CRIT "Interruption # %d\n", code);
 #endif
 
 	switch(code) {
+
 	case  1:
-		parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0);
+		/* High-priority machine check (HPMC) */
+		parisc_terminate("High Priority Machine Check (HPMC)",
+				regs, code, 0);
 		/* NOT REACHED */
-	case  3: /* Recovery counter trap */
+		
+	case  2:
+		/* Power failure interrupt */
+		printk(KERN_CRIT "Power failure interrupt !\n");
+		return;
+
+	case  3:
+		/* Recovery counter trap */
 		regs->gr[0] &= ~PSW_R;
 		if (regs->iasq[0])
 			handle_gdb_break(regs, TRAP_TRACE);
-		/* else this must be the start of a syscall - just let it
-		 * run.
-		 */
+		/* else this must be the start of a syscall - just let it run */
 		return;
 
 	case  5:
+		/* Low-priority machine check */
 		flush_all_caches();
 		cpu_lpmc(5, regs);
 		return;
 
 	case  6:
+		/* Instruction TLB miss fault/Instruction page fault */
 		fault_address = regs->iaoq[0];
 		fault_space   = regs->iasq[0];
 		break;
 
-	case  9: /* Break Instruction */
+	case  8:
+		/* Illegal instruction trap */
+		die_if_kernel("Illegal instruction", regs, code);
+		si.si_code = ILL_ILLOPC;
+		goto give_sigill;
+
+	case  9:
+		/* Break instruction trap */
 		handle_break(regs->iir,regs);
 		return;
+	
+	case 10:
+		/* Privileged operation trap */
+		die_if_kernel("Privileged operation", regs, code);
+		si.si_code = ILL_PRVOPC;
+		goto give_sigill;
+	
+	case 11:
+		/* Privileged register trap */
+		if ((regs->iir & 0xffdfffe0) == 0x034008a0) {
+
+			/* This is a MFCTL cr26/cr27 to gr instruction.
+			 * PCXS traps on this, so we need to emulate it.
+			 */
+
+			if (regs->iir & 0x00200000)
+				regs->gr[regs->iir & 0x1f] = mfctl(27);
+			else
+				regs->gr[regs->iir & 0x1f] = mfctl(26);
+
+			regs->iaoq[0] = regs->iaoq[1];
+			regs->iaoq[1] += 4;
+			regs->iasq[0] = regs->iasq[1];
+			return;
+		}
+
+		die_if_kernel("Privileged register usage", regs, code);
+		si.si_code = ILL_PRVREG;
+	give_sigill:
+		si.si_signo = SIGILL;
+		si.si_errno = 0;
+		si.si_addr = (void *) regs->iaoq[0];
+		force_sig_info(SIGILL, &si, current);
+		return;
 
 	case 14:
 		/* Assist Exception Trap, i.e. floating point exception. */
 		die_if_kernel("Floating point exception", regs, 0); /* quiet */
 		handle_fpe(regs);
 		return;
-	case 15:
-	case 16:  /* Non-Access TLB miss faulting address is in IOR */
+
 	case 17:
-	case 26:
+		/* Non-access data TLB miss fault/Non-access data page fault */
+		/* TODO: Still need to add slow path emulation code here */
 		fault_address = regs->ior;
-		fault_space   = regs->isr;
+		parisc_terminate("Non access data tlb fault!",regs,code,fault_address);
 
-		if (code == 26 && fault_space == 0)
-		    parisc_terminate("Data access rights fault in kernel",regs,code,fault_address);
+	case 18:
+		/* PCXS only -- later cpu's split this into types 26,27 & 28 */
+		/* Check for unaligned access */
+		if (check_unaligned(regs)) {
+			handle_unaligned(regs);
+			return;
+		}
+		/* Fall Through */
+
+	case 15: /* Data TLB miss fault/Data page fault */
+	case 26: /* PCXL: Data memory access rights trap */
+		fault_address = regs->ior;
+		fault_space   = regs->isr;
 		break;
 
 	case 19:
+		/* Data memory break trap */
 		regs->gr[0] |= PSW_X; /* So we can single-step over the trap */
 		/* fall thru */
 	case 21:
+		/* Page reference trap */
 		handle_gdb_break(regs, TRAP_HWBKPT);
 		return;
 
-	case 25: /* Taken branch trap */
+	case 25:
+		/* Taken branch trap */
+#ifndef CONFIG_KWDB
 		regs->gr[0] &= ~PSW_T;
 		if (regs->iasq[0])
 			handle_gdb_break(regs, TRAP_BRANCH);
@@ -596,9 +607,8 @@
 		 * run.
 		 */
 		return;
-
-#if 0 /* def CONFIG_KWDB */
-	case I_TAKEN_BR:	/* 25 */
+#else
+		/* Kernel debugger: */
 		mtctl(0, 15);
 		pt_regs_to_ssp(regs, &ssp);
 		kgdb_trap(I_TAKEN_BR, &ssp, 1);
@@ -606,39 +616,64 @@
 		break;
 #endif /* CONFIG_KWDB */
 
-	case  8:
-		die_if_kernel("Illegal instruction", regs, code);
-		si.si_code = ILL_ILLOPC;
-		goto give_sigill;
+	case  7:  
+		/* Instruction access rights */
+		/* PCXL: Instruction memory protection trap */
+
+		/*
+		 * This could be caused by either: 1) a process attempting
+		 * to execute within a vma that does not have execute
+		 * permission, or 2) an access rights violation caused by a
+		 * flush only translation set up by ptep_get_and_clear().
+		 * So we check the vma permissions to differentiate the two.
+		 * If the vma indicates we have execute permission, then
+		 * the cause is the latter one. In this case, we need to
+		 * call do_page_fault() to fix the problem.
+		 */
 
-	case 10:
-		die_if_kernel("Priviledged operation - shouldn't happen!", regs, code);
-		si.si_code = ILL_PRVOPC;
-		goto give_sigill;
-	case 11:
-		die_if_kernel("Priviledged register - shouldn't happen!", regs, code);
-		si.si_code = ILL_PRVREG;
-	give_sigill:
-		si.si_signo = SIGILL;
+		if (user_mode(regs)) {
+			struct vm_area_struct *vma;
+
+			down_read(&current->mm->mmap_sem);
+			vma = find_vma(current->mm,regs->iaoq[0]);
+			if (vma && (regs->iaoq[0] >= vma->vm_start)
+				&& (vma->vm_flags & VM_EXEC)) {
+
+				fault_address = regs->iaoq[0];
+				fault_space = regs->iasq[0];
+
+				up_read(&current->mm->mmap_sem);
+				break; /* call do_page_fault() */
+			}
+			up_read(&current->mm->mmap_sem);
+		}
+		/* Fall Through */
+
+	case 27: 
+		/* Data memory protection ID trap */
+		die_if_kernel("Protection id trap", regs, code);
+		si.si_code = SEGV_MAPERR;
+		si.si_signo = SIGSEGV;
 		si.si_errno = 0;
-		si.si_addr = (void *) regs->iaoq[0];
-		force_sig_info(SIGILL, &si, current);
+		if (code == 7)
+		    si.si_addr = (void *) regs->iaoq[0];
+		else
+		    si.si_addr = (void *) regs->ior;
+		force_sig_info(SIGSEGV, &si, current);
 		return;
 
-	case 28:  /* Unaligned just causes SIGBUS for now */
-		die_if_kernel("Unaligned data reference", regs, code);
-		si.si_code = BUS_ADRALN;
-		si.si_signo = SIGBUS;
-		si.si_errno = 0;
-		si.si_addr = (void *) regs->ior;
-		force_sig_info(SIGBUS, &si, current);
+	case 28: 
+		/* Unaligned data reference trap */
+		handle_unaligned(regs);
 		return;
 
 	default:
 		if (user_mode(regs)) {
-			printk("\nhandle_interruption() pid=%d command='%s'\n",
+#ifdef PRINT_USER_FAULTS
+			printk(KERN_DEBUG "\nhandle_interruption() pid=%d command='%s'\n",
 			    current->pid, current->comm);
 			show_regs(regs);
+#endif
 			/* SIGBUS, for lack of a better one. */
 			si.si_signo = SIGBUS;
 			si.si_code = BUS_OBJERR;
@@ -647,18 +682,20 @@
 			force_sig_info(SIGBUS, &si, current);
 			return;
 		}
-		parisc_terminate("Unexpected Interruption!",regs,code,0);
+		parisc_terminate("Unexpected interruption", regs, code, 0);
 		/* NOT REACHED */
 	}
 
 	if (user_mode(regs)) {
 	    if (fault_space != regs->sr[7]) {
+#ifdef PRINT_USER_FAULTS
 		if (fault_space == 0)
-			printk("User Fault on Kernel Space ");
-		else /* this case should never happen, but whatever... */
-			printk("User Fault (long pointer) ");
+			printk(KERN_DEBUG "User Fault on Kernel Space ");
+		else
+			printk(KERN_DEBUG "User Fault (long pointer) ");
 		printk("pid=%d command='%s'\n", current->pid, current->comm);
 		show_regs(regs);
+#endif
 		si.si_signo = SIGSEGV;
 		si.si_errno = 0;
 		si.si_code = SEGV_MAPERR;
@@ -674,7 +711,7 @@
 	     */
 
 	    if (fault_space == 0)
-		    parisc_terminate("Kernel Fault",regs,code,fault_address);
+		    parisc_terminate("Kernel Fault", regs, code, fault_address);
 	}
 
 #ifdef CONFIG_KWDB
@@ -682,149 +719,15 @@
 #endif /* CONFIG_KWDB */
 
 	do_page_fault(regs, code, fault_address);
-
-	/*
-	 * This should not be necessary.
-	 * However, we do not currently
-	 * implement flush_page_to_ram.
-	 *
-	 * The problem is that if we just
-	 * brought in some code through the
-	 * D-cache, the I-cache may not see
-	 * it since it hasn't been flushed
-	 * to ram.
-	 */
-
-/* 	flush_all_caches(); */
-
-#if 0
-	printk("returning %p\n", regs);
-/*	show_regs(regs); */
-#endif
-
-	return;
-
-}
-
-void show_stack(unsigned long sp)
-{
-#if 1
-	if ((sp & 0xc0000000UL) == 0xc0000000UL) {
-
-	    __u32 *stackptr;
-	    __u32 *dumpptr;
-
-	    /* Stack Dump! */
-
-	    stackptr = (__u32 *)sp;
-	    dumpptr  = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1));
-	    printk("\nDumping Stack from %p to %p:\n",dumpptr,stackptr);
-	    while (dumpptr < stackptr) {
-		printk("%04x %08x %08x %08x %08x %08x %08x %08x %08x\n",
-		    ((__u32)dumpptr) & 0xffff,
-		    dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3],
-		    dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]);
-		dumpptr += 8;
-	    }
-	}
-#endif
 }
 
 
-void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset)
+void show_trace_task(struct task_struct *tsk)
 {
-	set_eiem(0);
-	cli();
-
-	if (code == 1)
-	    transfer_pim_to_trap_frame(regs);
-
-#if 1
-	show_stack(regs->gr[30]);
-#endif
-
-	printk("\n%s: Code=%d regs=%p (Addr=%08lx)\n",msg,code,regs,offset);
-	show_regs(regs);
-
-	for(;;)
-	    ;
+    	BUG();
 }
 
-void transfer_pim_to_trap_frame(struct pt_regs *regs)
-{
-    register int i;
-    extern unsigned int hpmc_pim_data[];
-    struct pdc_hpmc_pim_11 *pim_narrow;
-    struct pdc_hpmc_pim_20 *pim_wide;
-
-    if (boot_cpu_data.cpu_type >= pcxu) {
 
-	pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;
-
-	/*
-	 * Note: The following code will probably generate a
-	 * bunch of truncation error warnings from the compiler.
-	 * Could be handled with an ifdef, but perhaps there
-	 * is a better way.
-	 */
-
-	regs->gr[0] = pim_wide->cr[22];
-
-	for (i = 1; i < 32; i++)
-	    regs->gr[i] = pim_wide->gr[i];
-
-	for (i = 0; i < 32; i++)
-	    regs->fr[i] = pim_wide->fr[i];
-
-	for (i = 0; i < 8; i++)
-	    regs->sr[i] = pim_wide->sr[i];
-
-	regs->iasq[0] = pim_wide->cr[17];
-	regs->iasq[1] = pim_wide->iasq_back;
-	regs->iaoq[0] = pim_wide->cr[18];
-	regs->iaoq[1] = pim_wide->iaoq_back;
-
-	regs->cr30 = pim_wide->cr[30];
-	regs->sar  = pim_wide->cr[11];
-	regs->iir  = pim_wide->cr[19];
-	regs->isr  = pim_wide->cr[20];
-	regs->ior  = pim_wide->cr[21];
-    }
-    else {
-	pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;
-
-	regs->gr[0] = pim_narrow->cr[22];
-
-	for (i = 1; i < 32; i++)
-	    regs->gr[i] = pim_narrow->gr[i];
-
-	for (i = 0; i < 32; i++)
-	    regs->fr[i] = pim_narrow->fr[i];
-
-	for (i = 0; i < 8; i++)
-	    regs->sr[i] = pim_narrow->sr[i];
-
-	regs->iasq[0] = pim_narrow->cr[17];
-	regs->iasq[1] = pim_narrow->iasq_back;
-	regs->iaoq[0] = pim_narrow->cr[18];
-	regs->iaoq[1] = pim_narrow->iaoq_back;
-
-	regs->cr30 = pim_narrow->cr[30];
-	regs->sar  = pim_narrow->cr[11];
-	regs->iir  = pim_narrow->cr[19];
-	regs->isr  = pim_narrow->cr[20];
-	regs->ior  = pim_narrow->cr[21];
-    }
-
-    /*
-     * The following fields only have meaning if we came through
-     * another path. So just zero them here.
-     */
-
-    regs->ksp = 0;
-    regs->kpc = 0;
-    regs->orig_r28 = 0;
-}
 
 int __init check_ivt(void *iva)
 {
@@ -836,7 +739,7 @@
 	extern void os_hpmc(void);
 	extern void os_hpmc_end(void);
 
-	if(strcmp((char *)iva, "cows can fly"))
+	if (strcmp((char *)iva, "cows can fly"))
 		return -1;
 
 	ivap = (u32 *)iva;
@@ -851,10 +754,10 @@
 
 	hpmcp = (u32 *)os_hpmc;
 
-	for(i=0; i<length/4; i++)
+	for (i=0; i<length/4; i++)
 	    check += *hpmcp++;
 
-	for(i=0; i<8; i++)
+	for (i=0; i<8; i++)
 	    check += ivap[i];
 
 	ivap[5] = -check;
@@ -869,11 +772,8 @@
 
 void __init trap_init(void)
 {
-	volatile long eiem;
 	void *iva;
 
-	printk("trap_init\n");
-	
 	if (boot_cpu_data.cpu_type >= pcxu)
 		iva = (void *) &fault_vector_20;
 	else
@@ -883,12 +783,6 @@
 		iva = (void *) &fault_vector_11;
 #endif
 
-	if(check_ivt(iva))
+	if (check_ivt(iva))
 		panic("IVT invalid");
-
-	mtctl(0, 30);
-	mtctl(90000000, 16);
-	set_eiem(-1L);
-	mtctl(-1L, 23);
-	asm volatile ("rsm 0,%0" : "=r" (eiem));
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/kernel/unaligned.c linux/arch/parisc/kernel/unaligned.c
--- linux.orig/arch/parisc/kernel/unaligned.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/kernel/unaligned.c	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,434 @@
+/*    $Id: unaligned.c,v 1.9 2001/10/04 03:31:08 tausq Exp $
+ *
+ *    Unaligned memory access handler
+ *
+ *    Copyright (C) 2001 Randolph Chung <tausq@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+
+#include <asm/smp.h>
+#include <asm/pdc.h>
+
+/* #define DEBUG_UNALIGNED 1 */
+
+#ifdef DEBUG_UNALIGNED
+#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0)
+#else
+#define DPRINTF(fmt, args...)
+#endif
+
+#ifdef __LP64__
+#define RFMT "%016lx"
+#else
+#define RFMT "%08lx"
+#endif
+
+/* 1111 1100 0000 0000 0001 0011 1100 0000 */
+#define OPCODE1(a,b,c)	((a)<<26|(b)<<12|(c)<<6) 
+#define OPCODE2(a,b)	((a)<<26|(b)<<1)
+#define OPCODE3(a,b)	((a)<<26|(b)<<2)
+#define OPCODE4(a)	((a)<<26)
+#define OPCODE1_MASK	OPCODE1(0x3f,1,0xf)
+#define OPCODE2_MASK 	OPCODE2(0x3f,1)
+#define OPCODE3_MASK	OPCODE3(0x3f,1)
+#define OPCODE4_MASK    OPCODE4(0x3f)
+
+/* skip LDB (index) */
+#define OPCODE_LDH_I	OPCODE1(0x03,0,0x1)
+#define OPCODE_LDW_I	OPCODE1(0x03,0,0x2)
+#define OPCODE_LDD_I	OPCODE1(0x03,0,0x3)
+#define OPCODE_LDDA_I	OPCODE1(0x03,0,0x4)
+/* skip LDCD (index) */
+#define OPCODE_LDWA_I	OPCODE1(0x03,0,0x6)
+/* skip LDCW (index) */
+/* skip LDB (short) */
+#define OPCODE_LDH_S	OPCODE1(0x03,1,0x1)
+#define OPCODE_LDW_S	OPCODE1(0x03,1,0x2)
+#define OPCODE_LDD_S	OPCODE1(0x03,1,0x3)
+#define OPCODE_LDDA_S	OPCODE1(0x03,1,0x4)
+/* skip LDCD (short) */
+#define OPCODE_LDWA_S	OPCODE1(0x03,1,0x6)
+/* skip LDCW (short) */
+/* skip STB */
+#define OPCODE_STH	OPCODE1(0x03,1,0x9)
+#define OPCODE_STW	OPCODE1(0x03,1,0xa)
+#define OPCODE_STD	OPCODE1(0x03,1,0xb)
+/* skip STBY */
+/* skip STDBY */
+#define OPCODE_STWA	OPCODE1(0x03,1,0xe)
+#define OPCODE_STDA	OPCODE1(0x03,1,0xf)
+
+#define OPCODE_LDD_L	OPCODE2(0x14,0)
+#define OPCODE_FLDD_L	OPCODE2(0x14,1)
+#define OPCODE_STD_L	OPCODE2(0x1c,0)
+#define OPCODE_FSTD_L	OPCODE2(0x1c,1)
+
+#define OPCODE_LDW_M	OPCODE3(0x17,1)
+#define OPCODE_FLDW_L	OPCODE3(0x17,0)
+#define OPCODE_FSTW_L	OPCODE3(0x1f,0)
+#define OPCODE_STW_M	OPCODE3(0x1f,1)
+
+#define OPCODE_LDH_L    OPCODE4(0x11)
+#define OPCODE_LDW_L    OPCODE4(0x12)
+#define OPCODE_LDW_L2   OPCODE4(0x13)
+#define OPCODE_STH_L    OPCODE4(0x19)
+#define OPCODE_STW_L    OPCODE4(0x1A)
+#define OPCODE_STW_L2   OPCODE4(0x1B)
+
+
+
+void die_if_kernel (char *str, struct pt_regs *regs, long err);
+
+static int emulate_load(struct pt_regs *regs, int len, int toreg)
+{
+	unsigned long saddr = regs->ior;
+	unsigned long val = 0;
+	int ret = 0;
+
+	if (regs->isr != regs->sr[7])
+	{
+		printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n",
+			regs->isr, regs->sr[7]);
+		return 1;
+	}
+
+	DPRINTF("load " RFMT ":" RFMT " to r%d for %d bytes\n", 
+		regs->isr, regs->ior, toreg, len);
+
+	__asm__ __volatile__  (
+"       mfsp %%sr1, %%r20\n"
+"       mtsp %6, %%sr1\n"
+"	copy %%r0, %0\n"
+"0:	ldbs,ma	1(%%sr1,%4), %%r19\n"
+"	addi -1, %5, %5\n"
+"	cmpib,>= 0, %5, 2f\n"
+"	or %%r19, %0, %0\n"
+"	b 0b\n"
+	
+#ifdef __LP64__
+	"depd,z %0, 55, 56, %0\n"
+#else
+	"depw,z %0, 23, 24, %0\n"
+#endif
+	
+"1:	ldi	10, %1\n"
+"2:     mtsp %%r20, %%sr1\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+	".dword 0b, (1b-0b)\n"
+#else
+	".word 0b, (1b-0b)\n"
+#endif
+	".previous\n" 
+	: "=r" (val), "=r" (ret)
+	: "0" (val), "1" (ret), "r" (saddr), "r" (len), "r" (regs->isr)
+	: "r19", "r20" );
+
+	DPRINTF("val = 0x" RFMT "\n", val);
+
+	regs->gr[toreg] = val;
+
+	return ret;
+}
+
+static int emulate_store(struct pt_regs *regs, int len, int frreg)
+{
+	int ret = 0;
+#ifdef __LP64__
+	unsigned long val = regs->gr[frreg] << (64 - (len << 3));
+#else
+	unsigned long val = regs->gr[frreg] << (32 - (len << 3));
+#endif
+
+	if (regs->isr != regs->sr[7])
+	{
+		printk(KERN_CRIT "isr verification failed (isr: " RFMT ", sr7: " RFMT "\n",
+			regs->isr, regs->sr[7]);
+		return 1;
+	}
+
+	DPRINTF("store r%d (0x" RFMT ") to " RFMT ":" RFMT " for %d bytes\n", frreg, 
+		regs->gr[frreg], regs->isr, regs->ior, len);
+
+
+	__asm__ __volatile__ (
+"       mfsp %%sr1, %%r20\n"		/* save sr1 */
+"       mtsp %5, %%sr1\n"
+#ifdef __LP64__
+"0:	extrd,u %2, 7, 8, %%r19\n"
+#else
+"0:	extrw,u %2, 7, 8, %%r19\n"
+#endif
+"1:	stb,ma %%r19, 1(%%sr1, %3)\n"
+"	addi -1, %4, %4\n"
+"	cmpib,>= 0, %4, 3f\n"
+	
+#ifdef __LP64__
+	"depd,z %2, 55, 56, %2\n"
+#else
+	"depw,z %2, 23, 24, %2\n"
+#endif
+
+"	b 0b\n"
+"	nop\n"
+
+"2:	ldi 11, %0\n"
+"3:     mtsp %%r20, %%sr1\n"
+"	.section __ex_table,\"a\"\n"
+#ifdef __LP64__
+	".dword 1b, (2b-1b)\n"
+#else
+	".word 1b, (2b-1b)\n"
+#endif
+	".previous\n" 
+	: "=r" (ret)
+	: "0" (ret), "r" (val), "r" (regs->ior), "r" (len), "r" (regs->isr)
+	: "r19", "r20" );
+
+	return ret;
+}
+
+
+void handle_unaligned(struct pt_regs *regs)
+{
+	unsigned long unaligned_count = 0;
+	unsigned long last_time = 0;
+	int ret = -1;
+	struct siginfo si;
+
+	/* if the unaligned access is inside the kernel:
+	 *   if the access is caused by a syscall, then we fault the calling
+	 *     user process
+	 *   otherwise we halt the kernel
+	 */
+	if (!user_mode(regs))
+	{
+		const struct exception_table_entry *fix;
+
+		/* see if the offending code have its own
+		 * exception handler 
+		 */ 
+
+		fix = search_exception_table(regs->iaoq[0]);
+		if (fix)
+		{
+			/* lower bits of fix->skip are flags
+			 * upper bits are the handler addr
+			 */
+			if (fix->skip & 1)
+				regs->gr[8] = -EFAULT;
+			if (fix->skip & 2)
+				regs->gr[9] = 0;
+
+			regs->iaoq[0] += ((fix->skip) & ~3);
+			regs->iaoq[1] = regs->iaoq[0] + 4;
+			regs->gr[0] &= ~PSW_B;
+
+			return;
+		}
+	}
+
+	/* log a message with pacing */
+	if (user_mode(regs))
+	{
+		if (unaligned_count > 5 && jiffies - last_time > 5*HZ)
+		{
+			unaligned_count = 0;
+			last_time = jiffies;
+		}
+		if (++unaligned_count < 5)
+		{
+			char buf[256];
+			sprintf(buf, "%s(%d): unaligned access to 0x" RFMT " at ip=0x" RFMT "\n",
+				current->comm, current->pid, regs->ior, regs->iaoq[0]);
+			printk(KERN_WARNING "%s", buf);
+#ifdef DEBUG_UNALIGNED
+			show_regs(regs);
+#endif		
+		}
+	}
+
+	/* TODO: make this cleaner... */
+	switch (regs->iir & OPCODE1_MASK)
+	{
+	case OPCODE_LDH_I:
+	case OPCODE_LDH_S:
+		ret = emulate_load(regs, 2, regs->iir & 0x1f);
+		break;
+
+	case OPCODE_LDW_I:
+	case OPCODE_LDWA_I:
+	case OPCODE_LDW_S:
+	case OPCODE_LDWA_S:
+		ret = emulate_load(regs, 4, regs->iir&0x1f);
+		break;
+
+	case OPCODE_LDD_I:
+	case OPCODE_LDDA_I:
+	case OPCODE_LDD_S:
+	case OPCODE_LDDA_S:
+		ret = emulate_load(regs, 8, regs->iir&0x1f);
+		break;
+
+	case OPCODE_STH:
+		ret = emulate_store(regs, 2, (regs->iir>>16)&0x1f);
+		break;
+
+	case OPCODE_STW:
+	case OPCODE_STWA:
+		ret = emulate_store(regs, 4, (regs->iir>>16)&0x1f);
+		break;
+
+	case OPCODE_STD:
+	case OPCODE_STDA:
+		ret = emulate_store(regs, 8, (regs->iir>>16)&0x1f);
+		break;
+	}
+	switch (regs->iir & OPCODE2_MASK)
+	{
+	case OPCODE_LDD_L:
+	case OPCODE_FLDD_L:
+		ret = emulate_load(regs, 8, (regs->iir>>16)&0x1f);
+		break;
+
+	case OPCODE_STD_L:
+	case OPCODE_FSTD_L:
+		ret = emulate_store(regs, 8, (regs->iir>>16)&0x1f);
+		break;
+	}
+	switch (regs->iir & OPCODE3_MASK)
+	{
+	case OPCODE_LDW_M:
+	case OPCODE_FLDW_L:
+		ret = emulate_load(regs, 4, (regs->iir>>16)&0x1f);
+		break;
+
+	case OPCODE_FSTW_L:
+	case OPCODE_STW_M:
+		ret = emulate_store(regs, 4, (regs->iir>>16)&0x1f);
+		break;
+	}
+	switch (regs->iir & OPCODE4_MASK)
+	{
+	case OPCODE_LDH_L:
+		ret = emulate_load(regs, 2, (regs->iir>>16)&0x1f);
+		break;
+	case OPCODE_LDW_L:
+	case OPCODE_LDW_L2:
+		ret = emulate_load(regs, 4, (regs->iir>>16)&0x1f);
+		break;
+	case OPCODE_STH_L:
+		ret = emulate_store(regs, 2, (regs->iir>>16)&0x1f);
+		break;
+	case OPCODE_STW_L:
+	case OPCODE_STW_L2:
+		ret = emulate_store(regs, 4, (regs->iir>>16)&0x1f);
+		break;
+	}
+
+	if (ret < 0)
+		printk(KERN_CRIT "Not-handled unaligned insn 0x%08lx\n", regs->iir);
+
+	DPRINTF("ret = %d\n", ret);
+
+	if (ret)
+	{
+		printk(KERN_CRIT "Unaligned handler failed, ret = %d\n", ret);
+		die_if_kernel("Unaligned data reference", regs, 28);
+
+		/* couldn't handle it ... */
+		si.si_signo = SIGBUS;
+		si.si_errno = 0;
+		si.si_code = BUS_ADRALN;
+		si.si_addr = (void *)regs->ior;
+		force_sig_info(SIGBUS, &si, current);
+		
+		return;
+	}
+
+	/* else we handled it, advance the PC.... */
+	regs->iaoq[0] = regs->iaoq[1];
+	regs->iaoq[1] = regs->iaoq[0] + 4;
+}
+
+/*
+ * NB: check_unaligned() is only used for PCXS processors right
+ * now, so we only check for PA1.1 encodings at this point.
+ */
+
+int
+check_unaligned(struct pt_regs *regs)
+{
+	unsigned long align_mask;
+
+	/* Get alignment mask */
+
+	align_mask = 0UL;
+	switch (regs->iir & OPCODE1_MASK) {
+
+	case OPCODE_LDH_I:
+	case OPCODE_LDH_S:
+	case OPCODE_STH:
+		align_mask = 1UL;
+		break;
+
+	case OPCODE_LDW_I:
+	case OPCODE_LDWA_I:
+	case OPCODE_LDW_S:
+	case OPCODE_LDWA_S:
+	case OPCODE_STW:
+	case OPCODE_STWA:
+		align_mask = 3UL;
+		break;
+
+	default:
+		switch (regs->iir & OPCODE4_MASK) {
+		case OPCODE_LDH_L:
+		case OPCODE_STH_L:
+			align_mask = 1UL;
+			break;
+		case OPCODE_LDW_L:
+		case OPCODE_LDW_L2:
+		case OPCODE_STW_L:
+		case OPCODE_STW_L2:
+			align_mask = 3UL;
+			break;
+		}
+		break;
+	}
+
+	return (int)(regs->ior & align_mask);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/lib/Makefile linux/arch/parisc/lib/Makefile
--- linux.orig/arch/parisc/lib/Makefile	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/lib/Makefile	2002-08-12 22:14:21.000000000 +0000
@@ -4,10 +4,6 @@
 
 
 L_TARGET = lib.a
-L_OBJS	= lusercopy.o bitops.o checksum.o
-
-
-.S.o:
-	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+obj-y	:= lusercopy.o bitops.o checksum.o io.o memset.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/lib/bitops.c linux/arch/parisc/lib/bitops.c
--- linux.orig/arch/parisc/lib/bitops.c	2000-12-06 19:46:39.000000000 +0000
+++ linux/arch/parisc/lib/bitops.c	2002-08-12 22:14:03.000000000 +0000
@@ -1,7 +1,10 @@
-/* atomic.c: atomic operations which got too long to be inlined all over
- * the place.
+/*
+ * bitops.c: atomic operations which got too long to be inlined all over
+ *      the place.
  * 
- * Copyright 1999 Philipp Rumpf (prumpf@tux.org */
+ * Copyright 1999 Philipp Rumpf (prumpf@tux.org)
+ * Copyright 2000 Grant Grundler (grundler@cup.hp.com)
+ */
 
 #include <linux/config.h>
 #include <linux/kernel.h>
@@ -17,44 +20,67 @@
 
 spinlock_t __atomic_lock = SPIN_LOCK_UNLOCKED;
 
-#ifndef __LP64__
-unsigned long __xchg(unsigned long x, unsigned long *ptr, int size)
+#ifdef __LP64__
+unsigned long __xchg64(unsigned long x, unsigned long *ptr)
 {
 	unsigned long temp, flags;
 
-	if (size != sizeof x) {
-		printk("__xchg called with bad pointer\n");
-	}
-	spin_lock_irqsave(&__atomic_lock, flags);
+	SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags);
 	temp = *ptr;
 	*ptr = x;
-	spin_unlock_irqrestore(&__atomic_lock, flags);
+	SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags);
 	return temp;
 }
-#else
-unsigned long __xchg(unsigned long x, unsigned long *ptr, int size)
+#endif
+
+unsigned long __xchg32(int x, int *ptr)
 {
-	unsigned long temp, flags;
-	unsigned int *ptr32;
+	unsigned long flags;
+	unsigned long temp;
+
+	SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags);
+	(long) temp = (long) *ptr;	/* XXX - sign extension wanted? */
+	*ptr = x;
+	SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags);
+	return temp;
+}
+
+
+unsigned long __xchg8(char x, char *ptr)
+{
+	unsigned long flags;
+	unsigned long temp;
 
-	if (size == 8) {
-try_long:
-		spin_lock_irqsave(&__atomic_lock, flags);
-		temp = *ptr;
-		*ptr = x;
-		spin_unlock_irqrestore(&__atomic_lock, flags);
-		return temp;
-	}
-	if (size == 4) {
-		ptr32 = (unsigned int *)ptr;
-		spin_lock_irqsave(&__atomic_lock, flags);
-		temp = (unsigned long)*ptr32;
-		*ptr32 = (unsigned int)x;
-		spin_unlock_irqrestore(&__atomic_lock, flags);
-		return temp;
-	}
+	SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags);
+	(long) temp = (long) *ptr;	/* XXX - sign extension wanted? */
+	*ptr = x;
+	SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags);
+	return temp;
+}
+
+
+#ifdef __LP64__
+unsigned long __cmpxchg_u64(volatile unsigned long *ptr, unsigned long old, unsigned long new)
+{
+	unsigned long flags;
+	unsigned long prev;
 
-	printk("__xchg called with bad pointer\n");
-	goto try_long;
+	SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags);
+	if ((prev = *ptr) == old)
+		*ptr = new;
+	SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags);
+	return prev;
 }
 #endif
+
+unsigned long __cmpxchg_u32(volatile unsigned int *ptr, unsigned int old, unsigned int new)
+{
+	unsigned long flags;
+	unsigned int prev;
+
+	SPIN_LOCK_IRQSAVE(ATOMIC_HASH(ptr), flags);
+	if ((prev = *ptr) == old)
+		*ptr = new;
+	SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(ptr), flags);
+	return (unsigned long)prev;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/lib/io.c linux/arch/parisc/lib/io.c
--- linux.orig/arch/parisc/lib/io.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/lib/io.c	2002-08-12 22:14:21.000000000 +0000
@@ -0,0 +1,459 @@
+/*
+ * arch/parisc/lib/io.c
+ *
+ * Copyright (c) Matthew Wilcox 2001 for Hewlett-Packard
+ * Copyright (c) Randolph Chung 2001 <tausq@debian.org>
+ *
+ * IO accessing functions which shouldn't be inlined because they're too big
+ */
+
+#include <linux/kernel.h>
+#include <asm/io.h>
+
+/* Copies a block of memory to a device in an efficient manner.
+ * Assumes the device can cope with 32-bit transfers.  If it can't,
+ * don't use this function.
+ */
+void memcpy_toio(unsigned long dest, const void *src, int count)
+{
+	if ((dest & 3) != ((unsigned long)src & 3))
+		goto bytecopy;
+	while (dest & 3) {
+		writeb(*(char *)src, dest++);
+		((char *)src)++;
+		count--;
+	}
+	while (count > 3) {
+		__raw_writel(*(u32 *)src, dest);
+		(unsigned long) src += 4;
+		dest += 4;
+		count -= 4;
+	}
+ bytecopy:
+	while (count--) {
+		writeb(*(char *)src, dest++);
+		((char *)src)++;
+	}
+}
+
+/*
+** Copies a block of memory from a device in an efficient manner.
+** Assumes the device can cope with 32-bit transfers.  If it can't,
+** don't use this function.
+**
+** CR16 counts on C3000 reading 256 bytes from Symbios 896 RAM:
+**	27341/64    = 427 cyc per int
+**	61311/128   = 478 cyc per short
+**	122637/256  = 479 cyc per byte
+** Ergo bus latencies dominant (not transfer size).
+**      Minimize total number of transfers at cost of CPU cycles.
+**	TODO: only look at src alignment and adjust the stores to dest.
+*/
+void memcpy_fromio(void *dest, unsigned long src, int count)
+{
+	/* first compare alignment of src/dst */ 
+	if ( (((unsigned long)dest ^ src) & 1) || (count < 2) )
+		goto bytecopy;
+
+	if ( (((unsigned long)dest ^ src) & 2) || (count < 4) )
+		goto shortcopy;
+
+	/* Then check for misaligned start address */
+	if (src & 1) {
+		*(u8 *)dest = readb(src);
+		((u8 *)src)++;
+		((u8 *)dest)++;
+		count--;
+		if (count < 2) goto bytecopy;
+	}
+
+	if (src & 2) {
+		*(u16 *)dest = __raw_readw(src);
+		((u16 *)src)++;
+		((u16 *)dest)++;
+		count-=2;
+	}
+
+	while (count > 3) {
+		*(u32 *)dest = __raw_readl(src);
+		dest += 4;
+		src += 4;
+		count -= 4;
+	}
+
+ shortcopy:
+	while (count > 1) {
+		*(u16 *)dest = __raw_readw(src);
+		((u16 *)src)++;
+		((u16 *)dest)++;
+		count-=2;
+	}
+
+ bytecopy:
+	while (count--) {
+		*(char *)dest = readb(src);
+		((char *)src)++;
+		((char *)dest)++;
+	}
+}
+
+/* Sets a block of memory on a device to a given value.
+ * Assumes the device can cope with 32-bit transfers.  If it can't,
+ * don't use this function.
+ */
+void memset_io(unsigned long dest, char fill, int count)
+{
+	u32 fill32 = (fill << 24) | (fill << 16) | (fill << 8) | fill;
+	while (dest & 3) {
+		writeb(fill, dest++);
+		count--;
+	}
+	while (count > 3) {
+		__raw_writel(fill32, dest);
+		dest += 4;
+		count -= 4;
+	}
+	while (count--) {
+		writeb(fill, dest++);
+	}
+}
+
+/*
+ * Read COUNT 8-bit bytes from port PORT into memory starting at
+ * SRC.
+ */
+void insb (unsigned long port, void *dst, unsigned long count)
+{
+	while (((unsigned long)dst) & 0x3) {
+		if (!count)
+			return;
+		count--;
+		*(unsigned char *) dst = inb(port);
+		((unsigned char *) dst)++;
+	}
+
+	while (count >= 4) {
+		unsigned int w;
+		count -= 4;
+		w = inb(port) << 24;
+		w |= inb(port) << 16;
+		w |= inb(port) << 8;
+		w |= inb(port);
+		*(unsigned int *) dst = w;
+		((unsigned int *) dst)++;
+	}
+
+	while (count) {
+		--count;
+		*(unsigned char *) dst = inb(port);
+		((unsigned char *) dst)++;
+	}
+}
+
+
+/*
+ * Read COUNT 16-bit words from port PORT into memory starting at
+ * SRC.  SRC must be at least short aligned.  This is used by the
+ * IDE driver to read disk sectors.  Performance is important, but
+ * the interfaces seems to be slow: just using the inlined version
+ * of the inw() breaks things.
+ */
+void insw (unsigned long port, void *dst, unsigned long count)
+{
+	unsigned int l = 0, l2;
+	
+	if (!count)
+		return;
+	
+	switch (((unsigned long) dst) & 0x3)
+	{
+	 case 0x00:			/* Buffer 32-bit aligned */
+		while (count>=2) {
+			
+			count -= 2;
+			l = cpu_to_le16(inw(port)) << 16;
+			l |= cpu_to_le16(inw(port));
+			*(unsigned int *) dst = l;
+			((unsigned int *) dst)++;
+		}
+		if (count) {
+			*(unsigned short *) dst = cpu_to_le16(inw(port));
+		}
+		break;
+	
+	 case 0x02:			/* Buffer 16-bit aligned */
+		*(unsigned short *) dst = cpu_to_le16(inw(port));
+		((unsigned short *) dst)++;
+		count--;
+		while (count>=2) {
+			
+			count -= 2;
+			l = cpu_to_le16(inw(port)) << 16;
+			l |= cpu_to_le16(inw(port));
+			*(unsigned int *) dst = l;
+			((unsigned int *) dst)++;
+		}
+		if (count) {
+			*(unsigned short *) dst = cpu_to_le16(inw(port));
+		}
+		break;
+		
+	 case 0x01:			/* Buffer 8-bit aligned */
+	 case 0x03:
+		/* I don't bother with 32bit transfers
+		 * in this case, 16bit will have to do -- DE */
+		--count;
+		
+		l = cpu_to_le16(inw(port));
+		*(unsigned char *) dst = l >> 8;
+		((unsigned char *) dst)++;
+		while (count--)
+		{
+			l2 = cpu_to_le16(inw(port));
+			*(unsigned short *) dst = (l & 0xff) << 8 | (l2 >> 8);
+			((unsigned short *) dst)++;
+			l = l2;
+		}
+		*(unsigned char *) dst = l & 0xff;
+		break;
+	}
+}
+
+
+
+/*
+ * Read COUNT 32-bit words from port PORT into memory starting at
+ * SRC. Now works with any alignment in SRC. Performance is important,
+ * but the interfaces seems to be slow: just using the inlined version
+ * of the inl() breaks things.
+ */
+void insl (unsigned long port, void *dst, unsigned long count)
+{
+	unsigned int l = 0, l2;
+	
+	if (!count)
+		return;
+	
+	switch (((unsigned long) dst) & 0x3)
+	{
+	 case 0x00:			/* Buffer 32-bit aligned */
+		while (count--)
+		{
+			*(unsigned int *) dst = cpu_to_le32(inl(port));
+			((unsigned int *) dst)++;
+		}
+		break;
+	
+	 case 0x02:			/* Buffer 16-bit aligned */
+		--count;
+		
+		l = cpu_to_le32(inl(port));
+		*(unsigned short *) dst = l >> 16;
+		((unsigned short *) dst)++;
+		
+		while (count--)
+		{
+			l2 = cpu_to_le32(inl(port));
+			*(unsigned int *) dst = (l & 0xffff) << 16 | (l2 >> 16);
+			((unsigned int *) dst)++;
+			l = l2;
+		}
+		*(unsigned short *) dst = l & 0xffff;
+		break;
+	 case 0x01:			/* Buffer 8-bit aligned */
+		--count;
+		
+		l = cpu_to_le32(inl(port));
+		*(unsigned char *) dst = l >> 24;
+		((unsigned char *) dst)++;
+		*(unsigned short *) dst = (l >> 8) & 0xffff;
+		((unsigned short *) dst)++;
+		while (count--)
+		{
+			l2 = cpu_to_le32(inl(port));
+			*(unsigned int *) dst = (l & 0xff) << 24 | (l2 >> 8);
+			((unsigned int *) dst)++;
+			l = l2;
+		}
+		*(unsigned char *) dst = l & 0xff;
+		break;
+	 case 0x03:			/* Buffer 8-bit aligned */
+		--count;
+		
+		l = cpu_to_le32(inl(port));
+		*(unsigned char *) dst = l >> 24;
+		((unsigned char *) dst)++;
+		while (count--)
+		{
+			l2 = cpu_to_le32(inl(port));
+			*(unsigned int *) dst = (l & 0xffffff) << 8 | l2 >> 24;
+			((unsigned int *) dst)++;
+			l = l2;
+		}
+		*(unsigned short *) dst = (l >> 8) & 0xffff;
+		((unsigned short *) dst)++;
+		*(unsigned char *) dst = l & 0xff;
+		break;
+	}
+}
+
+
+/*
+ * Like insb but in the opposite direction.
+ * Don't worry as much about doing aligned memory transfers:
+ * doing byte reads the "slow" way isn't nearly as slow as
+ * doing byte writes the slow way (no r-m-w cycle).
+ */
+void outsb(unsigned long port, const void * src, unsigned long count)
+{
+	while (count) {
+		count--;
+		outb(*(char *)src, port);
+		((char *) src)++;
+	}
+}
+
+/*
+ * Like insw but in the opposite direction.  This is used by the IDE
+ * driver to write disk sectors.  Performance is important, but the
+ * interfaces seems to be slow: just using the inlined version of the
+ * outw() breaks things.
+ */
+void outsw (unsigned long port, const void *src, unsigned long count)
+{
+	unsigned int l = 0, l2;
+	
+	if (!count)
+		return;
+	
+	switch (((unsigned long) src) & 0x3)
+	{
+	 case 0x00:			/* Buffer 32-bit aligned */
+		while (count>=2) {
+			count -= 2;
+			l = *(unsigned int *) src;
+			((unsigned int *) src)++;
+			outw(le16_to_cpu(l >> 16), port);
+			outw(le16_to_cpu(l & 0xffff), port);
+		}
+		if (count) {
+			outw(le16_to_cpu(*(unsigned short*)src), port);
+		}
+		break;
+	
+	 case 0x02:			/* Buffer 16-bit aligned */
+		
+		outw(le16_to_cpu(*(unsigned short*)src), port);
+		((unsigned short *) src)++;
+		count--;
+		
+		while (count>=2) {
+			count -= 2;
+			l = *(unsigned int *) src;
+			((unsigned int *) src)++;
+			outw(le16_to_cpu(l >> 16), port);
+			outw(le16_to_cpu(l & 0xffff), port);
+		}
+		if (count) {
+			outw(le16_to_cpu(*(unsigned short*)src), port);
+		}
+		break;
+		
+	 case 0x01:			/* Buffer 8-bit aligned */	
+		/* I don't bother with 32bit transfers
+		 * in this case, 16bit will have to do -- DE */
+		
+		l  = *(unsigned char *) src << 8;
+		((unsigned char *) src)++;
+		count--;
+		while (count)
+		{
+			count--;
+			l2 = *(unsigned short *) src;
+			((unsigned short *) src)++;
+			outw(le16_to_cpu(l | l2 >> 8), port);
+		        l = l2 << 8;
+		}
+		l2 = *(unsigned char *) src;
+		outw (le16_to_cpu(l | l2>>8), port);
+		break;
+	
+	}
+}
+
+
+/*
+ * Like insl but in the opposite direction.  This is used by the IDE
+ * driver to write disk sectors.  Works with any alignment in SRC.
+ *  Performance is important, but the interfaces seems to be slow:
+ * just using the inlined version of the outl() breaks things.
+ */
+void outsl (unsigned long port, const void *src, unsigned long count)
+{
+	unsigned int l = 0, l2;
+	
+	if (!count)
+		return;
+	
+	switch (((unsigned long) src) & 0x3)
+	{
+	 case 0x00:			/* Buffer 32-bit aligned */
+		while (count--)
+		{
+			outl(le32_to_cpu(*(unsigned int *) src), port);
+			((unsigned int *) src)++;
+		}
+		break;
+	
+	 case 0x02:			/* Buffer 16-bit aligned */
+		--count;
+		
+		l = *(unsigned short *) src;
+		((unsigned short *) src)++;
+		
+		while (count--)
+		{
+			l2 = *(unsigned int *) src;
+			((unsigned int *) src)++;
+			outl (le32_to_cpu(l << 16 | l2 >> 16), port);
+			l = l2;
+		}
+		l2 = *(unsigned short *) src;
+		outl (le32_to_cpu(l << 16 | l2), port);
+		break;
+	 case 0x01:			/* Buffer 8-bit aligned */
+		--count;
+		
+		l  = *(unsigned char *) src << 24;
+		((unsigned char *) src)++;
+		l |= *(unsigned short *) src << 8;
+		((unsigned short *) src)++;
+		while (count--)
+		{
+			l2 = *(unsigned int *) src;
+			((unsigned int *) src)++;
+			outl (le32_to_cpu(l | l2 >> 24), port);
+			l = l2 << 8;
+		}
+		l2 = *(unsigned char *) src;
+		      outl (le32_to_cpu(l | l2), port);
+		break;
+	 case 0x03:			/* Buffer 8-bit aligned */
+		--count;
+		
+		l  = *(unsigned char *) src << 24;
+		((unsigned char *) src)++;
+		while (count--)
+		{
+			l2 = *(unsigned int *) src;
+			((unsigned int *) src)++;
+			outl (le32_to_cpu(l | l2 >> 8), port);
+			l = l2 << 24;
+		}
+		l2  = *(unsigned short *) src << 16;
+		((unsigned short *) src)++;
+		l2 |= *(unsigned char *) src;
+		outl (le32_to_cpu(l | l2), port);
+		break;
+	}
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/lib/lusercopy.S linux/arch/parisc/lib/lusercopy.S
--- linux.orig/arch/parisc/lib/lusercopy.S	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/lib/lusercopy.S	2002-08-12 22:14:02.000000000 +0000
@@ -1,5 +1,5 @@
-/*------------------------------------------------------------------------------
- * Native PARISC/Linux Project (http://www.puffingroup.com/parisc)
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
  *
  * Assembly Language User Access Routines
  *  Copyright (C) 2000 Hewlett-Packard (John Marvin)
@@ -30,7 +30,6 @@
  */
 
 
-	.level		1.1
 	.text
 	
 #include <asm/assembly.h>
@@ -42,11 +41,8 @@
 	 * on the flag stored in the task structure.
 	 */
 
-	/* FIXME! depi below has hardcoded idea of kernel stack size */
-
 	.macro  get_sr
-	copy        %r30,%r1        ;! Get task structure
-	depi        0,31,14,%r1     ;! into r1
+	mfctl       %cr30,%r1
 	ldw         TASK_SEGMENT(%r1),%r22
 	mfsp        %sr3,%r1
 	or,<>       %r22,%r0,%r0
@@ -82,7 +78,11 @@
 	ldo         1(%r24),%r24
 
 	.section __ex_table,"a"
+#ifdef __LP64__
+	.dword      1b,(2b-1b)
+#else
 	.word       1b,(2b-1b)
+#endif
 	.previous
 
 	.procend
@@ -123,7 +123,11 @@
 	nop
 
 	.section __ex_table,"a"
+#ifdef __LP64__
+	.dword      1b,(2b-1b)
+#else
 	.word       1b,(2b-1b)
+#endif
 	.previous
 
 	.procend
@@ -133,7 +137,7 @@
 	 *
 	 * Returns -EFAULT if exception before terminator,
 	 *         N if the entire buffer filled,
-	 *         otherwise strlen + 1 (i.e. includes zero byte)
+	 *         otherwise strlen (i.e. excludes zero byte)
 	 */
 
 	.export lstrncpy_from_user,code
@@ -142,7 +146,7 @@
 	.callinfo NO_CALLS
 	.entry
 	comib,=     0,%r24,$lsfu_done
-	copy        %r26,%r23
+	copy        %r24,%r23
 	get_sr
 1:      ldbs,ma     1(%sr1,%r25),%r1
 $lsfu_loop:
@@ -151,7 +155,7 @@
 	addib,<>,n  -1,%r24,$lsfu_loop
 2:      ldbs,ma     1(%sr1,%r25),%r1
 $lsfu_done:
-	sub         %r26,%r23,%r28
+	sub         %r23,%r24,%r28
 $lsfu_exit:
 	bv          %r0(%r2)
 	nop
@@ -161,8 +165,13 @@
 	ldi         -EFAULT,%r28
 
 	.section __ex_table,"a"
+#ifdef __LP64__
+	.dword      1b,(3b-1b)
+	.dword      2b,(3b-2b)
+#else
 	.word       1b,(3b-1b)
-	.word       2b,(2b-1b)
+	.word       2b,(3b-2b)
+#endif
 	.previous
 
 	.procend
@@ -194,7 +203,11 @@
 	ldo        1(%r25),%r25
 
 	.section __ex_table,"a"
+#ifdef __LP64__
+	.dword      1b,(2b-1b)
+#else
 	.word       1b,(2b-1b)
+#endif
 	.previous
 
 	.procend
@@ -233,8 +246,13 @@
 	copy        %r24,%r26    /* reset r26 so 0 is returned on fault */
 
 	.section __ex_table,"a"
+#ifdef __LP64__
+	.dword      1b,(3b-1b)
+	.dword      2b,(3b-2b)
+#else
 	.word       1b,(3b-1b)
-	.word       2b,(2b-1b)
+	.word       2b,(3b-2b)
+#endif
 	.previous
 
 	.procend
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/lib/memset.c linux/arch/parisc/lib/memset.c
--- linux.orig/arch/parisc/lib/memset.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/lib/memset.c	2002-08-12 22:14:27.000000000 +0000
@@ -0,0 +1,91 @@
+/* Copyright (C) 1991, 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+/* Slight modifications for pa-risc linux - Paul Bame <bame@debian.org> */
+
+#include <linux/types.h>
+#include <asm/string.h>
+
+#define OPSIZ (BITS_PER_LONG/8)
+typedef unsigned long op_t;
+
+void *
+memset (void *dstpp, int sc, size_t len)
+{
+  unsigned int c = sc;
+  long int dstp = (long int) dstpp;
+
+  if (len >= 8)
+    {
+      size_t xlen;
+      op_t cccc;
+
+      cccc = (unsigned char) c;
+      cccc |= cccc << 8;
+      cccc |= cccc << 16;
+      if (OPSIZ > 4)
+	/* Do the shift in two steps to avoid warning if long has 32 bits.  */
+	cccc |= (cccc << 16) << 16;
+
+      /* There are at least some bytes to set.
+	 No need to test for LEN == 0 in this alignment loop.  */
+      while (dstp % OPSIZ != 0)
+	{
+	  ((unsigned char *) dstp)[0] = c;
+	  dstp += 1;
+	  len -= 1;
+	}
+
+      /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
+      xlen = len / (OPSIZ * 8);
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  ((op_t *) dstp)[1] = cccc;
+	  ((op_t *) dstp)[2] = cccc;
+	  ((op_t *) dstp)[3] = cccc;
+	  ((op_t *) dstp)[4] = cccc;
+	  ((op_t *) dstp)[5] = cccc;
+	  ((op_t *) dstp)[6] = cccc;
+	  ((op_t *) dstp)[7] = cccc;
+	  dstp += 8 * OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ * 8;
+
+      /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
+      xlen = len / OPSIZ;
+      while (xlen > 0)
+	{
+	  ((op_t *) dstp)[0] = cccc;
+	  dstp += OPSIZ;
+	  xlen -= 1;
+	}
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  while (len > 0)
+    {
+      ((unsigned char *) dstp)[0] = c;
+      dstp += 1;
+      len -= 1;
+    }
+
+  return dstpp;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/Makefile linux/arch/parisc/math-emu/Makefile
--- linux.orig/arch/parisc/math-emu/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/Makefile	2002-08-12 22:14:21.000000000 +0000
@@ -0,0 +1,22 @@
+#
+# Makefile for the linux/parisc floating point code
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := math.o
+obj-y	 := frnd.o driver.o decode_exc.o fpudispatch.o denormal.o \
+		dfmpy.o sfmpy.o sfsqrt.o dfsqrt.o dfadd.o fmpyfadd.o \
+		sfadd.o dfsub.o sfsub.o fcnvfxt.o fcnvff.o fcnvxf.o \
+		fcnvfx.o fcnvuf.o fcnvfu.o fcnvfut.o dfdiv.o sfdiv.o \
+		dfrem.o sfrem.o dfcmp.o sfcmp.o
+
+# Math emulation code beyond the FRND is required for 712/80i and
+# other very old or stripped-down PA-RISC CPUs -- not currently supported
+
+obj-$CONFIG_MATH_EMULATION	+= unimplemented-math-emulation.o
+
+include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/README linux/arch/parisc/math-emu/README
--- linux.orig/arch/parisc/math-emu/README	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/README	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,11 @@
+All files except driver.c are snapshots from the HP-UX kernel.  They've
+been modified as little as possible.  Even though they don't fit the
+Linux coding style, please leave them in their funny format just in case
+someone in the future, with access to HP-UX source code, is generous
+enough to update our copies with later changes from HP-UX -- it'll
+make their 'diff' job easier if our code is relatively unmodified.
+
+Required Disclaimer: Hewlett-Packard makes no implied or expressed
+warranties about this code nor any promises to maintain or test it
+in any way.  This copy of this snapshot is no longer the property
+of Hewlett-Packard.
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/cnv_float.h linux/arch/parisc/math-emu/cnv_float.h
--- linux.orig/arch/parisc/math-emu/cnv_float.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/cnv_float.h	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,377 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+/*
+ * Some more constants
+ */
+#define SGL_FX_MAX_EXP 30
+#define DBL_FX_MAX_EXP 62
+#define QUAD_FX_MAX_EXP 126
+
+#define Dintp1(object) (object)
+#define Dintp2(object) (object)
+
+#define Duintp1(object) (object)
+#define Duintp2(object) (object)
+
+#define Qintp0(object) (object)
+#define Qintp1(object) (object)
+#define Qintp2(object) (object)
+#define Qintp3(object) (object)
+
+
+/*
+ * These macros will be used specifically by the convert instructions.
+ *
+ *
+ * Single format macros
+ */
+
+#define Sgl_to_dbl_exponent(src_exponent,dest)			\
+    Deposit_dexponent(dest,src_exponent+(DBL_BIAS-SGL_BIAS))
+
+#define Sgl_to_dbl_mantissa(src_mantissa,destA,destB)	\
+    Deposit_dmantissap1(destA,src_mantissa>>3);		\
+    Dmantissap2(destB) = src_mantissa << 29
+
+#define Sgl_isinexact_to_fix(sgl_value,exponent)	\
+    ((exponent < (SGL_P - 1)) ?				\
+     (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE)
+
+#define Int_isinexact_to_sgl(int_value)	(int_value << 33 - SGL_EXP_LENGTH)
+
+#define Sgl_roundnearest_from_int(int_value,sgl_value)			\
+    if (int_value & 1<<(SGL_EXP_LENGTH - 2))   /* round bit */		\
+    	if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value))	\
+		Sall(sgl_value)++
+
+#define Dint_isinexact_to_sgl(dint_valueA,dint_valueB)		\
+    ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB))
+
+#define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value)	\
+    if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) 			\
+    	if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) ||		\
+    	Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
+
+#define Dint_isinexact_to_dbl(dint_value) 	\
+    (Dintp2(dint_value) << 33 - DBL_EXP_LENGTH)
+
+#define Dbl_roundnearest_from_dint(dint_opndB,dbl_opndA,dbl_opndB) 	\
+    if (Dintp2(dint_opndB) & 1<<(DBL_EXP_LENGTH - 2))			\
+       if ((Dintp2(dint_opndB) << 34 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB))  \
+          if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
+
+#define Sgl_isone_roundbit(sgl_value,exponent)			\
+    ((Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) >> 31)
+
+#define Sgl_isone_stickybit(sgl_value,exponent)		\
+    (exponent < (SGL_P - 2) ?				\
+     Sall(sgl_value) << (SGL_EXP_LENGTH + 2 + exponent) : FALSE)
+
+
+/* 
+ * Double format macros
+ */
+
+#define Dbl_to_sgl_exponent(src_exponent,dest)			\
+    dest = src_exponent + (SGL_BIAS - DBL_BIAS)
+
+#define Dbl_to_sgl_mantissa(srcA,srcB,dest,inexact,guard,sticky,odd)	\
+    Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest); 	\
+    guard = Dbit3p2(srcB);					\
+    sticky = Dallp2(srcB)<<4;					\
+    inexact = guard | sticky;					\
+    odd = Dbit2p2(srcB)
+
+#define Dbl_to_sgl_denormalized(srcA,srcB,exp,dest,inexact,guard,sticky,odd,tiny) \
+    Deposit_dexponent(srcA,1);						\
+    tiny = TRUE;							\
+    if (exp >= -2) {							\
+	if (exp == 0) {							\
+	    inexact = Dallp2(srcB) << 3;				\
+	    guard = inexact >> 31;					\
+	    sticky = inexact << 1;					\
+	    Shiftdouble(Dmantissap1(srcA),Dmantissap2(srcB),29,dest);	\
+	    odd = dest << 31;						\
+	    if (inexact) {						\
+		switch(Rounding_mode()) {				\
+		    case ROUNDPLUS:					\
+			if (Dbl_iszero_sign(srcA)) {			\
+			    dest++;					\
+			    if (Sgl_isone_hidden(dest))	\
+				tiny = FALSE;				\
+			    dest--;					\
+			}						\
+			break;						\
+		    case ROUNDMINUS:					\
+			if (Dbl_isone_sign(srcA)) {			\
+			    dest++;					\
+			    if (Sgl_isone_hidden(dest))	\
+				tiny = FALSE;				\
+			    dest--;					\
+			}						\
+			break;						\
+		    case ROUNDNEAREST:					\
+			if (guard && (sticky || odd)) {			\
+			    dest++;					\
+			    if (Sgl_isone_hidden(dest))	\
+				tiny = FALSE;				\
+			    dest--;					\
+			}						\
+			break;						\
+		}							\
+	    }								\
+		/* shift right by one to get correct result */		\
+		guard = odd;						\
+		sticky = inexact;					\
+		inexact |= guard;					\
+		dest >>= 1;						\
+    		Deposit_dsign(srcA,0);					\
+    	        Shiftdouble(Dallp1(srcA),Dallp2(srcB),30,dest);		\
+	        odd = dest << 31;					\
+	}								\
+	else {								\
+    	    inexact = Dallp2(srcB) << (2 + exp);			\
+    	    guard = inexact >> 31;					\
+    	    sticky = inexact << 1; 					\
+    	    Deposit_dsign(srcA,0);					\
+    	    if (exp == -2) dest = Dallp1(srcA);				\
+    	    else Variable_shift_double(Dallp1(srcA),Dallp2(srcB),30-exp,dest); \
+    	    odd = dest << 31;						\
+	}								\
+    }									\
+    else {								\
+    	Deposit_dsign(srcA,0);						\
+    	if (exp > (1 - SGL_P)) {					\
+    	    dest = Dallp1(srcA) >> (- 2 - exp);				\
+    	    inexact = Dallp1(srcA) << (34 + exp);			\
+    	    guard = inexact >> 31;					\
+    	    sticky = (inexact << 1) | Dallp2(srcB);			\
+    	    inexact |= Dallp2(srcB); 					\
+    	    odd = dest << 31;						\
+    	}								\
+    	else {								\
+    	    dest = 0;							\
+    	    inexact = Dallp1(srcA) | Dallp2(srcB);			\
+    	    if (exp == (1 - SGL_P)) {					\
+    	    	guard = Dhidden(srcA);					\
+    	    	sticky = Dmantissap1(srcA) | Dallp2(srcB); 		\
+    	    }								\
+    	    else {							\
+    	    	guard = 0;						\
+    	    	sticky = inexact;					\
+    	    }								\
+    	    odd = 0;							\
+    	}								\
+    }									\
+    exp = 0
+
+#define Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent)		\
+    (exponent < (DBL_P-33) ? 						\
+     Dallp2(dbl_valueB) || Dallp1(dbl_valueA) << (DBL_EXP_LENGTH+1+exponent) : \
+     (exponent < (DBL_P-1) ? Dallp2(dbl_valueB) << (exponent + (33-DBL_P)) :   \
+      FALSE))
+
+#define Dbl_isoverflow_to_int(exponent,dbl_valueA,dbl_valueB)		\
+    ((exponent > SGL_FX_MAX_EXP + 1) || Dsign(dbl_valueA)==0 ||		\
+     Dmantissap1(dbl_valueA)!=0 || (Dallp2(dbl_valueB)>>21)!=0 ) 
+
+#define Dbl_isone_roundbit(dbl_valueA,dbl_valueB,exponent)              \
+    ((exponent < (DBL_P - 33) ?						\
+      Dallp1(dbl_valueA) >> ((30 - DBL_EXP_LENGTH) - exponent) :	\
+      Dallp2(dbl_valueB) >> ((DBL_P - 2) - exponent)) & 1)
+
+#define Dbl_isone_stickybit(dbl_valueA,dbl_valueB,exponent)		\
+    (exponent < (DBL_P-34) ? 						\
+     (Dallp2(dbl_valueB) || Dallp1(dbl_valueA)<<(DBL_EXP_LENGTH+2+exponent)) : \
+     (exponent<(DBL_P-2) ? (Dallp2(dbl_valueB) << (exponent + (34-DBL_P))) : \
+      FALSE))
+
+
+/* Int macros */
+
+#define Int_from_sgl_mantissa(sgl_value,exponent)	\
+    Sall(sgl_value) = 				\
+    	(unsigned)(Sall(sgl_value) << SGL_EXP_LENGTH)>>(31 - exponent)
+
+#define Int_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent)	\
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),22,Dallp1(dbl_valueA)); \
+    if (exponent < 31) Dallp1(dbl_valueA) >>= 30 - exponent;	\
+    else Dallp1(dbl_valueA) <<= 1
+
+#define Int_negate(int_value) int_value = -int_value
+
+
+/* Dint macros */
+
+#define Dint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB)	\
+    {Sall(sgl_value) <<= SGL_EXP_LENGTH;  /*  left-justify  */		\
+    if (exponent <= 31) {						\
+    	Dintp1(dresultA) = 0;						\
+    	Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+    }									\
+    else {								\
+    	Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent);		\
+    	Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31);		\
+    }}
+
+
+#define Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
+    {if (exponent < 32) {						\
+    	Dintp1(destA) = 0;						\
+    	if (exponent <= 20)						\
+    	    Dintp2(destB) = Dallp1(dbl_valueA) >> 20-exponent;		\
+    	else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
+	     52-exponent,Dintp2(destB));					\
+    }									\
+    else {								\
+    	if (exponent <= 52) {						\
+    	    Dintp1(destA) = Dallp1(dbl_valueA) >> 52-exponent;		\
+	    if (exponent == 52) Dintp2(destB) = Dallp2(dbl_valueB);	\
+	    else Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
+	    52-exponent,Dintp2(destB));					\
+        }								\
+    	else {								\
+    	    Variable_shift_double(Dallp1(dbl_valueA),Dallp2(dbl_valueB), \
+	    84-exponent,Dintp1(destA));					\
+    	    Dintp2(destB) = Dallp2(dbl_valueB) << exponent-52;		\
+    	}								\
+    }}
+
+#define Dint_setzero(dresultA,dresultB) 	\
+    Dintp1(dresultA) = 0; 	\
+    Dintp2(dresultB) = 0
+
+#define Dint_setone_sign(dresultA,dresultB)		\
+    Dintp1(dresultA) = ~Dintp1(dresultA);		\
+    if ((Dintp2(dresultB) = -Dintp2(dresultB)) == 0) Dintp1(dresultA)++
+
+#define Dint_set_minint(dresultA,dresultB)		\
+    Dintp1(dresultA) = (unsigned int)1<<31;		\
+    Dintp2(dresultB) = 0
+
+#define Dint_isone_lowp2(dresultB)  (Dintp2(dresultB) & 01)
+
+#define Dint_increment(dresultA,dresultB) 		\
+    if ((++Dintp2(dresultB))==0) Dintp1(dresultA)++
+
+#define Dint_decrement(dresultA,dresultB) 		\
+    if ((Dintp2(dresultB)--)==0) Dintp1(dresultA)--
+
+#define Dint_negate(dresultA,dresultB)			\
+    Dintp1(dresultA) = ~Dintp1(dresultA);		\
+    if ((Dintp2(dresultB) = -Dintp2(dresultB))==0) Dintp1(dresultA)++
+
+#define Dint_copyfromptr(src,destA,destB) \
+     Dintp1(destA) = src->wd0;		\
+     Dintp2(destB) = src->wd1
+#define Dint_copytoptr(srcA,srcB,dest)	\
+    dest->wd0 = Dintp1(srcA);		\
+    dest->wd1 = Dintp2(srcB)
+
+
+/* other macros  */
+
+#define Find_ms_one_bit(value, position)	\
+    {						\
+	int var;				\
+	for (var=8; var >=1; var >>= 1) {	\
+	    if (value >> 32 - position)		\
+		position -= var;		\
+		else position += var;		\
+	}					\
+	if ((value >> 32 - position) == 0)	\
+	    position--;				\
+	else position -= 2;			\
+    }
+
+
+/*
+ * Unsigned int macros
+ */
+#define Duint_copyfromptr(src,destA,destB) \
+    Dint_copyfromptr(src,destA,destB)
+#define Duint_copytoptr(srcA,srcB,dest)	\
+    Dint_copytoptr(srcA,srcB,dest)
+
+#define Suint_isinexact_to_sgl(int_value) \
+    (int_value << 32 - SGL_EXP_LENGTH)
+
+#define Sgl_roundnearest_from_suint(suint_value,sgl_value)		\
+    if (suint_value & 1<<(SGL_EXP_LENGTH - 1))   /* round bit */	\
+    	if ((suint_value << 33 - SGL_EXP_LENGTH) || Slow(sgl_value))	\
+		Sall(sgl_value)++
+
+#define Duint_isinexact_to_sgl(duint_valueA,duint_valueB)	\
+    ((Duintp1(duint_valueA) << 32 - SGL_EXP_LENGTH) || Duintp2(duint_valueB))
+
+#define Sgl_roundnearest_from_duint(duint_valueA,duint_valueB,sgl_value) \
+    if (Duintp1(duint_valueA) & 1<<(SGL_EXP_LENGTH - 1))		\
+    	if ((Duintp1(duint_valueA) << 33 - SGL_EXP_LENGTH) ||		\
+    	Duintp2(duint_valueB) || Slow(sgl_value)) Sall(sgl_value)++
+
+#define Duint_isinexact_to_dbl(duint_value) 	\
+    (Duintp2(duint_value) << 32 - DBL_EXP_LENGTH)
+
+#define Dbl_roundnearest_from_duint(duint_opndB,dbl_opndA,dbl_opndB) 	\
+    if (Duintp2(duint_opndB) & 1<<(DBL_EXP_LENGTH - 1))			\
+       if ((Duintp2(duint_opndB) << 33 - DBL_EXP_LENGTH) || Dlowp2(dbl_opndB)) \
+          if ((++Dallp2(dbl_opndB))==0) Dallp1(dbl_opndA)++
+
+#define Suint_from_sgl_mantissa(src,exponent,result)	\
+    Sall(result) = (unsigned)(Sall(src) << SGL_EXP_LENGTH)>>(31 - exponent)
+
+#define Sgl_isinexact_to_unsigned(sgl_value,exponent)	\
+    Sgl_isinexact_to_fix(sgl_value,exponent)
+
+#define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB)	\
+  {Sall(sgl_value) <<= SGL_EXP_LENGTH;  /*  left-justify  */		\
+    if (exponent <= 31) {						\
+    	Dintp1(dresultA) = 0;						\
+    	Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+    }									\
+    else {								\
+    	Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent);		\
+    	Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31);		\
+    }									\
+    Sall(sgl_value) >>= SGL_EXP_LENGTH;  /* return to original */	\
+  }
+
+#define Duint_setzero(dresultA,dresultB) 	\
+    Dint_setzero(dresultA,dresultB)
+
+#define Duint_increment(dresultA,dresultB) Dint_increment(dresultA,dresultB) 
+
+#define Duint_isone_lowp2(dresultB)  Dint_isone_lowp2(dresultB)
+
+#define Suint_from_dbl_mantissa(srcA,srcB,exponent,dest) \
+    Shiftdouble(Dallp1(srcA),Dallp2(srcB),21,dest); \
+    dest = (unsigned)dest >> 31 - exponent
+
+#define Dbl_isinexact_to_unsigned(dbl_valueA,dbl_valueB,exponent) \
+    Dbl_isinexact_to_fix(dbl_valueA,dbl_valueB,exponent)
+
+#define Duint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) \
+    Dint_from_dbl_mantissa(dbl_valueA,dbl_valueB,exponent,destA,destB) 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dbl_float.h linux/arch/parisc/math-emu/dbl_float.h
--- linux.orig/arch/parisc/math-emu/dbl_float.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dbl_float.h	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,847 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+/* 32-bit word grabing functions */
+#define Dbl_firstword(value) Dallp1(value)
+#define Dbl_secondword(value) Dallp2(value)
+#define Dbl_thirdword(value) dummy_location
+#define Dbl_fourthword(value) dummy_location
+
+#define Dbl_sign(object) Dsign(object)
+#define Dbl_exponent(object) Dexponent(object)
+#define Dbl_signexponent(object) Dsignexponent(object)
+#define Dbl_mantissap1(object) Dmantissap1(object)
+#define Dbl_mantissap2(object) Dmantissap2(object)
+#define Dbl_exponentmantissap1(object) Dexponentmantissap1(object)
+#define Dbl_allp1(object) Dallp1(object)
+#define Dbl_allp2(object) Dallp2(object)
+
+/* dbl_and_signs ands the sign bits of each argument and puts the result
+ * into the first argument. dbl_or_signs ors those same sign bits */
+#define Dbl_and_signs( src1dst, src2)		\
+    Dallp1(src1dst) = (Dallp1(src2)|~((unsigned int)1<<31)) & Dallp1(src1dst)
+#define Dbl_or_signs( src1dst, src2)		\
+    Dallp1(src1dst) = (Dallp1(src2)&((unsigned int)1<<31)) | Dallp1(src1dst)
+
+/* The hidden bit is always the low bit of the exponent */
+#define Dbl_clear_exponent_set_hidden(srcdst) Deposit_dexponent(srcdst,1)
+#define Dbl_clear_signexponent_set_hidden(srcdst) \
+    Deposit_dsignexponent(srcdst,1)
+#define Dbl_clear_sign(srcdst) Dallp1(srcdst) &= ~((unsigned int)1<<31)
+#define Dbl_clear_signexponent(srcdst) \
+    Dallp1(srcdst) &= Dmantissap1((unsigned int)-1)
+
+/* Exponent field for doubles has already been cleared and may be
+ * included in the shift.  Here we need to generate two double width
+ * variable shifts.  The insignificant bits can be ignored.
+ *      MTSAR f(varamount)
+ *      VSHD	srcdst.high,srcdst.low => srcdst.low
+ *	VSHD	0,srcdst.high => srcdst.high 
+ * This is very difficult to model with C expressions since the shift amount
+ * could exceed 32.  */
+/* varamount must be less than 64 */
+#define Dbl_rightshift(srcdstA, srcdstB, varamount)			\
+    {if((varamount) >= 32) {						\
+        Dallp2(srcdstB) = Dallp1(srcdstA) >> (varamount-32);		\
+        Dallp1(srcdstA)=0;						\
+    }									\
+    else if(varamount > 0) {						\
+	Variable_shift_double(Dallp1(srcdstA), Dallp2(srcdstB), 	\
+	  (varamount), Dallp2(srcdstB));				\
+	Dallp1(srcdstA) >>= varamount;					\
+    } }
+/* varamount must be less than 64 */
+#define Dbl_rightshift_exponentmantissa(srcdstA, srcdstB, varamount)	\
+    {if((varamount) >= 32) {						\
+        Dallp2(srcdstB) = Dexponentmantissap1(srcdstA) >> (varamount-32); \
+	Dallp1(srcdstA) &= ((unsigned int)1<<31);  /* clear expmant field */ \
+    }									\
+    else if(varamount > 0) {						\
+	Variable_shift_double(Dexponentmantissap1(srcdstA), Dallp2(srcdstB), \
+	(varamount), Dallp2(srcdstB));					\
+	Deposit_dexponentmantissap1(srcdstA,				\
+	    (Dexponentmantissap1(srcdstA)>>varamount));			\
+    } }
+/* varamount must be less than 64 */
+#define Dbl_leftshift(srcdstA, srcdstB, varamount)			\
+    {if((varamount) >= 32) {						\
+	Dallp1(srcdstA) = Dallp2(srcdstB) << (varamount-32);		\
+	Dallp2(srcdstB)=0;						\
+    }									\
+    else {								\
+	if ((varamount) > 0) {						\
+	    Dallp1(srcdstA) = (Dallp1(srcdstA) << (varamount)) |	\
+		(Dallp2(srcdstB) >> (32-(varamount)));			\
+	    Dallp2(srcdstB) <<= varamount;				\
+	}								\
+    } }
+#define Dbl_leftshiftby1_withextent(lefta,leftb,right,resulta,resultb)	\
+    Shiftdouble(Dallp1(lefta), Dallp2(leftb), 31, Dallp1(resulta));	\
+    Shiftdouble(Dallp2(leftb), Extall(right), 31, Dallp2(resultb)) 
+    
+#define Dbl_rightshiftby1_withextent(leftb,right,dst)		\
+    Extall(dst) = (Dallp2(leftb) << 31) | ((unsigned int)Extall(right) >> 1) | \
+		  Extlow(right)
+
+#define Dbl_arithrightshiftby1(srcdstA,srcdstB)			\
+    Shiftdouble(Dallp1(srcdstA),Dallp2(srcdstB),1,Dallp2(srcdstB));\
+    Dallp1(srcdstA) = (int)Dallp1(srcdstA) >> 1
+   
+/* Sign extend the sign bit with an integer destination */
+#define Dbl_signextendedsign(value)  Dsignedsign(value)
+
+#define Dbl_isone_hidden(dbl_value) (Is_dhidden(dbl_value)!=0)
+/* Singles and doubles may include the sign and exponent fields.  The
+ * hidden bit and the hidden overflow must be included. */
+#define Dbl_increment(dbl_valueA,dbl_valueB) \
+    if( (Dallp2(dbl_valueB) += 1) == 0 )  Dallp1(dbl_valueA) += 1
+#define Dbl_increment_mantissa(dbl_valueA,dbl_valueB) \
+    if( (Dmantissap2(dbl_valueB) += 1) == 0 )  \
+    Deposit_dmantissap1(dbl_valueA,dbl_valueA+1)
+#define Dbl_decrement(dbl_valueA,dbl_valueB) \
+    if( Dallp2(dbl_valueB) == 0 )  Dallp1(dbl_valueA) -= 1; \
+    Dallp2(dbl_valueB) -= 1
+
+#define Dbl_isone_sign(dbl_value) (Is_dsign(dbl_value)!=0)
+#define Dbl_isone_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)!=0)
+#define Dbl_isone_lowmantissap1(dbl_valueA) (Is_dlowp1(dbl_valueA)!=0)
+#define Dbl_isone_lowmantissap2(dbl_valueB) (Is_dlowp2(dbl_valueB)!=0)
+#define Dbl_isone_signaling(dbl_value) (Is_dsignaling(dbl_value)!=0)
+#define Dbl_is_signalingnan(dbl_value) (Dsignalingnan(dbl_value)==0xfff)
+#define Dbl_isnotzero(dbl_valueA,dbl_valueB) \
+    (Dallp1(dbl_valueA) || Dallp2(dbl_valueB))
+#define Dbl_isnotzero_hiddenhigh7mantissa(dbl_value) \
+    (Dhiddenhigh7mantissa(dbl_value)!=0)
+#define Dbl_isnotzero_exponent(dbl_value) (Dexponent(dbl_value)!=0)
+#define Dbl_isnotzero_mantissa(dbl_valueA,dbl_valueB) \
+    (Dmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
+#define Dbl_isnotzero_mantissap1(dbl_valueA) (Dmantissap1(dbl_valueA)!=0)
+#define Dbl_isnotzero_mantissap2(dbl_valueB) (Dmantissap2(dbl_valueB)!=0)
+#define Dbl_isnotzero_exponentmantissa(dbl_valueA,dbl_valueB) \
+    (Dexponentmantissap1(dbl_valueA) || Dmantissap2(dbl_valueB))
+#define Dbl_isnotzero_low4p2(dbl_value) (Dlow4p2(dbl_value)!=0)
+#define Dbl_iszero(dbl_valueA,dbl_valueB) (Dallp1(dbl_valueA)==0 && \
+    Dallp2(dbl_valueB)==0)
+#define Dbl_iszero_allp1(dbl_value) (Dallp1(dbl_value)==0)
+#define Dbl_iszero_allp2(dbl_value) (Dallp2(dbl_value)==0)
+#define Dbl_iszero_hidden(dbl_value) (Is_dhidden(dbl_value)==0)
+#define Dbl_iszero_hiddenoverflow(dbl_value) (Is_dhiddenoverflow(dbl_value)==0)
+#define Dbl_iszero_hiddenhigh3mantissa(dbl_value) \
+    (Dhiddenhigh3mantissa(dbl_value)==0)
+#define Dbl_iszero_hiddenhigh7mantissa(dbl_value) \
+    (Dhiddenhigh7mantissa(dbl_value)==0)
+#define Dbl_iszero_sign(dbl_value) (Is_dsign(dbl_value)==0)
+#define Dbl_iszero_exponent(dbl_value) (Dexponent(dbl_value)==0)
+#define Dbl_iszero_mantissa(dbl_valueA,dbl_valueB) \
+    (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
+#define Dbl_iszero_exponentmantissa(dbl_valueA,dbl_valueB) \
+    (Dexponentmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
+#define Dbl_isinfinity_exponent(dbl_value)		\
+    (Dexponent(dbl_value)==DBL_INFINITY_EXPONENT)
+#define Dbl_isnotinfinity_exponent(dbl_value)		\
+    (Dexponent(dbl_value)!=DBL_INFINITY_EXPONENT)
+#define Dbl_isinfinity(dbl_valueA,dbl_valueB)			\
+    (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT &&	\
+    Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0)
+#define Dbl_isnan(dbl_valueA,dbl_valueB)		\
+    (Dexponent(dbl_valueA)==DBL_INFINITY_EXPONENT &&	\
+    (Dmantissap1(dbl_valueA)!=0 || Dmantissap2(dbl_valueB)!=0))
+#define Dbl_isnotnan(dbl_valueA,dbl_valueB)		\
+    (Dexponent(dbl_valueA)!=DBL_INFINITY_EXPONENT ||	\
+    (Dmantissap1(dbl_valueA)==0 && Dmantissap2(dbl_valueB)==0))
+
+#define Dbl_islessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b)	\
+    (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) ||			\
+     (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) &&			\
+      Dallp2(dbl_op1b) < Dallp2(dbl_op2b)))
+#define Dbl_isgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b)	\
+    (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) ||			\
+     (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) &&			\
+      Dallp2(dbl_op1b) > Dallp2(dbl_op2b)))
+#define Dbl_isnotlessthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b)	\
+    (Dallp1(dbl_op1a) > Dallp1(dbl_op2a) ||			\
+     (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) &&			\
+      Dallp2(dbl_op1b) >= Dallp2(dbl_op2b)))
+#define Dbl_isnotgreaterthan(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b) \
+    (Dallp1(dbl_op1a) < Dallp1(dbl_op2a) ||			\
+     (Dallp1(dbl_op1a) == Dallp1(dbl_op2a) &&			\
+      Dallp2(dbl_op1b) <= Dallp2(dbl_op2b)))
+#define Dbl_isequal(dbl_op1a,dbl_op1b,dbl_op2a,dbl_op2b)	\
+     ((Dallp1(dbl_op1a) == Dallp1(dbl_op2a)) &&			\
+      (Dallp2(dbl_op1b) == Dallp2(dbl_op2b)))
+
+#define Dbl_leftshiftby8(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),24,Dallp1(dbl_valueA)); \
+    Dallp2(dbl_valueB) <<= 8
+#define Dbl_leftshiftby7(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),25,Dallp1(dbl_valueA)); \
+    Dallp2(dbl_valueB) <<= 7
+#define Dbl_leftshiftby4(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),28,Dallp1(dbl_valueA)); \
+    Dallp2(dbl_valueB) <<= 4
+#define Dbl_leftshiftby3(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),29,Dallp1(dbl_valueA)); \
+    Dallp2(dbl_valueB) <<= 3
+#define Dbl_leftshiftby2(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),30,Dallp1(dbl_valueA)); \
+    Dallp2(dbl_valueB) <<= 2
+#define Dbl_leftshiftby1(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),31,Dallp1(dbl_valueA)); \
+    Dallp2(dbl_valueB) <<= 1
+
+#define Dbl_rightshiftby8(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),8,Dallp2(dbl_valueB)); \
+    Dallp1(dbl_valueA) >>= 8
+#define Dbl_rightshiftby4(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),4,Dallp2(dbl_valueB)); \
+    Dallp1(dbl_valueA) >>= 4
+#define Dbl_rightshiftby2(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),2,Dallp2(dbl_valueB)); \
+    Dallp1(dbl_valueA) >>= 2
+#define Dbl_rightshiftby1(dbl_valueA,dbl_valueB) \
+    Shiftdouble(Dallp1(dbl_valueA),Dallp2(dbl_valueB),1,Dallp2(dbl_valueB)); \
+    Dallp1(dbl_valueA) >>= 1
+    
+/* This magnitude comparison uses the signless first words and
+ * the regular part2 words.  The comparison is graphically:
+ *
+ *       1st greater?  -------------
+ *                                 |
+ *       1st less?-----------------+---------
+ *                                 |        |
+ *       2nd greater or equal----->|        |
+ *                               False     True
+ */
+#define Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright)	\
+      ((signlessleft <= signlessright) &&				\
+       ( (signlessleft < signlessright) || (Dallp2(leftB)<Dallp2(rightB)) ))
+    
+#define Dbl_copytoint_exponentmantissap1(src,dest) \
+    dest = Dexponentmantissap1(src)
+
+/* A quiet NaN has the high mantissa bit clear and at least on other (in this
+ * case the adjacent bit) bit set. */
+#define Dbl_set_quiet(dbl_value) Deposit_dhigh2mantissa(dbl_value,1)
+#define Dbl_set_exponent(dbl_value, exp) Deposit_dexponent(dbl_value,exp)
+
+#define Dbl_set_mantissa(desta,destb,valuea,valueb)	\
+    Deposit_dmantissap1(desta,valuea);			\
+    Dmantissap2(destb) = Dmantissap2(valueb)
+#define Dbl_set_mantissap1(desta,valuea)		\
+    Deposit_dmantissap1(desta,valuea)
+#define Dbl_set_mantissap2(destb,valueb)		\
+    Dmantissap2(destb) = Dmantissap2(valueb)
+
+#define Dbl_set_exponentmantissa(desta,destb,valuea,valueb)	\
+    Deposit_dexponentmantissap1(desta,valuea);			\
+    Dmantissap2(destb) = Dmantissap2(valueb)
+#define Dbl_set_exponentmantissap1(dest,value)			\
+    Deposit_dexponentmantissap1(dest,value)
+
+#define Dbl_copyfromptr(src,desta,destb) \
+    Dallp1(desta) = src->wd0;		\
+    Dallp2(destb) = src->wd1 
+#define Dbl_copytoptr(srca,srcb,dest)	\
+    dest->wd0 = Dallp1(srca);		\
+    dest->wd1 = Dallp2(srcb)
+
+/*  An infinity is represented with the max exponent and a zero mantissa */
+#define Dbl_setinfinity_exponent(dbl_value) \
+    Deposit_dexponent(dbl_value,DBL_INFINITY_EXPONENT)
+#define Dbl_setinfinity_exponentmantissa(dbl_valueA,dbl_valueB)	\
+    Deposit_dexponentmantissap1(dbl_valueA, 			\
+    (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH))));	\
+    Dmantissap2(dbl_valueB) = 0
+#define Dbl_setinfinitypositive(dbl_valueA,dbl_valueB)		\
+    Dallp1(dbl_valueA) 						\
+        = (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)));	\
+    Dmantissap2(dbl_valueB) = 0
+#define Dbl_setinfinitynegative(dbl_valueA,dbl_valueB)		\
+    Dallp1(dbl_valueA) = ((unsigned int)1<<31) |		\
+         (DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)));	\
+    Dmantissap2(dbl_valueB) = 0
+#define Dbl_setinfinity(dbl_valueA,dbl_valueB,sign)		\
+    Dallp1(dbl_valueA) = ((unsigned int)sign << 31) | 		\
+	(DBL_INFINITY_EXPONENT << (32-(1+DBL_EXP_LENGTH)));	\
+    Dmantissap2(dbl_valueB) = 0
+
+#define Dbl_sethigh4bits(dbl_value, extsign) Deposit_dhigh4p1(dbl_value,extsign)
+#define Dbl_set_sign(dbl_value,sign) Deposit_dsign(dbl_value,sign)
+#define Dbl_invert_sign(dbl_value) Deposit_dsign(dbl_value,~Dsign(dbl_value))
+#define Dbl_setone_sign(dbl_value) Deposit_dsign(dbl_value,1)
+#define Dbl_setone_lowmantissap2(dbl_value) Deposit_dlowp2(dbl_value,1)
+#define Dbl_setzero_sign(dbl_value) Dallp1(dbl_value) &= 0x7fffffff
+#define Dbl_setzero_exponent(dbl_value) 		\
+    Dallp1(dbl_value) &= 0x800fffff
+#define Dbl_setzero_mantissa(dbl_valueA,dbl_valueB)	\
+    Dallp1(dbl_valueA) &= 0xfff00000; 			\
+    Dallp2(dbl_valueB) = 0
+#define Dbl_setzero_mantissap1(dbl_value) Dallp1(dbl_value) &= 0xfff00000
+#define Dbl_setzero_mantissap2(dbl_value) Dallp2(dbl_value) = 0
+#define Dbl_setzero_exponentmantissa(dbl_valueA,dbl_valueB)	\
+    Dallp1(dbl_valueA) &= 0x80000000;		\
+    Dallp2(dbl_valueB) = 0
+#define Dbl_setzero_exponentmantissap1(dbl_valueA)	\
+    Dallp1(dbl_valueA) &= 0x80000000
+#define Dbl_setzero(dbl_valueA,dbl_valueB) \
+    Dallp1(dbl_valueA) = 0; Dallp2(dbl_valueB) = 0
+#define Dbl_setzerop1(dbl_value) Dallp1(dbl_value) = 0
+#define Dbl_setzerop2(dbl_value) Dallp2(dbl_value) = 0
+#define Dbl_setnegativezero(dbl_value) \
+    Dallp1(dbl_value) = (unsigned int)1 << 31; Dallp2(dbl_value) = 0
+#define Dbl_setnegativezerop1(dbl_value) Dallp1(dbl_value) = (unsigned int)1<<31
+
+/* Use the following macro for both overflow & underflow conditions */
+#define ovfl -
+#define unfl +
+#define Dbl_setwrapped_exponent(dbl_value,exponent,op) \
+    Deposit_dexponent(dbl_value,(exponent op DBL_WRAP))
+
+#define Dbl_setlargestpositive(dbl_valueA,dbl_valueB) 			\
+    Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
+			| ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 );		\
+    Dallp2(dbl_valueB) = 0xFFFFFFFF
+#define Dbl_setlargestnegative(dbl_valueA,dbl_valueB) 			\
+    Dallp1(dbl_valueA) = ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) \
+			| ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 )		\
+			| ((unsigned int)1<<31);			\
+    Dallp2(dbl_valueB) = 0xFFFFFFFF
+#define Dbl_setlargest_exponentmantissa(dbl_valueA,dbl_valueB)		\
+    Deposit_dexponentmantissap1(dbl_valueA,				\
+	(((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH)))		\
+			| ((1<<(32-(1+DBL_EXP_LENGTH))) - 1 )));	\
+    Dallp2(dbl_valueB) = 0xFFFFFFFF
+
+#define Dbl_setnegativeinfinity(dbl_valueA,dbl_valueB) 			\
+    Dallp1(dbl_valueA) = ((1<<DBL_EXP_LENGTH) | DBL_INFINITY_EXPONENT) 	\
+			 << (32-(1+DBL_EXP_LENGTH)) ; 			\
+    Dallp2(dbl_valueB) = 0
+#define Dbl_setlargest(dbl_valueA,dbl_valueB,sign)			\
+    Dallp1(dbl_valueA) = ((unsigned int)sign << 31) |			\
+         ((DBL_EMAX+DBL_BIAS) << (32-(1+DBL_EXP_LENGTH))) |	 	\
+	 ((1 << (32-(1+DBL_EXP_LENGTH))) - 1 );				\
+    Dallp2(dbl_valueB) = 0xFFFFFFFF
+    
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Dbl_right_align(srcdstA,srcdstB,shift,extent)			\
+    if( shift >= 32 ) 							\
+	{								\
+	/* Big shift requires examining the portion shift off 		\
+	the end to properly set inexact.  */				\
+	if(shift < 64)							\
+	    {								\
+	    if(shift > 32)						\
+		{							\
+	        Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),	\
+		 shift-32, Extall(extent));				\
+	        if(Dallp2(srcdstB) << 64 - (shift)) Ext_setone_low(extent); \
+	        }							\
+	    else Extall(extent) = Dallp2(srcdstB);			\
+	    Dallp2(srcdstB) = Dallp1(srcdstA) >> (shift - 32);		\
+	    }								\
+	else								\
+	    {								\
+	    Extall(extent) = Dallp1(srcdstA);				\
+	    if(Dallp2(srcdstB)) Ext_setone_low(extent);			\
+	    Dallp2(srcdstB) = 0;					\
+	    }								\
+	Dallp1(srcdstA) = 0;						\
+	}								\
+    else								\
+	{								\
+	/* Small alignment is simpler.  Extension is easily set. */	\
+	if (shift > 0)							\
+	    {								\
+	    Extall(extent) = Dallp2(srcdstB) << 32 - (shift);		\
+	    Variable_shift_double(Dallp1(srcdstA),Dallp2(srcdstB),shift, \
+	     Dallp2(srcdstB));						\
+	    Dallp1(srcdstA) >>= shift;					\
+	    }								\
+	else Extall(extent) = 0;					\
+	}
+
+/* 
+ * Here we need to shift the result right to correct for an overshift
+ * (due to the exponent becoming negative) during normalization.
+ */
+#define Dbl_fix_overshift(srcdstA,srcdstB,shift,extent)			\
+	    Extall(extent) = Dallp2(srcdstB) << 32 - (shift);		\
+	    Dallp2(srcdstB) = (Dallp1(srcdstA) << 32 - (shift)) |	\
+		(Dallp2(srcdstB) >> (shift));				\
+	    Dallp1(srcdstA) = Dallp1(srcdstA) >> shift
+
+#define Dbl_hiddenhigh3mantissa(dbl_value) Dhiddenhigh3mantissa(dbl_value)
+#define Dbl_hidden(dbl_value) Dhidden(dbl_value)
+#define Dbl_lowmantissap2(dbl_value) Dlowp2(dbl_value)
+
+/* The left argument is never smaller than the right argument */
+#define Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb)			\
+    if( Dallp2(rightb) > Dallp2(leftb) ) Dallp1(lefta)--;	\
+    Dallp2(resultb) = Dallp2(leftb) - Dallp2(rightb);		\
+    Dallp1(resulta) = Dallp1(lefta) - Dallp1(righta)
+
+/* Subtract right augmented with extension from left augmented with zeros and
+ * store into result and extension. */
+#define Dbl_subtract_withextension(lefta,leftb,righta,rightb,extent,resulta,resultb)	\
+    Dbl_subtract(lefta,leftb,righta,rightb,resulta,resultb);		\
+    if( (Extall(extent) = 0-Extall(extent)) )				\
+        {								\
+        if((Dallp2(resultb)--) == 0) Dallp1(resulta)--;			\
+        }
+
+#define Dbl_addition(lefta,leftb,righta,rightb,resulta,resultb)		\
+    /* If the sum of the low words is less than either source, then	\
+     * an overflow into the next word occurred. */			\
+    Dallp1(resulta) = Dallp1(lefta) + Dallp1(righta);			\
+    if((Dallp2(resultb) = Dallp2(leftb) + Dallp2(rightb)) < Dallp2(rightb)) \
+	Dallp1(resulta)++
+
+#define Dbl_xortointp1(left,right,result)			\
+    result = Dallp1(left) XOR Dallp1(right)
+
+#define Dbl_xorfromintp1(left,right,result)			\
+    Dallp1(result) = left XOR Dallp1(right)
+
+#define Dbl_swap_lower(left,right)				\
+    Dallp2(left)  = Dallp2(left) XOR Dallp2(right);		\
+    Dallp2(right) = Dallp2(left) XOR Dallp2(right);		\
+    Dallp2(left)  = Dallp2(left) XOR Dallp2(right)
+
+/* Need to Initialize */
+#define Dbl_makequietnan(desta,destb)					\
+    Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH))	\
+                 | (1<<(32-(1+DBL_EXP_LENGTH+2)));			\
+    Dallp2(destb) = 0
+#define Dbl_makesignalingnan(desta,destb)				\
+    Dallp1(desta) = ((DBL_EMAX+DBL_BIAS)+1)<< (32-(1+DBL_EXP_LENGTH))	\
+                 | (1<<(32-(1+DBL_EXP_LENGTH+1)));			\
+    Dallp2(destb) = 0
+
+#define Dbl_normalize(dbl_opndA,dbl_opndB,exponent)			\
+	while(Dbl_iszero_hiddenhigh7mantissa(dbl_opndA)) {		\
+		Dbl_leftshiftby8(dbl_opndA,dbl_opndB);			\
+		exponent -= 8;						\
+	}								\
+	if(Dbl_iszero_hiddenhigh3mantissa(dbl_opndA)) {			\
+		Dbl_leftshiftby4(dbl_opndA,dbl_opndB);			\
+		exponent -= 4;						\
+	}								\
+	while(Dbl_iszero_hidden(dbl_opndA)) {				\
+		Dbl_leftshiftby1(dbl_opndA,dbl_opndB);			\
+		exponent -= 1;						\
+	}
+
+#define Twoword_add(src1dstA,src1dstB,src2A,src2B)		\
+	/* 							\
+	 * want this macro to generate:				\
+	 *	ADD	src1dstB,src2B,src1dstB;		\
+	 *	ADDC	src1dstA,src2A,src1dstA;		\
+	 */							\
+	if ((src1dstB) + (src2B) < (src1dstB)) Dallp1(src1dstA)++; \
+	Dallp1(src1dstA) += (src2A);				\
+	Dallp2(src1dstB) += (src2B)
+
+#define Twoword_subtract(src1dstA,src1dstB,src2A,src2B)		\
+	/* 							\
+	 * want this macro to generate:				\
+	 *	SUB	src1dstB,src2B,src1dstB;		\
+	 *	SUBB	src1dstA,src2A,src1dstA;		\
+	 */							\
+	if ((src1dstB) < (src2B)) Dallp1(src1dstA)--;		\
+	Dallp1(src1dstA) -= (src2A);				\
+	Dallp2(src1dstB) -= (src2B)
+
+#define Dbl_setoverflow(resultA,resultB)				\
+	/* set result to infinity or largest number */			\
+	switch (Rounding_mode()) {					\
+		case ROUNDPLUS:						\
+			if (Dbl_isone_sign(resultA)) {			\
+				Dbl_setlargestnegative(resultA,resultB); \
+			}						\
+			else {						\
+				Dbl_setinfinitypositive(resultA,resultB); \
+			}						\
+			break;						\
+		case ROUNDMINUS:					\
+			if (Dbl_iszero_sign(resultA)) {			\
+				Dbl_setlargestpositive(resultA,resultB); \
+			}						\
+			else {						\
+				Dbl_setinfinitynegative(resultA,resultB); \
+			}						\
+			break;						\
+		case ROUNDNEAREST:					\
+			Dbl_setinfinity_exponentmantissa(resultA,resultB); \
+			break;						\
+		case ROUNDZERO:						\
+			Dbl_setlargest_exponentmantissa(resultA,resultB); \
+	}
+
+#define Dbl_denormalize(opndp1,opndp2,exponent,guard,sticky,inexact)	\
+    Dbl_clear_signexponent_set_hidden(opndp1);				\
+    if (exponent >= (1-DBL_P)) {					\
+	if (exponent >= -31) {						\
+	    guard = (Dallp2(opndp2) >> -exponent) & 1;			\
+	    if (exponent < 0) sticky |= Dallp2(opndp2) << (32+exponent); \
+	    if (exponent > -31) {					\
+		Variable_shift_double(opndp1,opndp2,1-exponent,opndp2);	\
+		Dallp1(opndp1) >>= 1-exponent;				\
+	    }								\
+	    else {							\
+		Dallp2(opndp2) = Dallp1(opndp1);			\
+		Dbl_setzerop1(opndp1);					\
+	    }								\
+	}								\
+	else {								\
+	    guard = (Dallp1(opndp1) >> -32-exponent) & 1;		\
+	    if (exponent == -32) sticky |= Dallp2(opndp2);		\
+	    else sticky |= (Dallp2(opndp2) | Dallp1(opndp1) << 64+exponent); \
+	    Dallp2(opndp2) = Dallp1(opndp1) >> -31-exponent;		\
+	    Dbl_setzerop1(opndp1);					\
+	}								\
+	inexact = guard | sticky;					\
+    }									\
+    else {								\
+	guard = 0;							\
+	sticky |= (Dallp1(opndp1) | Dallp2(opndp2));			\
+	Dbl_setzero(opndp1,opndp2);					\
+	inexact = sticky;						\
+    }
+
+/* 
+ * The fused multiply add instructions requires a double extended format,
+ * with 106 bits of mantissa.
+ */
+#define DBLEXT_THRESHOLD 106
+
+#define Dblext_setzero(valA,valB,valC,valD)	\
+    Dextallp1(valA) = 0; Dextallp2(valB) = 0;	\
+    Dextallp3(valC) = 0; Dextallp4(valD) = 0
+
+
+#define Dblext_isnotzero_mantissap3(valC) (Dextallp3(valC)!=0)
+#define Dblext_isnotzero_mantissap4(valD) (Dextallp3(valD)!=0)
+#define Dblext_isone_lowp2(val) (Dextlowp2(val)!=0)
+#define Dblext_isone_highp3(val) (Dexthighp3(val)!=0)
+#define Dblext_isnotzero_low31p3(val) (Dextlow31p3(val)!=0)
+#define Dblext_iszero(valA,valB,valC,valD) (Dextallp1(valA)==0 && \
+    Dextallp2(valB)==0 && Dextallp3(valC)==0 && Dextallp4(valD)==0)
+
+#define Dblext_copy(srca,srcb,srcc,srcd,desta,destb,destc,destd) \
+    Dextallp1(desta) = Dextallp4(srca);	\
+    Dextallp2(destb) = Dextallp4(srcb);	\
+    Dextallp3(destc) = Dextallp4(srcc);	\
+    Dextallp4(destd) = Dextallp4(srcd)
+
+#define Dblext_swap_lower(leftp2,leftp3,leftp4,rightp2,rightp3,rightp4)  \
+    Dextallp2(leftp2)  = Dextallp2(leftp2) XOR Dextallp2(rightp2);  \
+    Dextallp2(rightp2) = Dextallp2(leftp2) XOR Dextallp2(rightp2);  \
+    Dextallp2(leftp2)  = Dextallp2(leftp2) XOR Dextallp2(rightp2);  \
+    Dextallp3(leftp3)  = Dextallp3(leftp3) XOR Dextallp3(rightp3);  \
+    Dextallp3(rightp3) = Dextallp3(leftp3) XOR Dextallp3(rightp3);  \
+    Dextallp3(leftp3)  = Dextallp3(leftp3) XOR Dextallp3(rightp3);  \
+    Dextallp4(leftp4)  = Dextallp4(leftp4) XOR Dextallp4(rightp4);  \
+    Dextallp4(rightp4) = Dextallp4(leftp4) XOR Dextallp4(rightp4);  \
+    Dextallp4(leftp4)  = Dextallp4(leftp4) XOR Dextallp4(rightp4)
+
+#define Dblext_setone_lowmantissap4(dbl_value) Deposit_dextlowp4(dbl_value,1)
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Dblext_right_align(srcdstA,srcdstB,srcdstC,srcdstD,shift) \
+  {int shiftamt, sticky;						\
+    shiftamt = shift % 32;						\
+    sticky = 0;								\
+    switch (shift/32) {							\
+     case 0: if (shiftamt > 0) {					\
+	        sticky = Dextallp4(srcdstD) << 32 - (shiftamt); 	\
+                Variable_shift_double(Dextallp3(srcdstC),		\
+		 Dextallp4(srcdstD),shiftamt,Dextallp4(srcdstD));	\
+                Variable_shift_double(Dextallp2(srcdstB),		\
+		 Dextallp3(srcdstC),shiftamt,Dextallp3(srcdstC));	\
+                Variable_shift_double(Dextallp1(srcdstA),		\
+		 Dextallp2(srcdstB),shiftamt,Dextallp2(srcdstB));	\
+	        Dextallp1(srcdstA) >>= shiftamt;			\
+	     }								\
+	     break;							\
+     case 1: if (shiftamt > 0) {					\
+                sticky = (Dextallp3(srcdstC) << 31 - shiftamt) |	\
+			 Dextallp4(srcdstD);				\
+                Variable_shift_double(Dextallp2(srcdstB),		\
+		 Dextallp3(srcdstC),shiftamt,Dextallp4(srcdstD));	\
+                Variable_shift_double(Dextallp1(srcdstA),		\
+		 Dextallp2(srcdstB),shiftamt,Dextallp3(srcdstC));	\
+	     }								\
+	     else {							\
+		sticky = Dextallp4(srcdstD);				\
+		Dextallp4(srcdstD) = Dextallp3(srcdstC);		\
+		Dextallp3(srcdstC) = Dextallp2(srcdstB);		\
+	     }								\
+	     Dextallp2(srcdstB) = Dextallp1(srcdstA) >> shiftamt;	\
+	     Dextallp1(srcdstA) = 0;					\
+	     break;							\
+     case 2: if (shiftamt > 0) {					\
+                sticky = (Dextallp2(srcdstB) << 31 - shiftamt) |	\
+			 Dextallp3(srcdstC) | Dextallp4(srcdstD);	\
+                Variable_shift_double(Dextallp1(srcdstA),		\
+		 Dextallp2(srcdstB),shiftamt,Dextallp4(srcdstD));	\
+	     }								\
+	     else {							\
+		sticky = Dextallp3(srcdstC) | Dextallp4(srcdstD);	\
+		Dextallp4(srcdstD) = Dextallp2(srcdstB);		\
+	     }								\
+	     Dextallp3(srcdstC) = Dextallp1(srcdstA) >> shiftamt;	\
+	     Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0;		\
+	     break;							\
+     case 3: if (shiftamt > 0) {					\
+                sticky = (Dextallp1(srcdstA) << 31 - shiftamt) |	\
+			 Dextallp2(srcdstB) | Dextallp3(srcdstC) |	\
+			 Dextallp4(srcdstD);				\
+	     }								\
+	     else {							\
+		sticky = Dextallp2(srcdstB) | Dextallp3(srcdstC) |	\
+		    Dextallp4(srcdstD);					\
+	     }								\
+	     Dextallp4(srcdstD) = Dextallp1(srcdstA) >> shiftamt;	\
+	     Dextallp1(srcdstA) = Dextallp2(srcdstB) = 0;		\
+	     Dextallp3(srcdstC) = 0;					\
+	     break;							\
+    }									\
+    if (sticky) Dblext_setone_lowmantissap4(srcdstD);			\
+  }
+
+/* The left argument is never smaller than the right argument */
+#define Dblext_subtract(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
+    if( Dextallp4(rightd) > Dextallp4(leftd) ) 			\
+	if( (Dextallp3(leftc)--) == 0)				\
+	    if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--;	\
+    Dextallp4(resultd) = Dextallp4(leftd) - Dextallp4(rightd);	\
+    if( Dextallp3(rightc) > Dextallp3(leftc) ) 			\
+        if( (Dextallp2(leftb)--) == 0) Dextallp1(lefta)--;	\
+    Dextallp3(resultc) = Dextallp3(leftc) - Dextallp3(rightc);	\
+    if( Dextallp2(rightb) > Dextallp2(leftb) ) Dextallp1(lefta)--; \
+    Dextallp2(resultb) = Dextallp2(leftb) - Dextallp2(rightb);	\
+    Dextallp1(resulta) = Dextallp1(lefta) - Dextallp1(righta)
+
+#define Dblext_addition(lefta,leftb,leftc,leftd,righta,rightb,rightc,rightd,resulta,resultb,resultc,resultd) \
+    /* If the sum of the low words is less than either source, then \
+     * an overflow into the next word occurred. */ \
+    if ((Dextallp4(resultd) = Dextallp4(leftd)+Dextallp4(rightd)) < \
+	Dextallp4(rightd)) \
+	if((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)+1) <= \
+	    Dextallp3(rightc)) \
+	    if((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
+	        <= Dextallp2(rightb))  \
+		    Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+	    else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
+	else \
+	    if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
+	        Dextallp2(rightb)) \
+		    Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+	    else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
+    else \
+	if ((Dextallp3(resultc) = Dextallp3(leftc)+Dextallp3(rightc)) < \
+	    Dextallp3(rightc))  \
+	    if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)+1) \
+	        <= Dextallp2(rightb)) \
+		    Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+	    else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta); \
+	else \
+	    if ((Dextallp2(resultb) = Dextallp2(leftb)+Dextallp2(rightb)) < \
+	        Dextallp2(rightb)) \
+		    Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)+1; \
+	    else Dextallp1(resulta) = Dextallp1(lefta)+Dextallp1(righta)
+
+
+#define Dblext_arithrightshiftby1(srcdstA,srcdstB,srcdstC,srcdstD)	\
+    Shiftdouble(Dextallp3(srcdstC),Dextallp4(srcdstD),1,Dextallp4(srcdstD)); \
+    Shiftdouble(Dextallp2(srcdstB),Dextallp3(srcdstC),1,Dextallp3(srcdstC)); \
+    Shiftdouble(Dextallp1(srcdstA),Dextallp2(srcdstB),1,Dextallp2(srcdstB)); \
+    Dextallp1(srcdstA) = (int)Dextallp1(srcdstA) >> 1
+   
+#define Dblext_leftshiftby8(valA,valB,valC,valD) \
+    Shiftdouble(Dextallp1(valA),Dextallp2(valB),24,Dextallp1(valA)); \
+    Shiftdouble(Dextallp2(valB),Dextallp3(valC),24,Dextallp2(valB)); \
+    Shiftdouble(Dextallp3(valC),Dextallp4(valD),24,Dextallp3(valC)); \
+    Dextallp4(valD) <<= 8
+#define Dblext_leftshiftby4(valA,valB,valC,valD) \
+    Shiftdouble(Dextallp1(valA),Dextallp2(valB),28,Dextallp1(valA)); \
+    Shiftdouble(Dextallp2(valB),Dextallp3(valC),28,Dextallp2(valB)); \
+    Shiftdouble(Dextallp3(valC),Dextallp4(valD),28,Dextallp3(valC)); \
+    Dextallp4(valD) <<= 4
+#define Dblext_leftshiftby3(valA,valB,valC,valD) \
+    Shiftdouble(Dextallp1(valA),Dextallp2(valB),29,Dextallp1(valA)); \
+    Shiftdouble(Dextallp2(valB),Dextallp3(valC),29,Dextallp2(valB)); \
+    Shiftdouble(Dextallp3(valC),Dextallp4(valD),29,Dextallp3(valC)); \
+    Dextallp4(valD) <<= 3
+#define Dblext_leftshiftby2(valA,valB,valC,valD) \
+    Shiftdouble(Dextallp1(valA),Dextallp2(valB),30,Dextallp1(valA)); \
+    Shiftdouble(Dextallp2(valB),Dextallp3(valC),30,Dextallp2(valB)); \
+    Shiftdouble(Dextallp3(valC),Dextallp4(valD),30,Dextallp3(valC)); \
+    Dextallp4(valD) <<= 2
+#define Dblext_leftshiftby1(valA,valB,valC,valD) \
+    Shiftdouble(Dextallp1(valA),Dextallp2(valB),31,Dextallp1(valA)); \
+    Shiftdouble(Dextallp2(valB),Dextallp3(valC),31,Dextallp2(valB)); \
+    Shiftdouble(Dextallp3(valC),Dextallp4(valD),31,Dextallp3(valC)); \
+    Dextallp4(valD) <<= 1
+
+#define Dblext_rightshiftby4(valueA,valueB,valueC,valueD) \
+    Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),4,Dextallp4(valueD)); \
+    Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),4,Dextallp3(valueC)); \
+    Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),4,Dextallp2(valueB)); \
+    Dextallp1(valueA) >>= 4
+#define Dblext_rightshiftby1(valueA,valueB,valueC,valueD) \
+    Shiftdouble(Dextallp3(valueC),Dextallp4(valueD),1,Dextallp4(valueD)); \
+    Shiftdouble(Dextallp2(valueB),Dextallp3(valueC),1,Dextallp3(valueC)); \
+    Shiftdouble(Dextallp1(valueA),Dextallp2(valueB),1,Dextallp2(valueB)); \
+    Dextallp1(valueA) >>= 1
+
+#define Dblext_xortointp1(left,right,result) Dbl_xortointp1(left,right,result)
+
+#define Dblext_xorfromintp1(left,right,result) \
+	Dbl_xorfromintp1(left,right,result)
+
+#define Dblext_copytoint_exponentmantissap1(src,dest) \
+	Dbl_copytoint_exponentmantissap1(src,dest)
+
+#define Dblext_ismagnitudeless(leftB,rightB,signlessleft,signlessright) \
+	Dbl_ismagnitudeless(leftB,rightB,signlessleft,signlessright)
+
+#define Dbl_copyto_dblext(src1,src2,dest1,dest2,dest3,dest4) \
+	Dextallp1(dest1) = Dallp1(src1); Dextallp2(dest2) = Dallp2(src2); \
+	Dextallp3(dest3) = 0; Dextallp4(dest4) = 0
+
+#define Dblext_set_sign(dbl_value,sign)  Dbl_set_sign(dbl_value,sign)  
+#define Dblext_clear_signexponent_set_hidden(srcdst) \
+	Dbl_clear_signexponent_set_hidden(srcdst) 
+#define Dblext_clear_signexponent(srcdst) Dbl_clear_signexponent(srcdst) 
+#define Dblext_clear_sign(srcdst) Dbl_clear_sign(srcdst) 
+#define Dblext_isone_hidden(dbl_value) Dbl_isone_hidden(dbl_value) 
+
+/*
+ * The Fourword_add() macro assumes that integers are 4 bytes in size.
+ * It will break if this is not the case.
+ */
+
+#define Fourword_add(src1dstA,src1dstB,src1dstC,src1dstD,src2A,src2B,src2C,src2D) \
+	/* 								\
+	 * want this macro to generate:					\
+	 *	ADD	src1dstD,src2D,src1dstD;			\
+	 *	ADDC	src1dstC,src2C,src1dstC;			\
+	 *	ADDC	src1dstB,src2B,src1dstB;			\
+	 *	ADDC	src1dstA,src2A,src1dstA;			\
+	 */								\
+	if ((unsigned int)(src1dstD += (src2D)) < (unsigned int)(src2D)) { \
+	   if ((unsigned int)(src1dstC += (src2C) + 1) <=		\
+	       (unsigned int)(src2C)) {					\
+	     if ((unsigned int)(src1dstB += (src2B) + 1) <=		\
+		 (unsigned int)(src2B)) src1dstA++;			\
+	   }								\
+	   else if ((unsigned int)(src1dstB += (src2B)) < 		\
+		    (unsigned int)(src2B)) src1dstA++;			\
+	}								\
+	else {								\
+	   if ((unsigned int)(src1dstC += (src2C)) <			\
+	       (unsigned int)(src2C)) {					\
+	      if ((unsigned int)(src1dstB += (src2B) + 1) <=		\
+		  (unsigned int)(src2B)) src1dstA++;			\
+	   }								\
+	   else if ((unsigned int)(src1dstB += (src2B)) <		\
+		    (unsigned int)(src2B)) src1dstA++;			\
+	}								\
+	src1dstA += (src2A)
+
+#define Dblext_denormalize(opndp1,opndp2,opndp3,opndp4,exponent,is_tiny) \
+  {int shiftamt, sticky;						\
+    is_tiny = TRUE;							\
+    if (exponent == 0 && (Dextallp3(opndp3) || Dextallp4(opndp4))) {	\
+	switch (Rounding_mode()) {					\
+	case ROUNDPLUS:							\
+		if (Dbl_iszero_sign(opndp1)) {				\
+			Dbl_increment(opndp1,opndp2);			\
+			if (Dbl_isone_hiddenoverflow(opndp1))		\
+				is_tiny = FALSE;			\
+			Dbl_decrement(opndp1,opndp2);			\
+		}							\
+		break;							\
+	case ROUNDMINUS:						\
+		if (Dbl_isone_sign(opndp1)) {				\
+			Dbl_increment(opndp1,opndp2);			\
+			if (Dbl_isone_hiddenoverflow(opndp1))		\
+				is_tiny = FALSE;			\
+			Dbl_decrement(opndp1,opndp2);			\
+		}							\
+		break;							\
+	case ROUNDNEAREST:						\
+		if (Dblext_isone_highp3(opndp3) &&			\
+		    (Dblext_isone_lowp2(opndp2) || 			\
+		     Dblext_isnotzero_low31p3(opndp3)))	{		\
+			Dbl_increment(opndp1,opndp2);			\
+			if (Dbl_isone_hiddenoverflow(opndp1))		\
+				is_tiny = FALSE;			\
+			Dbl_decrement(opndp1,opndp2);			\
+		}							\
+		break;							\
+	}								\
+    }									\
+    Dblext_clear_signexponent_set_hidden(opndp1);			\
+    if (exponent >= (1-QUAD_P)) {					\
+	shiftamt = (1-exponent) % 32;					\
+	switch((1-exponent)/32) {					\
+	  case 0: sticky = Dextallp4(opndp4) << 32-(shiftamt);		\
+		  Variableshiftdouble(opndp3,opndp4,shiftamt,opndp4);	\
+		  Variableshiftdouble(opndp2,opndp3,shiftamt,opndp3);	\
+		  Variableshiftdouble(opndp1,opndp2,shiftamt,opndp2);	\
+		  Dextallp1(opndp1) >>= shiftamt;			\
+		  break;						\
+	  case 1: sticky = (Dextallp3(opndp3) << 32-(shiftamt)) | 	\
+			   Dextallp4(opndp4);				\
+		  Variableshiftdouble(opndp2,opndp3,shiftamt,opndp4);	\
+		  Variableshiftdouble(opndp1,opndp2,shiftamt,opndp3);	\
+		  Dextallp2(opndp2) = Dextallp1(opndp1) >> shiftamt;	\
+		  Dextallp1(opndp1) = 0;				\
+		  break;						\
+	  case 2: sticky = (Dextallp2(opndp2) << 32-(shiftamt)) |	\
+			    Dextallp3(opndp3) | Dextallp4(opndp4);	\
+		  Variableshiftdouble(opndp1,opndp2,shiftamt,opndp4);	\
+		  Dextallp3(opndp3) = Dextallp1(opndp1) >> shiftamt;	\
+		  Dextallp1(opndp1) = Dextallp2(opndp2) = 0;		\
+		  break;						\
+	  case 3: sticky = (Dextallp1(opndp1) << 32-(shiftamt)) |	\
+		  	Dextallp2(opndp2) | Dextallp3(opndp3) | 	\
+			Dextallp4(opndp4);				\
+		  Dextallp4(opndp4) = Dextallp1(opndp1) >> shiftamt;	\
+		  Dextallp1(opndp1) = Dextallp2(opndp2) = 0;		\
+		  Dextallp3(opndp3) = 0;				\
+		  break;						\
+	}								\
+    }									\
+    else {								\
+	sticky = Dextallp1(opndp1) | Dextallp2(opndp2) |		\
+		 Dextallp3(opndp3) | Dextallp4(opndp4);			\
+	Dblext_setzero(opndp1,opndp2,opndp3,opndp4);			\
+    }									\
+    if (sticky) Dblext_setone_lowmantissap4(opndp4);			\
+    exponent = 0;							\
+  }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/decode_exc.c linux/arch/parisc/math-emu/decode_exc.c
--- linux.orig/arch/parisc/math-emu/decode_exc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/decode_exc.c	2002-08-12 22:13:58.000000000 +0000
@@ -0,0 +1,368 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/fp/decode_exc.c		$ Revision: $
+ *
+ *  Purpose:
+ *	<<please update with a synopsis of the functionality provided by this file>>
+ *
+ *  External Interfaces:
+ *	<<the following list was autogenerated, please review>>
+ *	decode_fpu(Fpu_register, trap_counts)
+ *
+ *  Internal Interfaces:
+ *	<<please update>>
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+/* #include "types.h" */
+#include <asm/signal.h>
+#include <asm/siginfo.h>
+/* #include <machine/sys/mdep_private.h> */
+
+#undef Fpustatus_register
+#define Fpustatus_register Fpu_register[0]
+
+/* General definitions */
+#define DOESTRAP 1
+#define NOTRAP 0
+#define SIGNALCODE(signal, code) ((signal) << 24 | (code));
+#define copropbit	1<<31-2	/* bit position 2 */
+#define opclass		9	/* bits 21 & 22 */
+#define fmt		11	/* bits 19 & 20 */
+#define df		13	/* bits 17 & 18 */
+#define twobits		3	/* mask low-order 2 bits */
+#define fivebits	31	/* mask low-order 5 bits */
+#define MAX_EXCP_REG	7	/* number of excpeption registers to check */
+
+/* Exception register definitions */
+#define Excp_type(index) Exceptiontype(Fpu_register[index])
+#define Excp_instr(index) Instructionfield(Fpu_register[index])
+#define Clear_excp_register(index) Allexception(Fpu_register[index]) = 0
+#define Excp_format() \
+    (current_ir >> ((current_ir>>opclass & twobits)==1 ? df : fmt) & twobits)
+
+/* Miscellaneous definitions */
+#define Fpu_sgl(index) Fpu_register[index*2]
+
+#define Fpu_dblp1(index) Fpu_register[index*2]
+#define Fpu_dblp2(index) Fpu_register[(index*2)+1]
+
+#define Fpu_quadp1(index) Fpu_register[index*2]
+#define Fpu_quadp2(index) Fpu_register[(index*2)+1]
+#define Fpu_quadp3(index) Fpu_register[(index*2)+2]
+#define Fpu_quadp4(index) Fpu_register[(index*2)+3]
+
+/* Single precision floating-point definitions */
+#ifndef Sgl_decrement
+# define Sgl_decrement(sgl_value) Sall(sgl_value)--
+#endif
+
+/* Double precision floating-point definitions */
+#ifndef Dbl_decrement
+# define Dbl_decrement(dbl_valuep1,dbl_valuep2) \
+    if ((Dallp2(dbl_valuep2)--) == 0) Dallp1(dbl_valuep1)-- 
+#endif
+
+
+#define update_trap_counts(Fpu_register, aflags, bflags, trap_counts) {	\
+	aflags=(Fpu_register[0])>>27;	/* assumes zero fill. 32 bit */	\
+	Fpu_register[0] |= bflags;					\
+}
+
+u_int
+decode_fpu(unsigned int Fpu_register[], unsigned int trap_counts[])
+{
+    unsigned int current_ir, excp;
+    int target, exception_index = 1;
+    boolean inexact;
+    unsigned int aflags;
+    unsigned int bflags;
+    unsigned int excptype;
+
+
+    /* Keep stats on how many floating point exceptions (based on type)
+     * that happen.  Want to keep this overhead low, but still provide
+     * some information to the customer.  All exits from this routine
+     * need to restore Fpu_register[0]
+    */
+
+    bflags=(Fpu_register[0] & 0xf8000000);
+    Fpu_register[0] &= 0x07ffffff;
+
+    /* exception_index is used to index the exception register queue.  It
+     *   always points at the last register that contains a valid exception.  A
+     *   zero value implies no exceptions (also the initialized value).  Setting
+     *   the T-bit resets the exception_index to zero.
+     */
+
+    /*
+     * Check for reserved-op exception.  A reserved-op exception does not 
+     * set any exception registers nor does it set the T-bit.  If the T-bit
+     * is not set then a reserved-op exception occurred.
+     *
+     * At some point, we may want to report reserved op exceptions as
+     * illegal instructions.
+     */
+    
+    if (!Is_tbit_set()) {
+	update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+	return SIGNALCODE(SIGILL, ILL_COPROC);
+    }
+
+    /* 
+     * Is a coprocessor op. 
+     *
+     * Now we need to determine what type of exception occurred.
+     */
+    for (exception_index=1; exception_index<=MAX_EXCP_REG; exception_index++) {
+	current_ir = Excp_instr(exception_index);
+	  /*
+	   * On PA89: there are 5 different unimplemented exception
+	   * codes: 0x1, 0x9, 0xb, 0x3, and 0x23.  PA-RISC 2.0 adds
+	   * another, 0x2b.  Only these have the low order bit set.
+	   */
+	excptype = Excp_type(exception_index);
+	if (excptype & UNIMPLEMENTEDEXCEPTION) {
+		/*
+		 * Clear T-bit and exception register so that
+		 * we can tell if a trap really occurs while 
+		 * emulating the instruction.
+		 */
+		Clear_tbit();
+		Clear_excp_register(exception_index);
+		/*
+		 * Now emulate this instruction.  If a trap occurs,
+		 * fpudispatch will return a non-zero number 
+		 */
+		excp = fpudispatch(current_ir,excptype,0,Fpu_register);
+		/* accumulate the status flags, don't lose them as in hpux */
+		if (excp) {
+			/*
+			 * We now need to make sure that the T-bit and the
+			 * exception register contain the correct values
+			 * before continuing.
+			 */
+			/*
+			 * Set t-bit since it might still be needed for a
+			 * subsequent real trap (I don't understand fully -PB)
+			 */
+			Set_tbit();
+			/* some of the following code uses
+			 * Excp_type(exception_index) so fix that up */
+			Set_exceptiontype_and_instr_field(excp,current_ir,
+			 Fpu_register[exception_index]);
+			if (excp == UNIMPLEMENTEDEXCEPTION) {
+				/*
+			 	 * it is really unimplemented, so restore the
+			 	 * TIMEX extended unimplemented exception code
+			 	 */
+				excp = excptype;
+				update_trap_counts(Fpu_register, aflags, bflags, 
+					   trap_counts);
+				return SIGNALCODE(SIGILL, ILL_COPROC);
+			}
+			/* some of the following code uses excptype, so
+			 * fix that up too */
+			excptype = excp;
+		}
+		/* handle exceptions other than the real UNIMPLIMENTED the
+		 * same way as if the hardware had caused them */
+		if (excp == NOEXCEPTION)
+			/* For now use 'break', should technically be 'continue' */
+			break;
+	}
+
+	  /*
+	   * In PA89, the underflow exception has been extended to encode
+	   * additional information.  The exception looks like pp01x0,
+	   * where x is 1 if inexact and pp represent the inexact bit (I)
+	   * and the round away bit (RA)
+	   */
+	if (excptype & UNDERFLOWEXCEPTION) {
+		/* check for underflow trap enabled */
+		if (Is_underflowtrap_enabled()) {
+			update_trap_counts(Fpu_register, aflags, bflags, 
+					   trap_counts);
+			return SIGNALCODE(SIGFPE, FPE_FLTUND);
+		} else {
+		    /*
+		     * Isn't a real trap; we need to 
+		     * return the default value.
+		     */
+		    target = current_ir & fivebits;
+#ifndef lint
+		    if (Ibit(Fpu_register[exception_index])) inexact = TRUE;
+		    else inexact = FALSE;
+#endif
+		    switch (Excp_format()) {
+		      case SGL:
+		        /*
+		         * If ra (round-away) is set, will 
+		         * want to undo the rounding done
+		         * by the hardware.
+		         */
+		        if (Rabit(Fpu_register[exception_index])) 
+				Sgl_decrement(Fpu_sgl(target));
+
+			/* now denormalize */
+			sgl_denormalize(&Fpu_sgl(target),&inexact,Rounding_mode());
+		    	break;
+		      case DBL:
+		    	/*
+		    	 * If ra (round-away) is set, will 
+		    	 * want to undo the rounding done
+		    	 * by the hardware.
+		    	 */
+		    	if (Rabit(Fpu_register[exception_index])) 
+				Dbl_decrement(Fpu_dblp1(target),Fpu_dblp2(target));
+
+			/* now denormalize */
+			dbl_denormalize(&Fpu_dblp1(target),&Fpu_dblp2(target),
+			  &inexact,Rounding_mode());
+		    	break;
+		    }
+		    if (inexact) Set_underflowflag();
+		    /* 
+		     * Underflow can generate an inexact
+		     * exception.  If inexact trap is enabled,
+		     * want to do an inexact trap, otherwise 
+		     * set inexact flag.
+		     */
+		    if (inexact && Is_inexacttrap_enabled()) {
+		    	/*
+		    	 * Set exception field of exception register
+		    	 * to inexact, parm field to zero.
+			 * Underflow bit should be cleared.
+		    	 */
+		    	Set_exceptiontype(Fpu_register[exception_index],
+			 INEXACTEXCEPTION);
+			Set_parmfield(Fpu_register[exception_index],0);
+			update_trap_counts(Fpu_register, aflags, bflags, 
+					   trap_counts);
+			return SIGNALCODE(SIGFPE, FPE_FLTRES);
+		    }
+		    else {
+		    	/*
+		    	 * Exception register needs to be cleared.  
+			 * Inexact flag needs to be set if inexact.
+		    	 */
+		    	Clear_excp_register(exception_index);
+		    	if (inexact) Set_inexactflag();
+		    }
+		}
+		continue;
+	}
+	switch(Excp_type(exception_index)) {
+	  case OVERFLOWEXCEPTION:
+	  case OVERFLOWEXCEPTION | INEXACTEXCEPTION:
+		/* check for overflow trap enabled */
+			update_trap_counts(Fpu_register, aflags, bflags, 
+					   trap_counts);
+		if (Is_overflowtrap_enabled()) {
+			update_trap_counts(Fpu_register, aflags, bflags, 
+					   trap_counts);
+			return SIGNALCODE(SIGFPE, FPE_FLTOVF);
+		} else {
+			/*
+			 * Isn't a real trap; we need to 
+			 * return the default value.
+			 */
+			target = current_ir & fivebits;
+			switch (Excp_format()) {
+			  case SGL: 
+				Sgl_setoverflow(Fpu_sgl(target));
+				break;
+			  case DBL:
+				Dbl_setoverflow(Fpu_dblp1(target),Fpu_dblp2(target));
+				break;
+			}
+			Set_overflowflag();
+			/* 
+			 * Overflow always generates an inexact
+			 * exception.  If inexact trap is enabled,
+			 * want to do an inexact trap, otherwise 
+			 * set inexact flag.
+			 */
+			if (Is_inexacttrap_enabled()) {
+				/*
+				 * Set exception field of exception
+				 * register to inexact.  Overflow
+				 * bit should be cleared.
+				 */
+				Set_exceptiontype(Fpu_register[exception_index],
+				 INEXACTEXCEPTION);
+				update_trap_counts(Fpu_register, aflags, bflags,
+					   trap_counts);
+				return SIGNALCODE(SIGFPE, FPE_FLTRES);
+			}
+			else {
+				/*
+				 * Exception register needs to be cleared.  
+				 * Inexact flag needs to be set.
+				 */
+				Clear_excp_register(exception_index);
+				Set_inexactflag();
+			}
+		}
+		break;
+	  case INVALIDEXCEPTION:
+		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+		return SIGNALCODE(SIGFPE, FPE_FLTINV);
+	  case DIVISIONBYZEROEXCEPTION:
+		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+	  	return SIGNALCODE(SIGFPE, FPE_FLTDIV);
+	  case INEXACTEXCEPTION:
+		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+		return SIGNALCODE(SIGFPE, FPE_FLTRES);
+	  default:
+		update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+		printk(__FILE__ "(%d) Unknown FPU exception 0x%x\n",
+			__LINE__, Excp_type(exception_index));
+		return SIGNALCODE(SIGILL, ILL_COPROC);
+	  case NOEXCEPTION:	/* no exception */
+		/*
+		 * Clear exception register in case 
+		 * other fields are non-zero.
+		 */
+		Clear_excp_register(exception_index);
+		break;
+	}
+    }
+    /*
+     * No real exceptions occurred.
+     */
+    Clear_tbit();
+    update_trap_counts(Fpu_register, aflags, bflags, trap_counts);
+    return(NOTRAP);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/denormal.c linux/arch/parisc/math-emu/denormal.c
--- linux.orig/arch/parisc/math-emu/denormal.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/denormal.c	2002-08-12 22:14:01.000000000 +0000
@@ -0,0 +1,135 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/fp/denormal.c		$ Revision: $
+ *
+ *  Purpose:
+ *	<<please update with a synopsis of the functionality provided by this file>>
+ *
+ *  External Interfaces:
+ *	<<the following list was autogenerated, please review>>
+ *	dbl_denormalize(dbl_opndp1,dbl_opndp2,inexactflag,rmode)
+ *	sgl_denormalize(sgl_opnd,inexactflag,rmode)
+ *
+ *  Internal Interfaces:
+ *	<<please update>>
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "hppa.h"
+#include "types.h"
+/* #include <machine/sys/mdep_private.h> */
+
+#undef Fpustatus_register
+#define Fpustatus_register Fpu_register[0]
+
+void
+sgl_denormalize(unsigned int *sgl_opnd, boolean *inexactflag, int rmode)
+{
+	unsigned int opnd;
+	int sign, exponent;
+	boolean guardbit = FALSE, stickybit, inexact;
+
+	opnd = *sgl_opnd;
+	stickybit = *inexactflag;
+        exponent = Sgl_exponent(opnd) - SGL_WRAP;
+        sign = Sgl_sign(opnd);
+	Sgl_denormalize(opnd,exponent,guardbit,stickybit,inexact);
+	if (inexact) {
+	    switch (rmode) {
+	      case ROUNDPLUS:
+		if (sign == 0) {
+			Sgl_increment(opnd);
+		}
+		break;
+	      case ROUNDMINUS:
+		if (sign != 0) {
+			Sgl_increment(opnd);
+		}
+		break;
+	      case ROUNDNEAREST:
+		if (guardbit && (stickybit || 
+		       Sgl_isone_lowmantissa(opnd))) {
+			   Sgl_increment(opnd);
+		}
+		break;
+	    }
+	}
+	Sgl_set_sign(opnd,sign);
+	*sgl_opnd = opnd;
+	*inexactflag = inexact;
+	return;
+}
+
+void
+dbl_denormalize(unsigned int *dbl_opndp1,
+	unsigned int * dbl_opndp2,
+	boolean *inexactflag,
+	int rmode)
+{
+	unsigned int opndp1, opndp2;
+	int sign, exponent;
+	boolean guardbit = FALSE, stickybit, inexact;
+
+	opndp1 = *dbl_opndp1;
+	opndp2 = *dbl_opndp2;
+	stickybit = *inexactflag;
+	exponent = Dbl_exponent(opndp1) - DBL_WRAP;
+	sign = Dbl_sign(opndp1);
+	Dbl_denormalize(opndp1,opndp2,exponent,guardbit,stickybit,inexact);
+	if (inexact) {
+	    switch (rmode) {
+	      case ROUNDPLUS:
+		if (sign == 0) {
+			Dbl_increment(opndp1,opndp2);
+		}
+		break;
+	      case ROUNDMINUS:
+		if (sign != 0) {
+			Dbl_increment(opndp1,opndp2);
+		}
+		break;
+	      case ROUNDNEAREST:
+		if (guardbit && (stickybit || 
+		       Dbl_isone_lowmantissap2(opndp2))) {
+			   Dbl_increment(opndp1,opndp2);
+		}
+		break;
+	    }
+	}
+	Dbl_set_sign(opndp1,sign);
+	*dbl_opndp1 = opndp1;
+	*dbl_opndp2 = opndp2;
+	*inexactflag = inexact;
+	return;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfadd.c linux/arch/parisc/math-emu/dfadd.c
--- linux.orig/arch/parisc/math-emu/dfadd.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfadd.c	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,524 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfadd.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double_add: add two double precision values.
+ *
+ *  External Interfaces:
+ *	dbl_fadd(leftptr, rightptr, dstptr, status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double_add: add two double precision values.
+ */
+dbl_fadd(
+    dbl_floating_point *leftptr,
+    dbl_floating_point *rightptr,
+    dbl_floating_point *dstptr,
+    unsigned int *status)
+{
+    register unsigned int signless_upper_left, signless_upper_right, save;
+    register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
+    register unsigned int resultp1 = 0, resultp2 = 0;
+    
+    register int result_exponent, right_exponent, diff_exponent;
+    register int sign_save, jumpsize;
+    register boolean inexact = FALSE;
+    register boolean underflowtrap;
+        
+    /* Create local copies of the numbers */
+    Dbl_copyfromptr(leftptr,leftp1,leftp2);
+    Dbl_copyfromptr(rightptr,rightp1,rightp2);
+
+    /* A zero "save" helps discover equal operands (for later),  *
+     * and is used in swapping operands (if needed).             */
+    Dbl_xortointp1(leftp1,rightp1,/*to*/save);
+
+    /*
+     * check first operand for NaN's or infinity
+     */
+    if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
+	{
+	if (Dbl_iszero_mantissa(leftp1,leftp2)) 
+	    {
+	    if (Dbl_isnotnan(rightp1,rightp2)) 
+		{
+		if (Dbl_isinfinity(rightp1,rightp2) && save!=0) 
+		    {
+		    /* 
+		     * invalid since operands are opposite signed infinity's
+		     */
+		    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                    Set_invalidflag();
+                    Dbl_makequietnan(resultp1,resultp2);
+		    Dbl_copytoptr(resultp1,resultp2,dstptr);
+		    return(NOEXCEPTION);
+		    }
+		/*
+	 	 * return infinity
+	 	 */
+		Dbl_copytoptr(leftp1,leftp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    }
+	else 
+	    {
+            /*
+             * is NaN; signaling or quiet?
+             */
+            if (Dbl_isone_signaling(leftp1)) 
+		{
+               	/* trap if INVALIDTRAP enabled */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+        	/* make NaN quiet */
+        	Set_invalidflag();
+        	Dbl_set_quiet(leftp1);
+        	}
+	    /* 
+	     * is second operand a signaling NaN? 
+	     */
+	    else if (Dbl_is_signalingnan(rightp1)) 
+		{
+        	/* trap if INVALIDTRAP enabled */
+               	if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+		/* make NaN quiet */
+		Set_invalidflag();
+		Dbl_set_quiet(rightp1);
+		Dbl_copytoptr(rightp1,rightp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    /*
+ 	     * return quiet NaN
+ 	     */
+	    Dbl_copytoptr(leftp1,leftp2,dstptr);
+ 	    return(NOEXCEPTION);
+	    }
+	} /* End left NaN or Infinity processing */
+    /*
+     * check second operand for NaN's or infinity
+     */
+    if (Dbl_isinfinity_exponent(rightp1)) 
+	{
+	if (Dbl_iszero_mantissa(rightp1,rightp2)) 
+	    {
+	    /* return infinity */
+	    Dbl_copytoptr(rightp1,rightp2,dstptr);
+	    return(NOEXCEPTION);
+	    }
+        /*
+         * is NaN; signaling or quiet?
+         */
+        if (Dbl_isone_signaling(rightp1)) 
+	    {
+            /* trap if INVALIDTRAP enabled */
+	    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+	    /* make NaN quiet */
+	    Set_invalidflag();
+	    Dbl_set_quiet(rightp1);
+	    }
+	/*
+	 * return quiet NaN
+ 	 */
+	Dbl_copytoptr(rightp1,rightp2,dstptr);
+	return(NOEXCEPTION);
+    	} /* End right NaN or Infinity processing */
+
+    /* Invariant: Must be dealing with finite numbers */
+
+    /* Compare operands by removing the sign */
+    Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
+    Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
+
+    /* sign difference selects add or sub operation. */
+    if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
+	{
+	/* Set the left operand to the larger one by XOR swap *
+	 *  First finish the first word using "save"          */
+	Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
+	Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
+     	Dbl_swap_lower(leftp2,rightp2);
+	result_exponent = Dbl_exponent(leftp1);
+	}
+    /* Invariant:  left is not smaller than right. */ 
+
+    if((right_exponent = Dbl_exponent(rightp1)) == 0)
+        {
+	/* Denormalized operands.  First look for zeroes */
+	if(Dbl_iszero_mantissa(rightp1,rightp2)) 
+	    {
+	    /* right is zero */
+	    if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
+		{
+		/* Both operands are zeros */
+		if(Is_rounding_mode(ROUNDMINUS))
+		    {
+		    Dbl_or_signs(leftp1,/*with*/rightp1);
+		    }
+		else
+		    {
+		    Dbl_and_signs(leftp1,/*with*/rightp1);
+		    }
+		}
+	    else 
+		{
+		/* Left is not a zero and must be the result.  Trapped
+		 * underflows are signaled if left is denormalized.  Result
+		 * is always exact. */
+		if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+		    {
+		    /* need to normalize results mantissa */
+	    	    sign_save = Dbl_signextendedsign(leftp1);
+		    Dbl_leftshiftby1(leftp1,leftp2);
+		    Dbl_normalize(leftp1,leftp2,result_exponent);
+		    Dbl_set_sign(leftp1,/*using*/sign_save);
+                    Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
+		    Dbl_copytoptr(leftp1,leftp2,dstptr);
+		    /* inexact = FALSE */
+		    return(UNDERFLOWEXCEPTION);
+		    }
+		}
+	    Dbl_copytoptr(leftp1,leftp2,dstptr);
+	    return(NOEXCEPTION);
+	    }
+
+	/* Neither are zeroes */
+	Dbl_clear_sign(rightp1);	/* Exponent is already cleared */
+	if(result_exponent == 0 )
+	    {
+	    /* Both operands are denormalized.  The result must be exact
+	     * and is simply calculated.  A sum could become normalized and a
+	     * difference could cancel to a true zero. */
+	    if( (/*signed*/int) save < 0 )
+		{
+		Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
+		/*into*/resultp1,resultp2);
+		if(Dbl_iszero_mantissa(resultp1,resultp2))
+		    {
+		    if(Is_rounding_mode(ROUNDMINUS))
+			{
+			Dbl_setone_sign(resultp1);
+			}
+		    else
+			{
+			Dbl_setzero_sign(resultp1);
+			}
+		    Dbl_copytoptr(resultp1,resultp2,dstptr);
+		    return(NOEXCEPTION);
+		    }
+		}
+	    else
+		{
+		Dbl_addition(leftp1,leftp2,rightp1,rightp2,
+		/*into*/resultp1,resultp2);
+		if(Dbl_isone_hidden(resultp1))
+		    {
+		    Dbl_copytoptr(resultp1,resultp2,dstptr);
+		    return(NOEXCEPTION);
+		    }
+		}
+	    if(Is_underflowtrap_enabled())
+		{
+		/* need to normalize result */
+	    	sign_save = Dbl_signextendedsign(resultp1);
+		Dbl_leftshiftby1(resultp1,resultp2);
+		Dbl_normalize(resultp1,resultp2,result_exponent);
+		Dbl_set_sign(resultp1,/*using*/sign_save);
+                Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+	        Dbl_copytoptr(resultp1,resultp2,dstptr);
+		/* inexact = FALSE */
+	        return(UNDERFLOWEXCEPTION);
+		}
+	    Dbl_copytoptr(resultp1,resultp2,dstptr);
+	    return(NOEXCEPTION);
+	    }
+	right_exponent = 1;	/* Set exponent to reflect different bias
+				 * with denomalized numbers. */
+	}
+    else
+	{
+	Dbl_clear_signexponent_set_hidden(rightp1);
+	}
+    Dbl_clear_exponent_set_hidden(leftp1);
+    diff_exponent = result_exponent - right_exponent;
+
+    /* 
+     * Special case alignment of operands that would force alignment 
+     * beyond the extent of the extension.  A further optimization
+     * could special case this but only reduces the path length for this
+     * infrequent case.
+     */
+    if(diff_exponent > DBL_THRESHOLD)
+	{
+	diff_exponent = DBL_THRESHOLD;
+	}
+    
+    /* Align right operand by shifting to right */
+    Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
+    /*and lower to*/extent);
+
+    /* Treat sum and difference of the operands separately. */
+    if( (/*signed*/int) save < 0 )
+	{
+	/*
+	 * Difference of the two operands.  Their can be no overflow.  A
+	 * borrow can occur out of the hidden bit and force a post
+	 * normalization phase.
+	 */
+	Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
+	/*with*/extent,/*into*/resultp1,resultp2);
+	if(Dbl_iszero_hidden(resultp1))
+	    {
+	    /* Handle normalization */
+	    /* A straight foward algorithm would now shift the result
+	     * and extension left until the hidden bit becomes one.  Not
+	     * all of the extension bits need participate in the shift.
+	     * Only the two most significant bits (round and guard) are
+	     * needed.  If only a single shift is needed then the guard
+	     * bit becomes a significant low order bit and the extension
+	     * must participate in the rounding.  If more than a single 
+	     * shift is needed, then all bits to the right of the guard 
+	     * bit are zeros, and the guard bit may or may not be zero. */
+	    sign_save = Dbl_signextendedsign(resultp1);
+            Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
+
+            /* Need to check for a zero result.  The sign and exponent
+	     * fields have already been zeroed.  The more efficient test
+	     * of the full object can be used.
+	     */
+    	    if(Dbl_iszero(resultp1,resultp2))
+		/* Must have been "x-x" or "x+(-x)". */
+		{
+		if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    result_exponent--;
+	    /* Look to see if normalization is finished. */
+	    if(Dbl_isone_hidden(resultp1))
+		{
+		if(result_exponent==0)
+		    {
+		    /* Denormalized, exponent should be zero.  Left operand *
+		     * was normalized, so extent (guard, round) was zero    */
+		    goto underflow;
+		    }
+		else
+		    {
+		    /* No further normalization is needed. */
+		    Dbl_set_sign(resultp1,/*using*/sign_save);
+	    	    Ext_leftshiftby1(extent);
+		    goto round;
+		    }
+		}
+
+	    /* Check for denormalized, exponent should be zero.  Left    *
+	     * operand was normalized, so extent (guard, round) was zero */
+	    if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+	       result_exponent==0) goto underflow;
+
+	    /* Shift extension to complete one bit of normalization and
+	     * update exponent. */
+	    Ext_leftshiftby1(extent);
+
+	    /* Discover first one bit to determine shift amount.  Use a
+	     * modified binary search.  We have already shifted the result
+	     * one position right and still not found a one so the remainder
+	     * of the extension must be zero and simplifies rounding. */
+	    /* Scan bytes */
+	    while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
+		{
+		Dbl_leftshiftby8(resultp1,resultp2);
+		if((result_exponent -= 8) <= 0  && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Now narrow it down to the nibble */
+	    if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
+		{
+		/* The lower nibble contains the normalizing one */
+		Dbl_leftshiftby4(resultp1,resultp2);
+		if((result_exponent -= 4) <= 0 && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Select case were first bit is set (already normalized)
+	     * otherwise select the proper shift. */
+	    if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
+		{
+		/* Already normalized */
+		if(result_exponent <= 0) goto underflow;
+		Dbl_set_sign(resultp1,/*using*/sign_save);
+		Dbl_set_exponent(resultp1,/*using*/result_exponent);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    Dbl_sethigh4bits(resultp1,/*using*/sign_save);
+	    switch(jumpsize) 
+		{
+		case 1:
+		    {
+		    Dbl_leftshiftby3(resultp1,resultp2);
+		    result_exponent -= 3;
+		    break;
+		    }
+		case 2:
+		case 3:
+		    {
+		    Dbl_leftshiftby2(resultp1,resultp2);
+		    result_exponent -= 2;
+		    break;
+		    }
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		    {
+		    Dbl_leftshiftby1(resultp1,resultp2);
+		    result_exponent -= 1;
+		    break;
+		    }
+		}
+	    if(result_exponent > 0) 
+		{
+		Dbl_set_exponent(resultp1,/*using*/result_exponent);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION); 	/* Sign bit is already set */
+		}
+	    /* Fixup potential underflows */
+	  underflow:
+	    if(Is_underflowtrap_enabled())
+		{
+		Dbl_set_sign(resultp1,sign_save);
+                Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		/* inexact = FALSE */
+		return(UNDERFLOWEXCEPTION);
+		}
+	    /* 
+	     * Since we cannot get an inexact denormalized result,
+	     * we can now return.
+	     */
+	    Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
+	    Dbl_clear_signexponent(resultp1);
+	    Dbl_set_sign(resultp1,sign_save);
+	    Dbl_copytoptr(resultp1,resultp2,dstptr);
+	    return(NOEXCEPTION);
+	    } /* end if(hidden...)... */
+	/* Fall through and round */
+	} /* end if(save < 0)... */
+    else 
+	{
+	/* Add magnitudes */
+	Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
+	if(Dbl_isone_hiddenoverflow(resultp1))
+	    {
+	    /* Prenormalization required. */
+	    Dbl_rightshiftby1_withextent(resultp2,extent,extent);
+	    Dbl_arithrightshiftby1(resultp1,resultp2);
+	    result_exponent++;
+	    } /* end if hiddenoverflow... */
+	} /* end else ...add magnitudes... */
+    
+    /* Round the result.  If the extension is all zeros,then the result is
+     * exact.  Otherwise round in the correct direction.  No underflow is
+     * possible. If a postnormalization is necessary, then the mantissa is
+     * all zeros so no shift is needed. */
+  round:
+    if(Ext_isnotzero(extent))
+	{
+	inexact = TRUE;
+	switch(Rounding_mode())
+	    {
+	    case ROUNDNEAREST: /* The default. */
+	    if(Ext_isone_sign(extent))
+		{
+		/* at least 1/2 ulp */
+		if(Ext_isnotzero_lower(extent)  ||
+		  Dbl_isone_lowmantissap2(resultp2))
+		    {
+		    /* either exactly half way and odd or more than 1/2ulp */
+		    Dbl_increment(resultp1,resultp2);
+		    }
+		}
+	    break;
+
+	    case ROUNDPLUS:
+	    if(Dbl_iszero_sign(resultp1))
+		{
+		/* Round up positive results */
+		Dbl_increment(resultp1,resultp2);
+		}
+	    break;
+	    
+	    case ROUNDMINUS:
+	    if(Dbl_isone_sign(resultp1))
+		{
+		/* Round down negative results */
+		Dbl_increment(resultp1,resultp2);
+		}
+	    
+	    case ROUNDZERO:;
+	    /* truncate is simple */
+	    } /* end switch... */
+	if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+	}
+    if(result_exponent == DBL_INFINITY_EXPONENT)
+        {
+        /* Overflow */
+        if(Is_overflowtrap_enabled())
+	    {
+	    Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+	    Dbl_copytoptr(resultp1,resultp2,dstptr);
+	    if (inexact)
+		if (Is_inexacttrap_enabled())
+			return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+		else Set_inexactflag();
+	    return(OVERFLOWEXCEPTION);
+	    }
+        else
+	    {
+	    inexact = TRUE;
+	    Set_overflowflag();
+	    Dbl_setoverflow(resultp1,resultp2);
+	    }
+	}
+    else Dbl_set_exponent(resultp1,result_exponent);
+    Dbl_copytoptr(resultp1,resultp2,dstptr);
+    if(inexact) 
+	if(Is_inexacttrap_enabled())
+	    return(INEXACTEXCEPTION);
+	else Set_inexactflag();
+    return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfcmp.c linux/arch/parisc/math-emu/dfcmp.c
--- linux.orig/arch/parisc/math-emu/dfcmp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfcmp.c	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,181 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfcmp.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	dbl_cmp: compare two values
+ *
+ *  External Interfaces:
+ *	dbl_fcmp(leftptr, rightptr, cond, status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "dbl_float.h"
+    
+/*
+ * dbl_cmp: compare two values
+ */
+int
+dbl_fcmp (dbl_floating_point * leftptr, dbl_floating_point * rightptr,
+	  unsigned int cond, unsigned int *status)
+                                           
+                       /* The predicate to be tested */
+                         
+    {
+    register unsigned int leftp1, leftp2, rightp1, rightp2;
+    register int xorresult;
+        
+    /* Create local copies of the numbers */
+    Dbl_copyfromptr(leftptr,leftp1,leftp2);
+    Dbl_copyfromptr(rightptr,rightp1,rightp2);
+    /*
+     * Test for NaN
+     */
+    if(    (Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
+        || (Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT) )
+	{
+	/* Check if a NaN is involved.  Signal an invalid exception when 
+	 * comparing a signaling NaN or when comparing quiet NaNs and the
+	 * low bit of the condition is set */
+        if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
+	    && Dbl_isnotzero_mantissa(leftp1,leftp2) 
+	    && (Exception(cond) || Dbl_isone_signaling(leftp1)))
+	   ||
+	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
+	    && Dbl_isnotzero_mantissa(rightp1,rightp2) 
+	    && (Exception(cond) || Dbl_isone_signaling(rightp1))) )
+	    {
+	    if( Is_invalidtrap_enabled() ) {
+	    	Set_status_cbit(Unordered(cond));
+		return(INVALIDEXCEPTION);
+	    }
+	    else Set_invalidflag();
+	    Set_status_cbit(Unordered(cond));
+	    return(NOEXCEPTION);
+	    }
+	/* All the exceptional conditions are handled, now special case
+	   NaN compares */
+        else if( ((Dbl_exponent(leftp1) == DBL_INFINITY_EXPONENT)
+	    && Dbl_isnotzero_mantissa(leftp1,leftp2))
+	   ||
+	    ((Dbl_exponent(rightp1) == DBL_INFINITY_EXPONENT)
+	    && Dbl_isnotzero_mantissa(rightp1,rightp2)) )
+	    {
+	    /* NaNs always compare unordered. */
+	    Set_status_cbit(Unordered(cond));
+	    return(NOEXCEPTION);
+	    }
+	/* infinities will drop down to the normal compare mechanisms */
+	}
+    /* First compare for unequal signs => less or greater or
+     * special equal case */
+    Dbl_xortointp1(leftp1,rightp1,xorresult);
+    if( xorresult < 0 )
+        {
+        /* left negative => less, left positive => greater.
+         * equal is possible if both operands are zeros. */
+        if( Dbl_iszero_exponentmantissa(leftp1,leftp2) 
+	  && Dbl_iszero_exponentmantissa(rightp1,rightp2) )
+            {
+	    Set_status_cbit(Equal(cond));
+	    }
+	else if( Dbl_isone_sign(leftp1) )
+	    {
+	    Set_status_cbit(Lessthan(cond));
+	    }
+	else
+	    {
+	    Set_status_cbit(Greaterthan(cond));
+	    }
+        }
+    /* Signs are the same.  Treat negative numbers separately
+     * from the positives because of the reversed sense.  */
+    else if(Dbl_isequal(leftp1,leftp2,rightp1,rightp2))
+        {
+        Set_status_cbit(Equal(cond));
+        }
+    else if( Dbl_iszero_sign(leftp1) )
+        {
+        /* Positive compare */
+	if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
+	    {
+	    Set_status_cbit(Lessthan(cond));
+	    }
+	else if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
+	    {
+	    Set_status_cbit(Greaterthan(cond));
+	    }
+	else
+	    {
+	    /* Equal first parts.  Now we must use unsigned compares to
+	     * resolve the two possibilities. */
+	    if( Dbl_allp2(leftp2) < Dbl_allp2(rightp2) )
+		{
+		Set_status_cbit(Lessthan(cond));
+		}
+	    else 
+		{
+		Set_status_cbit(Greaterthan(cond));
+		}
+	    }
+	}
+    else
+        {
+        /* Negative compare.  Signed or unsigned compares
+         * both work the same.  That distinction is only
+         * important when the sign bits differ. */
+	if( Dbl_allp1(leftp1) > Dbl_allp1(rightp1) )
+	    {
+	    Set_status_cbit(Lessthan(cond));
+	    }
+	else if( Dbl_allp1(leftp1) < Dbl_allp1(rightp1) )
+	    {
+	    Set_status_cbit(Greaterthan(cond));
+	    }
+	else
+	    {
+	    /* Equal first parts.  Now we must use unsigned compares to
+	     * resolve the two possibilities. */
+	    if( Dbl_allp2(leftp2) > Dbl_allp2(rightp2) )
+		{
+		Set_status_cbit(Lessthan(cond));
+		}
+	    else 
+		{
+		Set_status_cbit(Greaterthan(cond));
+		}
+	    }
+        }
+	return(NOEXCEPTION);
+    }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfdiv.c linux/arch/parisc/math-emu/dfdiv.c
--- linux.orig/arch/parisc/math-emu/dfdiv.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfdiv.c	2002-08-12 22:14:17.000000000 +0000
@@ -0,0 +1,400 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfdiv.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double Precision Floating-point Divide
+ *
+ *  External Interfaces:
+ *	dbl_fdiv(srcptr1,srcptr2,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ *  Double Precision Floating-point Divide
+ */
+
+int
+dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
+	  dbl_floating_point * dstptr, unsigned int *status)
+{
+	register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
+	register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
+	register int dest_exponent, count;
+	register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+	boolean is_tiny;
+
+	Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
+	Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
+	/* 
+	 * set sign bit of result 
+	 */
+	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
+		Dbl_setnegativezerop1(resultp1);  
+	else Dbl_setzerop1(resultp1);
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd1p1)) {
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
+				if (Dbl_isinfinity(opnd2p1,opnd2p2)) {
+					/* 
+					 * invalid since both operands 
+					 * are infinity 
+					 */
+					if (Is_invalidtrap_enabled())
+                                		return(INVALIDEXCEPTION);
+                                	Set_invalidflag();
+                                	Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+				/*
+			 	 * return infinity
+			 	 */
+				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+                	/*
+                 	 * is NaN; signaling or quiet?
+                 	 */
+                	if (Dbl_isone_signaling(opnd1p1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled())
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Dbl_set_quiet(opnd1p1);
+                	}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd2p1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled())
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Dbl_set_quiet(opnd2p1);
+				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+                		return(NOEXCEPTION);
+			}
+                	/*
+                 	 * return quiet NaN
+                 	 */
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+                	return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd2p1)) {
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			/*
+			 * return zero
+			 */
+			Dbl_setzero_exponentmantissa(resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+                /*
+                 * is NaN; signaling or quiet?
+                 */
+                if (Dbl_isone_signaling(opnd2p1)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Dbl_set_quiet(opnd2p1);
+                }
+                /*
+                 * return quiet NaN
+                 */
+		Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+                return(NOEXCEPTION);
+	}
+        /*
+         * check for division by zero
+         */
+        if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+                if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+                        /* invalid since both operands are zero */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        Set_invalidflag();
+                        Dbl_makequietnan(resultp1,resultp2);
+                        Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        return(NOEXCEPTION);
+                }
+                if (Is_divisionbyzerotrap_enabled())
+                       	return(DIVISIONBYZEROEXCEPTION);
+                Set_divisionbyzeroflag();
+                Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+                Dbl_copytoptr(resultp1,resultp2,dstptr);
+                return(NOEXCEPTION);
+        }
+	/*
+	 * Generate exponent 
+	 */
+	dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS;
+
+	/*
+	 * Generate mantissa
+	 */
+	if (Dbl_isnotzero_exponent(opnd1p1)) {
+		/* set hidden bit */
+		Dbl_clear_signexponent_set_hidden(opnd1p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			Dbl_setzero_exponentmantissa(resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+                /* is denormalized, want to normalize */
+                Dbl_clear_signexponent(opnd1p1);
+                Dbl_leftshiftby1(opnd1p1,opnd1p2);
+		Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Dbl_isnotzero_exponent(opnd2p1)) {
+		Dbl_clear_signexponent_set_hidden(opnd2p1);
+	}
+	else {
+                /* is denormalized; want to normalize */
+                Dbl_clear_signexponent(opnd2p1);
+                Dbl_leftshiftby1(opnd2p1,opnd2p2);
+                while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) {
+                        dest_exponent+=8;
+                        Dbl_leftshiftby8(opnd2p1,opnd2p2);
+                }
+                if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) {
+                        dest_exponent+=4;
+                        Dbl_leftshiftby4(opnd2p1,opnd2p2);
+                }
+                while (Dbl_iszero_hidden(opnd2p1)) {
+                        dest_exponent++;
+                        Dbl_leftshiftby1(opnd2p1,opnd2p2);
+                }
+	}
+
+	/* Divide the source mantissas */
+
+	/* 
+	 * A non-restoring divide algorithm is used.
+	 */
+	Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+	Dbl_setzero(opnd3p1,opnd3p2);
+	for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) {
+		Dbl_leftshiftby1(opnd1p1,opnd1p2);
+		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+		if (Dbl_iszero_sign(opnd1p1)) {
+			Dbl_setone_lowmantissap2(opnd3p2);
+			Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+		}
+		else {
+			Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2);
+		}
+	}
+	if (count <= DBL_P) {
+		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+		Dbl_setone_lowmantissap2(opnd3p2);
+		Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count));
+		if (Dbl_iszero_hidden(opnd3p1)) {
+			Dbl_leftshiftby1(opnd3p1,opnd3p2);
+			dest_exponent--;
+		}
+	}
+	else {
+		if (Dbl_iszero_hidden(opnd3p1)) {
+			/* need to get one more bit of result */
+			Dbl_leftshiftby1(opnd1p1,opnd1p2);
+			Dbl_leftshiftby1(opnd3p1,opnd3p2);
+			if (Dbl_iszero_sign(opnd1p1)) {
+				Dbl_setone_lowmantissap2(opnd3p2);
+				Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+			}
+			else {
+				Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2);
+			}
+			dest_exponent--;
+		}
+		if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE;
+		stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2);
+	}
+	inexact = guardbit | stickybit;
+
+	/* 
+	 * round result 
+	 */
+	if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
+		Dbl_clear_signexponent(opnd3p1);
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Dbl_iszero_sign(resultp1)) 
+					Dbl_increment(opnd3p1,opnd3p2);
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) 
+					Dbl_increment(opnd3p1,opnd3p2);
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Dbl_isone_lowmantissap2(opnd3p2))) {
+			      		Dbl_increment(opnd3p1,opnd3p2);
+				}
+		}
+		if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
+	}
+	Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+
+        /* 
+         * Test for overflow
+         */
+	if (dest_exponent >= DBL_INFINITY_EXPONENT) {
+                /* trap if OVERFLOWTRAP enabled */
+                if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
+                        Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        if (inexact) 
+                            if (Is_inexacttrap_enabled())
+                                return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return(OVERFLOWEXCEPTION);
+                }
+		Set_overflowflag();
+                /* set result to infinity or largest number */
+		Dbl_setoverflow(resultp1,resultp2);
+		inexact = TRUE;
+	}
+        /* 
+         * Test for underflow
+         */
+	else if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
+                        Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        if (inexact) 
+                            if (Is_inexacttrap_enabled())
+                                return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return(UNDERFLOWEXCEPTION);
+                }
+
+		/* Determine if should set underflow flag */
+		is_tiny = TRUE;
+		if (dest_exponent == 0 && inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Dbl_iszero_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+					if (Dbl_isone_hiddenoverflow(opnd3p1))
+                			    is_tiny = FALSE;
+					Dbl_decrement(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+					if (Dbl_isone_hiddenoverflow(opnd3p1))
+                			    is_tiny = FALSE;
+					Dbl_decrement(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Dbl_isone_lowmantissap2(opnd3p2))) {
+				      	Dbl_increment(opnd3p1,opnd3p2);
+					if (Dbl_isone_hiddenoverflow(opnd3p1))
+                			    is_tiny = FALSE;
+					Dbl_decrement(opnd3p1,opnd3p2);
+				}
+				break;
+			}
+		}
+
+                /*
+                 * denormalize result or set to signed zero
+                 */
+		stickybit = inexact;
+		Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
+		 stickybit,inexact);
+
+		/* return rounded number */ 
+		if (inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				if (Dbl_iszero_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Dbl_isone_lowmantissap2(opnd3p2))) {
+			      		Dbl_increment(opnd3p1,opnd3p2);
+				}
+				break;
+			}
+                	if (is_tiny) Set_underflowflag();
+                }
+		Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+	}
+	else Dbl_set_exponent(resultp1,dest_exponent);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+
+	/* check for inexact */
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfmpy.c linux/arch/parisc/math-emu/dfmpy.c
--- linux.orig/arch/parisc/math-emu/dfmpy.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfmpy.c	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,394 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfmpy.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double Precision Floating-point Multiply
+ *
+ *  External Interfaces:
+ *	dbl_fmpy(srcptr1,srcptr2,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ *  Double Precision Floating-point Multiply
+ */
+
+int
+dbl_fmpy(
+	    dbl_floating_point *srcptr1,
+	    dbl_floating_point *srcptr2,
+	    dbl_floating_point *dstptr,
+	    unsigned int *status)
+{
+	register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
+	register unsigned int opnd3p1, opnd3p2, resultp1, resultp2;
+	register int dest_exponent, count;
+	register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+	boolean is_tiny;
+
+	Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
+	Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
+
+	/* 
+	 * set sign bit of result 
+	 */
+	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
+		Dbl_setnegativezerop1(resultp1); 
+	else Dbl_setzerop1(resultp1);
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd1p1)) {
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
+				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+					/* 
+					 * invalid since operands are infinity 
+					 * and zero 
+					 */
+					if (Is_invalidtrap_enabled())
+                                		return(INVALIDEXCEPTION);
+                                	Set_invalidflag();
+                                	Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+				/*
+			 	 * return infinity
+			 	 */
+				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+                	/*
+                 	 * is NaN; signaling or quiet?
+                 	 */
+                	if (Dbl_isone_signaling(opnd1p1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Dbl_set_quiet(opnd1p1);
+                	}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd2p1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled())
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Dbl_set_quiet(opnd2p1);
+				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+                		return(NOEXCEPTION);
+			}
+                	/*
+                 	 * return quiet NaN
+                 	 */
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+                	return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd2p1)) {
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+				/* invalid since operands are zero & infinity */
+				if (Is_invalidtrap_enabled())
+                                	return(INVALIDEXCEPTION);
+                                Set_invalidflag();
+                                Dbl_makequietnan(opnd2p1,opnd2p2);
+				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/*
+			 * return infinity
+			 */
+			Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+                /*
+                 * is NaN; signaling or quiet?
+                 */
+                if (Dbl_isone_signaling(opnd2p1)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Dbl_set_quiet(opnd2p1);
+                }
+                /*
+                 * return quiet NaN
+                 */
+		Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+                return(NOEXCEPTION);
+	}
+	/*
+	 * Generate exponent 
+	 */
+	dest_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) -DBL_BIAS;
+
+	/*
+	 * Generate mantissa
+	 */
+	if (Dbl_isnotzero_exponent(opnd1p1)) {
+		/* set hidden bit */
+		Dbl_clear_signexponent_set_hidden(opnd1p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			Dbl_setzero_exponentmantissa(resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+                /* is denormalized, adjust exponent */
+                Dbl_clear_signexponent(opnd1p1);
+                Dbl_leftshiftby1(opnd1p1,opnd1p2);
+		Dbl_normalize(opnd1p1,opnd1p2,dest_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Dbl_isnotzero_exponent(opnd2p1)) {
+		Dbl_clear_signexponent_set_hidden(opnd2p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			Dbl_setzero_exponentmantissa(resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+                /* is denormalized; want to normalize */
+                Dbl_clear_signexponent(opnd2p1);
+                Dbl_leftshiftby1(opnd2p1,opnd2p2);
+		Dbl_normalize(opnd2p1,opnd2p2,dest_exponent);
+	}
+
+	/* Multiply two source mantissas together */
+
+	/* make room for guard bits */
+	Dbl_leftshiftby7(opnd2p1,opnd2p2);
+	Dbl_setzero(opnd3p1,opnd3p2);
+        /* 
+         * Four bits at a time are inspected in each loop, and a 
+         * simple shift and add multiply algorithm is used. 
+         */ 
+	for (count=1;count<=DBL_P;count+=4) {
+		stickybit |= Dlow4p2(opnd3p2);
+		Dbl_rightshiftby4(opnd3p1,opnd3p2);
+		if (Dbit28p2(opnd1p2)) {
+	 		/* Twoword_add should be an ADDC followed by an ADD. */
+                        Twoword_add(opnd3p1, opnd3p2, opnd2p1<<3 | opnd2p2>>29, 
+				    opnd2p2<<3);
+		}
+		if (Dbit29p2(opnd1p2)) {
+                        Twoword_add(opnd3p1, opnd3p2, opnd2p1<<2 | opnd2p2>>30, 
+				    opnd2p2<<2);
+		}
+		if (Dbit30p2(opnd1p2)) {
+                        Twoword_add(opnd3p1, opnd3p2, opnd2p1<<1 | opnd2p2>>31,
+				    opnd2p2<<1);
+		}
+		if (Dbit31p2(opnd1p2)) {
+                        Twoword_add(opnd3p1, opnd3p2, opnd2p1, opnd2p2);
+		}
+		Dbl_rightshiftby4(opnd1p1,opnd1p2);
+	}
+	if (Dbit3p1(opnd3p1)==0) {
+		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+	}
+	else {
+		/* result mantissa >= 2. */
+		dest_exponent++;
+	}
+	/* check for denormalized result */
+	while (Dbit3p1(opnd3p1)==0) {
+		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+		dest_exponent--;
+	}
+	/*
+	 * check for guard, sticky and inexact bits 
+	 */
+	stickybit |= Dallp2(opnd3p2) << 25;
+	guardbit = (Dallp2(opnd3p2) << 24) >> 31;
+	inexact = guardbit | stickybit;
+
+	/* align result mantissa */
+	Dbl_rightshiftby8(opnd3p1,opnd3p2);
+
+	/* 
+	 * round result 
+	 */
+	if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
+		Dbl_clear_signexponent(opnd3p1);
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Dbl_iszero_sign(resultp1)) 
+					Dbl_increment(opnd3p1,opnd3p2);
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) 
+					Dbl_increment(opnd3p1,opnd3p2);
+				break;
+			case ROUNDNEAREST:
+				if (guardbit) {
+			   	if (stickybit || Dbl_isone_lowmantissap2(opnd3p2))
+			      	Dbl_increment(opnd3p1,opnd3p2);
+				}
+		}
+		if (Dbl_isone_hidden(opnd3p1)) dest_exponent++;
+	}
+	Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+
+        /* 
+         * Test for overflow
+         */
+	if (dest_exponent >= DBL_INFINITY_EXPONENT) {
+                /* trap if OVERFLOWTRAP enabled */
+                if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+			Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			if (inexact) 
+			    if (Is_inexacttrap_enabled())
+				return (OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+			    else Set_inexactflag();
+			return (OVERFLOWEXCEPTION);
+                }
+		inexact = TRUE;
+		Set_overflowflag();
+                /* set result to infinity or largest number */
+		Dbl_setoverflow(resultp1,resultp2);
+	}
+        /* 
+         * Test for underflow
+         */
+	else if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+			Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			if (inexact) 
+			    if (Is_inexacttrap_enabled())
+				return (UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+			    else Set_inexactflag();
+			return (UNDERFLOWEXCEPTION);
+                }
+
+		/* Determine if should set underflow flag */
+		is_tiny = TRUE;
+		if (dest_exponent == 0 && inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Dbl_iszero_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+					if (Dbl_isone_hiddenoverflow(opnd3p1))
+                			    is_tiny = FALSE;
+					Dbl_decrement(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+					if (Dbl_isone_hiddenoverflow(opnd3p1))
+                			    is_tiny = FALSE;
+					Dbl_decrement(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Dbl_isone_lowmantissap2(opnd3p2))) {
+				      	Dbl_increment(opnd3p1,opnd3p2);
+					if (Dbl_isone_hiddenoverflow(opnd3p1))
+                			    is_tiny = FALSE;
+					Dbl_decrement(opnd3p1,opnd3p2);
+				}
+				break;
+			}
+		}
+
+		/*
+		 * denormalize result or set to signed zero
+		 */
+		stickybit = inexact;
+		Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit,
+		 stickybit,inexact);
+
+		/* return zero or smallest number */
+		if (inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Dbl_iszero_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) {
+					Dbl_increment(opnd3p1,opnd3p2);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Dbl_isone_lowmantissap2(opnd3p2))) {
+			      		Dbl_increment(opnd3p1,opnd3p2);
+				}
+				break;
+			}
+                	if (is_tiny) Set_underflowflag();
+		}
+		Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2);
+	}
+	else Dbl_set_exponent(resultp1,dest_exponent);
+	/* check for inexact */
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfrem.c linux/arch/parisc/math-emu/dfrem.c
--- linux.orig/arch/parisc/math-emu/dfrem.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfrem.c	2002-08-12 22:14:18.000000000 +0000
@@ -0,0 +1,297 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfrem.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double Precision Floating-point Remainder
+ *
+ *  External Interfaces:
+ *	dbl_frem(srcptr1,srcptr2,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ *  Double Precision Floating-point Remainder
+ */
+
+int
+dbl_frem (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2,
+	  dbl_floating_point * dstptr, unsigned int *status)
+{
+	register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2;
+	register unsigned int resultp1, resultp2;
+	register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
+	register boolean roundup = FALSE;
+
+	Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2);
+	Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2);
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if ((opnd1_exponent = Dbl_exponent(opnd1p1)) == DBL_INFINITY_EXPONENT) {
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			if (Dbl_isnotnan(opnd2p1,opnd2p2)) {
+				/* invalid since first operand is infinity */
+				if (Is_invalidtrap_enabled()) 
+                                	return(INVALIDEXCEPTION);
+                                Set_invalidflag();
+                                Dbl_makequietnan(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+                	/*
+                 	 * is NaN; signaling or quiet?
+                 	 */
+                	if (Dbl_isone_signaling(opnd1p1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Dbl_set_quiet(opnd1p1);
+                	}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd2p1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Dbl_set_quiet(opnd2p1);
+				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+                		return(NOEXCEPTION);
+			}
+                	/*
+                 	 * return quiet NaN
+                 	 */
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+                	return(NOEXCEPTION);
+		}
+	} 
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if ((opnd2_exponent = Dbl_exponent(opnd2p1)) == DBL_INFINITY_EXPONENT) {
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			/*
+			 * return first operand
+			 */
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+			return(NOEXCEPTION);
+		}
+                /*
+                 * is NaN; signaling or quiet?
+                 */
+                if (Dbl_isone_signaling(opnd2p1)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Dbl_set_quiet(opnd2p1);
+                }
+                /*
+                 * return quiet NaN
+                 */
+		Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+                return(NOEXCEPTION);
+	}
+	/*
+	 * check second operand for zero
+	 */
+	if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+		/* invalid since second operand is zero */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                Set_invalidflag();
+                Dbl_makequietnan(resultp1,resultp2);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+
+	/* 
+	 * get sign of result
+	 */
+	resultp1 = opnd1p1;  
+
+	/* 
+	 * check for denormalized operands
+	 */
+	if (opnd1_exponent == 0) {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* normalize, then continue */
+		opnd1_exponent = 1;
+		Dbl_normalize(opnd1p1,opnd1p2,opnd1_exponent);
+	}
+	else {
+		Dbl_clear_signexponent_set_hidden(opnd1p1);
+	}
+	if (opnd2_exponent == 0) {
+		/* normalize, then continue */
+		opnd2_exponent = 1;
+		Dbl_normalize(opnd2p1,opnd2p2,opnd2_exponent);
+	}
+	else {
+		Dbl_clear_signexponent_set_hidden(opnd2p1);
+	}
+
+	/* find result exponent and divide step loop count */
+	dest_exponent = opnd2_exponent - 1;
+	stepcount = opnd1_exponent - opnd2_exponent;
+
+	/*
+	 * check for opnd1/opnd2 < 1
+	 */
+	if (stepcount < 0) {
+		/*
+		 * check for opnd1/opnd2 > 1/2
+		 *
+		 * In this case n will round to 1, so 
+		 *    r = opnd1 - opnd2 
+		 */
+		if (stepcount == -1 && 
+		    Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+			/* set sign */
+			Dbl_allp1(resultp1) = ~Dbl_allp1(resultp1);
+			/* align opnd2 with opnd1 */
+			Dbl_leftshiftby1(opnd2p1,opnd2p2); 
+			Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,
+			 opnd2p1,opnd2p2);
+			/* now normalize */
+                	while (Dbl_iszero_hidden(opnd2p1)) {
+                        	Dbl_leftshiftby1(opnd2p1,opnd2p2);
+                        	dest_exponent--;
+			}
+			Dbl_set_exponentmantissa(resultp1,resultp2,opnd2p1,opnd2p2);
+			goto testforunderflow;
+		}
+		/*
+		 * opnd1/opnd2 <= 1/2
+		 *
+		 * In this case n will round to zero, so 
+		 *    r = opnd1
+		 */
+		Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
+		dest_exponent = opnd1_exponent;
+		goto testforunderflow;
+	}
+
+	/*
+	 * Generate result
+	 *
+	 * Do iterative subtract until remainder is less than operand 2.
+	 */
+	while (stepcount-- > 0 && (Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2))) {
+		if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+			Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
+		}
+		Dbl_leftshiftby1(opnd1p1,opnd1p2);
+	}
+	/*
+	 * Do last subtract, then determine which way to round if remainder 
+	 * is exactly 1/2 of opnd2 
+	 */
+	if (Dbl_isnotlessthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+		Dbl_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2,opnd1p1,opnd1p2);
+		roundup = TRUE;
+	}
+	if (stepcount > 0 || Dbl_iszero(opnd1p1,opnd1p2)) {
+		/* division is exact, remainder is zero */
+		Dbl_setzero_exponentmantissa(resultp1,resultp2);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+
+	/* 
+	 * Check for cases where opnd1/opnd2 < n 
+	 *
+	 * In this case the result's sign will be opposite that of
+	 * opnd1.  The mantissa also needs some correction.
+	 */
+	Dbl_leftshiftby1(opnd1p1,opnd1p2);
+	if (Dbl_isgreaterthan(opnd1p1,opnd1p2,opnd2p1,opnd2p2)) {
+		Dbl_invert_sign(resultp1);
+		Dbl_leftshiftby1(opnd2p1,opnd2p2);
+		Dbl_subtract(opnd2p1,opnd2p2,opnd1p1,opnd1p2,opnd1p1,opnd1p2);
+	}
+	/* check for remainder being exactly 1/2 of opnd2 */
+	else if (Dbl_isequal(opnd1p1,opnd1p2,opnd2p1,opnd2p2) && roundup) { 
+		Dbl_invert_sign(resultp1);
+	}
+
+	/* normalize result's mantissa */
+        while (Dbl_iszero_hidden(opnd1p1)) {
+                dest_exponent--;
+                Dbl_leftshiftby1(opnd1p1,opnd1p2);
+        }
+	Dbl_set_exponentmantissa(resultp1,resultp2,opnd1p1,opnd1p2);
+
+        /* 
+         * Test for underflow
+         */
+    testforunderflow:
+	if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl);
+			/* frem is always exact */
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(UNDERFLOWEXCEPTION);
+                }
+                /*
+                 * denormalize result or set to signed zero
+                 */
+                if (dest_exponent >= (1 - DBL_P)) {
+			Dbl_rightshift_exponentmantissa(resultp1,resultp2,
+			 1-dest_exponent);
+                }
+                else {
+			Dbl_setzero_exponentmantissa(resultp1,resultp2);
+		}
+	}
+	else Dbl_set_exponent(resultp1,dest_exponent);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfsqrt.c linux/arch/parisc/math-emu/dfsqrt.c
--- linux.orig/arch/parisc/math-emu/dfsqrt.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfsqrt.c	2002-08-12 22:14:22.000000000 +0000
@@ -0,0 +1,195 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfsqrt.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double Floating-point Square Root
+ *
+ *  External Interfaces:
+ *	dbl_fsqrt(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ *  Double Floating-point Square Root
+ */
+
+/*ARGSUSED*/
+unsigned int
+dbl_fsqrt(
+	    dbl_floating_point *srcptr,
+	    unsigned int *nullptr,
+	    dbl_floating_point *dstptr,
+	    unsigned int *status)
+{
+	register unsigned int srcp1, srcp2, resultp1, resultp2;
+	register unsigned int newbitp1, newbitp2, sump1, sump2;
+	register int src_exponent;
+	register boolean guardbit = FALSE, even_exponent;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+        /*
+         * check source operand for NaN or infinity
+         */
+        if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
+                /*
+                 * is signaling NaN?
+                 */
+                if (Dbl_isone_signaling(srcp1)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Dbl_set_quiet(srcp1);
+                }
+                /*
+                 * Return quiet NaN or positive infinity.
+		 *  Fall thru to negative test if negative infinity.
+                 */
+		if (Dbl_iszero_sign(srcp1) || 
+		    Dbl_isnotzero_mantissa(srcp1,srcp2)) {
+                	Dbl_copytoptr(srcp1,srcp2,dstptr);
+                	return(NOEXCEPTION);
+		}
+        }
+
+        /*
+         * check for zero source operand
+         */
+	if (Dbl_iszero_exponentmantissa(srcp1,srcp2)) {
+		Dbl_copytoptr(srcp1,srcp2,dstptr);
+		return(NOEXCEPTION);
+	}
+
+        /*
+         * check for negative source operand 
+         */
+	if (Dbl_isone_sign(srcp1)) {
+		/* trap if INVALIDTRAP enabled */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+		/* make NaN quiet */
+		Set_invalidflag();
+		Dbl_makequietnan(srcp1,srcp2);
+		Dbl_copytoptr(srcp1,srcp2,dstptr);
+		return(NOEXCEPTION);
+	}
+
+	/*
+	 * Generate result
+	 */
+	if (src_exponent > 0) {
+		even_exponent = Dbl_hidden(srcp1);
+		Dbl_clear_signexponent_set_hidden(srcp1);
+	}
+	else {
+		/* normalize operand */
+		Dbl_clear_signexponent(srcp1);
+		src_exponent++;
+		Dbl_normalize(srcp1,srcp2,src_exponent);
+		even_exponent = src_exponent & 1;
+	}
+	if (even_exponent) {
+		/* exponent is even */
+		/* Add comment here.  Explain why odd exponent needs correction */
+		Dbl_leftshiftby1(srcp1,srcp2);
+	}
+	/*
+	 * Add comment here.  Explain following algorithm.
+	 * 
+	 * Trust me, it works.
+	 *
+	 */
+	Dbl_setzero(resultp1,resultp2);
+	Dbl_allp1(newbitp1) = 1 << (DBL_P - 32);
+	Dbl_setzero_mantissap2(newbitp2);
+	while (Dbl_isnotzero(newbitp1,newbitp2) && Dbl_isnotzero(srcp1,srcp2)) {
+		Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,sump1,sump2);
+		if(Dbl_isnotgreaterthan(sump1,sump2,srcp1,srcp2)) {
+			Dbl_leftshiftby1(newbitp1,newbitp2);
+			/* update result */
+			Dbl_addition(resultp1,resultp2,newbitp1,newbitp2,
+			 resultp1,resultp2);  
+			Dbl_subtract(srcp1,srcp2,sump1,sump2,srcp1,srcp2);
+			Dbl_rightshiftby2(newbitp1,newbitp2);
+		}
+		else {
+			Dbl_rightshiftby1(newbitp1,newbitp2);
+		}
+		Dbl_leftshiftby1(srcp1,srcp2);
+	}
+	/* correct exponent for pre-shift */
+	if (even_exponent) {
+		Dbl_rightshiftby1(resultp1,resultp2);
+	}
+
+	/* check for inexact */
+	if (Dbl_isnotzero(srcp1,srcp2)) {
+		if (!even_exponent && Dbl_islessthan(resultp1,resultp2,srcp1,srcp2)) {
+			Dbl_increment(resultp1,resultp2);
+		}
+		guardbit = Dbl_lowmantissap2(resultp2);
+		Dbl_rightshiftby1(resultp1,resultp2);
+
+		/*  now round result  */
+		switch (Rounding_mode()) {
+		case ROUNDPLUS:
+		     Dbl_increment(resultp1,resultp2);
+		     break;
+		case ROUNDNEAREST:
+		     /* stickybit is always true, so guardbit 
+		      * is enough to determine rounding */
+		     if (guardbit) {
+			    Dbl_increment(resultp1,resultp2);
+		     }
+		     break;
+		}
+		/* increment result exponent by 1 if mantissa overflowed */
+		if (Dbl_isone_hiddenoverflow(resultp1)) src_exponent+=2;
+
+		if (Is_inexacttrap_enabled()) {
+			Dbl_set_exponent(resultp1,
+			 ((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	else {
+		Dbl_rightshiftby1(resultp1,resultp2);
+	}
+	Dbl_set_exponent(resultp1,((src_exponent-DBL_BIAS)>>1)+DBL_BIAS);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/dfsub.c linux/arch/parisc/math-emu/dfsub.c
--- linux.orig/arch/parisc/math-emu/dfsub.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/dfsub.c	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,526 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/dfsub.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double_subtract: subtract two double precision values.
+ *
+ *  External Interfaces:
+ *	dbl_fsub(leftptr, rightptr, dstptr, status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "dbl_float.h"
+
+/*
+ * Double_subtract: subtract two double precision values.
+ */
+int
+dbl_fsub(
+	    dbl_floating_point *leftptr,
+	    dbl_floating_point *rightptr,
+	    dbl_floating_point *dstptr,
+	    unsigned int *status)
+    {
+    register unsigned int signless_upper_left, signless_upper_right, save;
+    register unsigned int leftp1, leftp2, rightp1, rightp2, extent;
+    register unsigned int resultp1 = 0, resultp2 = 0;
+    
+    register int result_exponent, right_exponent, diff_exponent;
+    register int sign_save, jumpsize;
+    register boolean inexact = FALSE, underflowtrap;
+        
+    /* Create local copies of the numbers */
+    Dbl_copyfromptr(leftptr,leftp1,leftp2);
+    Dbl_copyfromptr(rightptr,rightp1,rightp2);
+
+    /* A zero "save" helps discover equal operands (for later),  *
+     * and is used in swapping operands (if needed).             */
+    Dbl_xortointp1(leftp1,rightp1,/*to*/save);
+
+    /*
+     * check first operand for NaN's or infinity
+     */
+    if ((result_exponent = Dbl_exponent(leftp1)) == DBL_INFINITY_EXPONENT)
+	{
+	if (Dbl_iszero_mantissa(leftp1,leftp2)) 
+	    {
+	    if (Dbl_isnotnan(rightp1,rightp2)) 
+		{
+		if (Dbl_isinfinity(rightp1,rightp2) && save==0) 
+		    {
+		    /* 
+		     * invalid since operands are same signed infinity's
+		     */
+		    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                    Set_invalidflag();
+                    Dbl_makequietnan(resultp1,resultp2);
+		    Dbl_copytoptr(resultp1,resultp2,dstptr);
+		    return(NOEXCEPTION);
+		    }
+		/*
+	 	 * return infinity
+	 	 */
+		Dbl_copytoptr(leftp1,leftp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    }
+	else 
+	    {
+            /*
+             * is NaN; signaling or quiet?
+             */
+            if (Dbl_isone_signaling(leftp1)) 
+		{
+               	/* trap if INVALIDTRAP enabled */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+        	/* make NaN quiet */
+        	Set_invalidflag();
+        	Dbl_set_quiet(leftp1);
+        	}
+	    /* 
+	     * is second operand a signaling NaN? 
+	     */
+	    else if (Dbl_is_signalingnan(rightp1)) 
+		{
+        	/* trap if INVALIDTRAP enabled */
+               	if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+		/* make NaN quiet */
+		Set_invalidflag();
+		Dbl_set_quiet(rightp1);
+		Dbl_copytoptr(rightp1,rightp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    /*
+ 	     * return quiet NaN
+ 	     */
+	    Dbl_copytoptr(leftp1,leftp2,dstptr);
+ 	    return(NOEXCEPTION);
+	    }
+	} /* End left NaN or Infinity processing */
+    /*
+     * check second operand for NaN's or infinity
+     */
+    if (Dbl_isinfinity_exponent(rightp1)) 
+	{
+	if (Dbl_iszero_mantissa(rightp1,rightp2)) 
+	    {
+	    /* return infinity */
+	    Dbl_invert_sign(rightp1);
+	    Dbl_copytoptr(rightp1,rightp2,dstptr);
+	    return(NOEXCEPTION);
+	    }
+        /*
+         * is NaN; signaling or quiet?
+         */
+        if (Dbl_isone_signaling(rightp1)) 
+	    {
+            /* trap if INVALIDTRAP enabled */
+	    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+	    /* make NaN quiet */
+	    Set_invalidflag();
+	    Dbl_set_quiet(rightp1);
+	    }
+	/*
+	 * return quiet NaN
+ 	 */
+	Dbl_copytoptr(rightp1,rightp2,dstptr);
+	return(NOEXCEPTION);
+    	} /* End right NaN or Infinity processing */
+
+    /* Invariant: Must be dealing with finite numbers */
+
+    /* Compare operands by removing the sign */
+    Dbl_copytoint_exponentmantissap1(leftp1,signless_upper_left);
+    Dbl_copytoint_exponentmantissap1(rightp1,signless_upper_right);
+
+    /* sign difference selects add or sub operation. */
+    if(Dbl_ismagnitudeless(leftp2,rightp2,signless_upper_left,signless_upper_right))
+	{
+	/* Set the left operand to the larger one by XOR swap *
+	 *  First finish the first word using "save"          */
+	Dbl_xorfromintp1(save,rightp1,/*to*/rightp1);
+	Dbl_xorfromintp1(save,leftp1,/*to*/leftp1);
+     	Dbl_swap_lower(leftp2,rightp2);
+	result_exponent = Dbl_exponent(leftp1);
+	Dbl_invert_sign(leftp1);
+	}
+    /* Invariant:  left is not smaller than right. */ 
+
+    if((right_exponent = Dbl_exponent(rightp1)) == 0)
+        {
+	/* Denormalized operands.  First look for zeroes */
+	if(Dbl_iszero_mantissa(rightp1,rightp2)) 
+	    {
+	    /* right is zero */
+	    if(Dbl_iszero_exponentmantissa(leftp1,leftp2))
+		{
+		/* Both operands are zeros */
+		Dbl_invert_sign(rightp1);
+		if(Is_rounding_mode(ROUNDMINUS))
+		    {
+		    Dbl_or_signs(leftp1,/*with*/rightp1);
+		    }
+		else
+		    {
+		    Dbl_and_signs(leftp1,/*with*/rightp1);
+		    }
+		}
+	    else 
+		{
+		/* Left is not a zero and must be the result.  Trapped
+		 * underflows are signaled if left is denormalized.  Result
+		 * is always exact. */
+		if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+		    {
+		    /* need to normalize results mantissa */
+	    	    sign_save = Dbl_signextendedsign(leftp1);
+		    Dbl_leftshiftby1(leftp1,leftp2);
+		    Dbl_normalize(leftp1,leftp2,result_exponent);
+		    Dbl_set_sign(leftp1,/*using*/sign_save);
+                    Dbl_setwrapped_exponent(leftp1,result_exponent,unfl);
+		    Dbl_copytoptr(leftp1,leftp2,dstptr);
+		    /* inexact = FALSE */
+		    return(UNDERFLOWEXCEPTION);
+		    }
+		}
+	    Dbl_copytoptr(leftp1,leftp2,dstptr);
+	    return(NOEXCEPTION);
+	    }
+
+	/* Neither are zeroes */
+	Dbl_clear_sign(rightp1);	/* Exponent is already cleared */
+	if(result_exponent == 0 )
+	    {
+	    /* Both operands are denormalized.  The result must be exact
+	     * and is simply calculated.  A sum could become normalized and a
+	     * difference could cancel to a true zero. */
+	    if( (/*signed*/int) save >= 0 )
+		{
+		Dbl_subtract(leftp1,leftp2,/*minus*/rightp1,rightp2,
+		 /*into*/resultp1,resultp2);
+		if(Dbl_iszero_mantissa(resultp1,resultp2))
+		    {
+		    if(Is_rounding_mode(ROUNDMINUS))
+			{
+			Dbl_setone_sign(resultp1);
+			}
+		    else
+			{
+			Dbl_setzero_sign(resultp1);
+			}
+		    Dbl_copytoptr(resultp1,resultp2,dstptr);
+		    return(NOEXCEPTION);
+		    }
+		}
+	    else
+		{
+		Dbl_addition(leftp1,leftp2,rightp1,rightp2,
+		 /*into*/resultp1,resultp2);
+		if(Dbl_isone_hidden(resultp1))
+		    {
+		    Dbl_copytoptr(resultp1,resultp2,dstptr);
+		    return(NOEXCEPTION);
+		    }
+		}
+	    if(Is_underflowtrap_enabled())
+		{
+		/* need to normalize result */
+	    	sign_save = Dbl_signextendedsign(resultp1);
+		Dbl_leftshiftby1(resultp1,resultp2);
+		Dbl_normalize(resultp1,resultp2,result_exponent);
+		Dbl_set_sign(resultp1,/*using*/sign_save);
+                Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		/* inexact = FALSE */
+		return(UNDERFLOWEXCEPTION);
+		}
+	    Dbl_copytoptr(resultp1,resultp2,dstptr);
+	    return(NOEXCEPTION);
+	    }
+	right_exponent = 1;	/* Set exponent to reflect different bias
+				 * with denomalized numbers. */
+	}
+    else
+	{
+	Dbl_clear_signexponent_set_hidden(rightp1);
+	}
+    Dbl_clear_exponent_set_hidden(leftp1);
+    diff_exponent = result_exponent - right_exponent;
+
+    /* 
+     * Special case alignment of operands that would force alignment 
+     * beyond the extent of the extension.  A further optimization
+     * could special case this but only reduces the path length for this
+     * infrequent case.
+     */
+    if(diff_exponent > DBL_THRESHOLD)
+	{
+	diff_exponent = DBL_THRESHOLD;
+	}
+    
+    /* Align right operand by shifting to right */
+    Dbl_right_align(/*operand*/rightp1,rightp2,/*shifted by*/diff_exponent,
+     /*and lower to*/extent);
+
+    /* Treat sum and difference of the operands separately. */
+    if( (/*signed*/int) save >= 0 )
+	{
+	/*
+	 * Difference of the two operands.  Their can be no overflow.  A
+	 * borrow can occur out of the hidden bit and force a post
+	 * normalization phase.
+	 */
+	Dbl_subtract_withextension(leftp1,leftp2,/*minus*/rightp1,rightp2,
+	 /*with*/extent,/*into*/resultp1,resultp2);
+	if(Dbl_iszero_hidden(resultp1))
+	    {
+	    /* Handle normalization */
+	    /* A straight foward algorithm would now shift the result
+	     * and extension left until the hidden bit becomes one.  Not
+	     * all of the extension bits need participate in the shift.
+	     * Only the two most significant bits (round and guard) are
+	     * needed.  If only a single shift is needed then the guard
+	     * bit becomes a significant low order bit and the extension
+	     * must participate in the rounding.  If more than a single 
+	     * shift is needed, then all bits to the right of the guard 
+	     * bit are zeros, and the guard bit may or may not be zero. */
+	    sign_save = Dbl_signextendedsign(resultp1);
+            Dbl_leftshiftby1_withextent(resultp1,resultp2,extent,resultp1,resultp2);
+
+            /* Need to check for a zero result.  The sign and exponent
+	     * fields have already been zeroed.  The more efficient test
+	     * of the full object can be used.
+	     */
+    	    if(Dbl_iszero(resultp1,resultp2))
+		/* Must have been "x-x" or "x+(-x)". */
+		{
+		if(Is_rounding_mode(ROUNDMINUS)) Dbl_setone_sign(resultp1);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    result_exponent--;
+	    /* Look to see if normalization is finished. */
+	    if(Dbl_isone_hidden(resultp1))
+		{
+		if(result_exponent==0)
+		    {
+		    /* Denormalized, exponent should be zero.  Left operand *
+		     * was normalized, so extent (guard, round) was zero    */
+		    goto underflow;
+		    }
+		else
+		    {
+		    /* No further normalization is needed. */
+		    Dbl_set_sign(resultp1,/*using*/sign_save);
+	    	    Ext_leftshiftby1(extent);
+		    goto round;
+		    }
+		}
+
+	    /* Check for denormalized, exponent should be zero.  Left    *
+	     * operand was normalized, so extent (guard, round) was zero */
+	    if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+	       result_exponent==0) goto underflow;
+
+	    /* Shift extension to complete one bit of normalization and
+	     * update exponent. */
+	    Ext_leftshiftby1(extent);
+
+	    /* Discover first one bit to determine shift amount.  Use a
+	     * modified binary search.  We have already shifted the result
+	     * one position right and still not found a one so the remainder
+	     * of the extension must be zero and simplifies rounding. */
+	    /* Scan bytes */
+	    while(Dbl_iszero_hiddenhigh7mantissa(resultp1))
+		{
+		Dbl_leftshiftby8(resultp1,resultp2);
+		if((result_exponent -= 8) <= 0  && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Now narrow it down to the nibble */
+	    if(Dbl_iszero_hiddenhigh3mantissa(resultp1))
+		{
+		/* The lower nibble contains the normalizing one */
+		Dbl_leftshiftby4(resultp1,resultp2);
+		if((result_exponent -= 4) <= 0 && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Select case were first bit is set (already normalized)
+	     * otherwise select the proper shift. */
+	    if((jumpsize = Dbl_hiddenhigh3mantissa(resultp1)) > 7)
+		{
+		/* Already normalized */
+		if(result_exponent <= 0) goto underflow;
+		Dbl_set_sign(resultp1,/*using*/sign_save);
+		Dbl_set_exponent(resultp1,/*using*/result_exponent);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+		}
+	    Dbl_sethigh4bits(resultp1,/*using*/sign_save);
+	    switch(jumpsize) 
+		{
+		case 1:
+		    {
+		    Dbl_leftshiftby3(resultp1,resultp2);
+		    result_exponent -= 3;
+		    break;
+		    }
+		case 2:
+		case 3:
+		    {
+		    Dbl_leftshiftby2(resultp1,resultp2);
+		    result_exponent -= 2;
+		    break;
+		    }
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		    {
+		    Dbl_leftshiftby1(resultp1,resultp2);
+		    result_exponent -= 1;
+		    break;
+		    }
+		}
+	    if(result_exponent > 0) 
+		{
+		Dbl_set_exponent(resultp1,/*using*/result_exponent);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);		/* Sign bit is already set */
+		}
+	    /* Fixup potential underflows */
+	  underflow:
+	    if(Is_underflowtrap_enabled())
+		{
+		Dbl_set_sign(resultp1,sign_save);
+                Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		/* inexact = FALSE */
+		return(UNDERFLOWEXCEPTION);
+		}
+	    /* 
+	     * Since we cannot get an inexact denormalized result,
+	     * we can now return.
+	     */
+	    Dbl_fix_overshift(resultp1,resultp2,(1-result_exponent),extent);
+	    Dbl_clear_signexponent(resultp1);
+	    Dbl_set_sign(resultp1,sign_save);
+	    Dbl_copytoptr(resultp1,resultp2,dstptr);
+	    return(NOEXCEPTION);
+	    } /* end if(hidden...)... */
+	/* Fall through and round */
+	} /* end if(save >= 0)... */
+    else 
+	{
+	/* Subtract magnitudes */
+	Dbl_addition(leftp1,leftp2,rightp1,rightp2,/*to*/resultp1,resultp2);
+	if(Dbl_isone_hiddenoverflow(resultp1))
+	    {
+	    /* Prenormalization required. */
+	    Dbl_rightshiftby1_withextent(resultp2,extent,extent);
+	    Dbl_arithrightshiftby1(resultp1,resultp2);
+	    result_exponent++;
+	    } /* end if hiddenoverflow... */
+	} /* end else ...subtract magnitudes... */
+    
+    /* Round the result.  If the extension is all zeros,then the result is
+     * exact.  Otherwise round in the correct direction.  No underflow is
+     * possible. If a postnormalization is necessary, then the mantissa is
+     * all zeros so no shift is needed. */
+  round:
+    if(Ext_isnotzero(extent))
+	{
+	inexact = TRUE;
+	switch(Rounding_mode())
+	    {
+	    case ROUNDNEAREST: /* The default. */
+	    if(Ext_isone_sign(extent))
+		{
+		/* at least 1/2 ulp */
+		if(Ext_isnotzero_lower(extent)  ||
+		  Dbl_isone_lowmantissap2(resultp2))
+		    {
+		    /* either exactly half way and odd or more than 1/2ulp */
+		    Dbl_increment(resultp1,resultp2);
+		    }
+		}
+	    break;
+
+	    case ROUNDPLUS:
+	    if(Dbl_iszero_sign(resultp1))
+		{
+		/* Round up positive results */
+		Dbl_increment(resultp1,resultp2);
+		}
+	    break;
+	    
+	    case ROUNDMINUS:
+	    if(Dbl_isone_sign(resultp1))
+		{
+		/* Round down negative results */
+		Dbl_increment(resultp1,resultp2);
+		}
+	    
+	    case ROUNDZERO:;
+	    /* truncate is simple */
+	    } /* end switch... */
+	if(Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+	}
+    if(result_exponent == DBL_INFINITY_EXPONENT)
+        {
+        /* Overflow */
+        if(Is_overflowtrap_enabled())
+	    {
+	    Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+	    Dbl_copytoptr(resultp1,resultp2,dstptr);
+	    if (inexact)
+	    if (Is_inexacttrap_enabled())
+		return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+		else Set_inexactflag();
+	    return(OVERFLOWEXCEPTION);
+	    }
+        else
+	    {
+	    inexact = TRUE;
+	    Set_overflowflag();
+	    Dbl_setoverflow(resultp1,resultp2);
+	    }
+	}
+    else Dbl_set_exponent(resultp1,result_exponent);
+    Dbl_copytoptr(resultp1,resultp2,dstptr);
+    if(inexact) 
+	if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+	else Set_inexactflag();
+    return(NOEXCEPTION);
+    }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/driver.c linux/arch/parisc/math-emu/driver.c
--- linux.orig/arch/parisc/math-emu/driver.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/driver.c	2002-08-12 22:14:17.000000000 +0000
@@ -0,0 +1,125 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ *  linux/arch/math-emu/driver.c.c
+ *
+ *	decodes and dispatches unimplemented FPU instructions
+ *
+ *  Copyright (C) 1999, 2000  Philipp Rumpf <prumpf@tux.org>
+ *  Copyright (C) 2001	      Hewlett-Packard <bame@debian.org>
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include "float.h"
+#include "math-emu.h"
+
+
+#define fptpos 31
+#define fpr1pos 10
+#define extru(r,pos,len) (((r) >> (31-(pos))) & (( 1 << (len)) - 1))
+
+#define FPUDEBUG 0
+
+/* Format of the floating-point exception registers. */
+struct exc_reg {
+	unsigned int exception : 6;
+	unsigned int ei : 26;
+};
+
+/* Macros for grabbing bits of the instruction format from the 'ei'
+   field above. */
+/* Major opcode 0c and 0e */
+#define FP0CE_UID(i) (((i) >> 6) & 3)
+#define FP0CE_CLASS(i) (((i) >> 9) & 3)
+#define FP0CE_SUBOP(i) (((i) >> 13) & 7)
+#define FP0CE_SUBOP1(i) (((i) >> 15) & 7) /* Class 1 subopcode */
+#define FP0C_FORMAT(i) (((i) >> 11) & 3)
+#define FP0E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 0c, uid 2 (performance monitoring) */
+#define FPPM_SUBOP(i) (((i) >> 9) & 0x1f)
+
+/* Major opcode 2e (fused operations).   */
+#define FP2E_SUBOP(i)  (((i) >> 5) & 1)
+#define FP2E_FORMAT(i) (((i) >> 11) & 1)
+
+/* Major opcode 26 (FMPYSUB) */
+/* Major opcode 06 (FMPYADD) */
+#define FPx6_FORMAT(i) ((i) & 0x1f)
+
+/* Flags and enable bits of the status word. */
+#define FPSW_FLAGS(w) ((w) >> 27)
+#define FPSW_ENABLE(w) ((w) & 0x1f)
+#define FPSW_V (1<<4)
+#define FPSW_Z (1<<3)
+#define FPSW_O (1<<2)
+#define FPSW_U (1<<1)
+#define FPSW_I (1<<0)
+
+/* Handle a floating point exception.  Return zero if the faulting
+   instruction can be completed successfully. */
+int
+handle_fpe(struct pt_regs *regs)
+{
+	extern void printbinary(unsigned long x, int nbits);
+	struct siginfo si;
+	unsigned int orig_sw, sw;
+	int signalcode;
+	/* need an intermediate copy of float regs because FPU emulation
+	 * code expects an artificial last entry which contains zero
+	 */
+	__u64 frcopy[33];
+
+	memcpy(frcopy, regs->fr, sizeof regs->fr);
+	frcopy[32] = 0;
+
+	memcpy(&orig_sw, frcopy, sizeof(orig_sw));
+
+	if (FPUDEBUG) {
+		printk(KERN_DEBUG "FP VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI ->\n   ");
+		printbinary(orig_sw, 32);
+		printk(KERN_DEBUG "\n");
+	}
+
+	signalcode = decode_fpu(frcopy, 0x666);
+
+	/* Status word = FR0L. */
+	memcpy(&sw, frcopy, sizeof(sw));
+	if (FPUDEBUG) {
+		printk(KERN_DEBUG "VZOUICxxxxCQCQCQCQCQCRMxxTDVZOUI decode_fpu returns %d|0x%x\n",
+			signalcode >> 24, signalcode & 0xffffff);
+		printbinary(sw, 32);
+		printk(KERN_DEBUG "\n");
+	}
+
+	memcpy(regs->fr, frcopy, sizeof regs->fr);
+	if (signalcode != 0) {
+	    si.si_signo = signalcode >> 24;
+	    si.si_errno = 0;
+	    si.si_code = signalcode & 0xffffff;
+	    si.si_addr = (void *) regs->iaoq[0];
+	    force_sig_info(si.si_signo, &si, current);
+	    return -1;
+	}
+
+	return signalcode ? -1 : 0;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvff.c linux/arch/parisc/math-emu/fcnvff.c
--- linux.orig/arch/parisc/math-emu/fcnvff.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvff.c	2002-08-12 22:14:09.000000000 +0000
@@ -0,0 +1,309 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvff.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Floating-point to Double Floating-point
+ *	Double Floating-point to Single Floating-point
+ *
+ *  External Interfaces:
+ *	dbl_to_sgl_fcnvff(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvff(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ *  Single Floating-point to Double Floating-point 
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvff(
+	    sgl_floating_point *srcptr,
+	    unsigned int *nullptr,
+	    dbl_floating_point *dstptr,
+	    unsigned int *status)
+{
+	register unsigned int src, resultp1, resultp2;
+	register int src_exponent;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src);
+	Dbl_allp1(resultp1) = Sgl_all(src);  /* set sign of result */
+	/* 
+ 	 * Test for NaN or infinity
+ 	 */
+	if (src_exponent == SGL_INFINITY_EXPONENT) {
+		/*
+		 * determine if NaN or infinity
+		 */
+		if (Sgl_iszero_mantissa(src)) {
+			/*
+			 * is infinity; want to return double infinity
+			 */
+			Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		else {
+			/* 
+			 * is NaN; signaling or quiet?
+			 */
+			if (Sgl_isone_signaling(src)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(INVALIDEXCEPTION);
+				/* make NaN quiet */
+				else {
+					Set_invalidflag();
+					Sgl_set_quiet(src);
+				}
+			}
+			/* 
+			 * NaN is quiet, return as double NaN 
+			 */
+			Dbl_setinfinity_exponent(resultp1);
+			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+	/* 
+ 	 * Test for zero or denormalized
+ 	 */
+	if (src_exponent == 0) {
+		/*
+		 * determine if zero or denormalized
+		 */
+		if (Sgl_isnotzero_mantissa(src)) {
+			/*
+			 * is denormalized; want to normalize
+			 */
+			Sgl_clear_signexponent(src);
+			Sgl_leftshiftby1(src);
+			Sgl_normalize(src,src_exponent);
+			Sgl_to_dbl_exponent(src_exponent,resultp1);
+			Sgl_to_dbl_mantissa(src,resultp1,resultp2);
+		}
+		else {
+			Dbl_setzero_exponentmantissa(resultp1,resultp2);
+		}
+		Dbl_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * No special cases, just complete the conversion
+	 */
+	Sgl_to_dbl_exponent(src_exponent, resultp1);
+	Sgl_to_dbl_mantissa(Sgl_mantissa(src), resultp1,resultp2);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Single Floating-point 
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvff(
+		    dbl_floating_point *srcptr,
+		    unsigned int *nullptr,
+		    sgl_floating_point *dstptr,
+		    unsigned int *status)
+{
+        register unsigned int srcp1, srcp2, result;
+        register int src_exponent, dest_exponent, dest_mantissa;
+        register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+	register boolean lsb_odd = FALSE;
+	boolean is_tiny;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+        src_exponent = Dbl_exponent(srcp1);
+	Sgl_all(result) = Dbl_allp1(srcp1);  /* set sign of result */
+        /* 
+         * Test for NaN or infinity
+         */
+        if (src_exponent == DBL_INFINITY_EXPONENT) {
+                /*
+                 * determine if NaN or infinity
+                 */
+                if (Dbl_iszero_mantissa(srcp1,srcp2)) {
+                        /*
+                         * is infinity; want to return single infinity
+                         */
+                        Sgl_setinfinity_exponentmantissa(result);
+                        *dstptr = result;
+                        return(NOEXCEPTION);
+                }
+                /* 
+                 * is NaN; signaling or quiet?
+                 */
+                if (Dbl_isone_signaling(srcp1)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        else {
+				Set_invalidflag();
+                        	/* make NaN quiet */
+                        	Dbl_set_quiet(srcp1);
+			}
+                }
+                /* 
+                 * NaN is quiet, return as single NaN 
+                 */
+                Sgl_setinfinity_exponent(result);
+		Sgl_set_mantissa(result,Dallp1(srcp1)<<3 | Dallp2(srcp2)>>29);
+		if (Sgl_iszero_mantissa(result)) Sgl_set_quiet(result);
+                *dstptr = result;
+                return(NOEXCEPTION);
+        }
+        /*
+         * Generate result
+         */
+        Dbl_to_sgl_exponent(src_exponent,dest_exponent);
+	if (dest_exponent > 0) {
+        	Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,guardbit, 
+		stickybit,lsb_odd);
+	}
+	else {
+		if (Dbl_iszero_exponentmantissa(srcp1,srcp2)){
+			Sgl_setzero_exponentmantissa(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+                if (Is_underflowtrap_enabled()) {
+			Dbl_to_sgl_mantissa(srcp1,srcp2,dest_mantissa,inexact,
+			guardbit,stickybit,lsb_odd);
+                }
+		else {
+			/* compute result, determine inexact info,
+			 * and set Underflowflag if appropriate
+			 */
+			Dbl_to_sgl_denormalized(srcp1,srcp2,dest_exponent,
+			dest_mantissa,inexact,guardbit,stickybit,lsb_odd,
+			is_tiny);
+		}
+	}
+        /* 
+         * Now round result if not exact
+         */
+        if (inexact) {
+                switch (Rounding_mode()) {
+                        case ROUNDPLUS: 
+                                if (Sgl_iszero_sign(result)) dest_mantissa++;
+                                break;
+                        case ROUNDMINUS: 
+                                if (Sgl_isone_sign(result)) dest_mantissa++;
+                                break;
+                        case ROUNDNEAREST:
+                                if (guardbit) {
+                                   if (stickybit || lsb_odd) dest_mantissa++;
+                                   }
+                }
+        }
+        Sgl_set_exponentmantissa(result,dest_mantissa);
+
+        /*
+         * check for mantissa overflow after rounding
+         */
+        if ((dest_exponent>0 || Is_underflowtrap_enabled()) && 
+	    Sgl_isone_hidden(result)) dest_exponent++;
+
+        /* 
+         * Test for overflow
+         */
+        if (dest_exponent >= SGL_INFINITY_EXPONENT) {
+                /* trap if OVERFLOWTRAP enabled */
+                if (Is_overflowtrap_enabled()) {
+                        /* 
+                         * Check for gross overflow
+                         */
+                        if (dest_exponent >= SGL_INFINITY_EXPONENT+SGL_WRAP) 
+                        	return(UNIMPLEMENTEDEXCEPTION);
+                        
+                        /*
+                         * Adjust bias of result
+                         */
+			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
+			*dstptr = result;
+			if (inexact) 
+			    if (Is_inexacttrap_enabled())
+				return(OVERFLOWEXCEPTION|INEXACTEXCEPTION);
+			    else Set_inexactflag();
+                        return(OVERFLOWEXCEPTION);
+                }
+                Set_overflowflag();
+		inexact = TRUE;
+		/* set result to infinity or largest number */
+		Sgl_setoverflow(result);
+        }
+        /* 
+         * Test for underflow
+         */
+        else if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /* 
+                         * Check for gross underflow
+                         */
+                        if (dest_exponent <= -(SGL_WRAP))
+                        	return(UNIMPLEMENTEDEXCEPTION);
+                        /*
+                         * Adjust bias of result
+                         */
+			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+			*dstptr = result;
+			if (inexact) 
+			    if (Is_inexacttrap_enabled())
+				return(UNDERFLOWEXCEPTION|INEXACTEXCEPTION);
+			    else Set_inexactflag();
+                        return(UNDERFLOWEXCEPTION);
+                }
+                 /* 
+                  * result is denormalized or signed zero
+                  */
+               if (inexact && is_tiny) Set_underflowflag();
+
+        }
+	else Sgl_set_exponent(result,dest_exponent);
+	*dstptr = result;
+        /* 
+         * Trap if inexact trap is enabled
+         */
+        if (inexact)
+        	if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+        	else Set_inexactflag();
+        return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvfu.c linux/arch/parisc/math-emu/fcnvfu.c
--- linux.orig/arch/parisc/math-emu/fcnvfu.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvfu.c	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,536 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvfu.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Floating-point to Unsigned Fixed-point Converts
+ *
+ *  External Interfaces:
+ *	dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
+ *	dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
+ *	sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/************************************************************************
+ *  Floating-point to Unsigned Fixed-point Converts			*
+ ************************************************************************/
+
+/*
+ *  Single Floating-point to Single Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfu(
+			sgl_floating_point *srcptr,
+			unsigned int *nullptr,
+			unsigned int *dstptr,
+			unsigned int *status)
+{
+	register unsigned int src, result;
+	register int src_exponent;
+	register boolean inexact = FALSE;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP + 1) {
+		if (Sgl_isone_sign(src)) {
+			result = 0;
+		} else {
+			result = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Sgl_isone_sign(src)) {
+			result = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+		Sgl_clear_signexponent_set_hidden(src);
+		Suint_from_sgl_mantissa(src,src_exponent,result);
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				result++;
+				break;
+			case ROUNDMINUS: /* never negative */
+				break;
+			case ROUNDNEAREST:
+				if (Sgl_isone_roundbit(src,src_exponent) &&
+				    (Sgl_isone_stickybit(src,src_exponent) ||
+				     (result & 1))) {
+			     		result++;
+				}
+				break;
+			}
+		}
+	} else {
+		result = 0;
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				if (Sgl_iszero_sign(src)) {
+					result++;
+				}
+				break;
+			case ROUNDMINUS:
+				if (Sgl_isone_sign(src)) {
+					result = 0;
+					if (Is_invalidtrap_enabled()) {
+						return(INVALIDEXCEPTION);
+					}
+					Set_invalidflag();
+					inexact = FALSE;
+				}
+				break;
+			case ROUNDNEAREST:
+				if (src_exponent == -1 &&
+				    Sgl_isnotzero_mantissa(src)) {
+					if (Sgl_isone_sign(src)) {
+						result = 0;
+						if (Is_invalidtrap_enabled()) {
+							return(INVALIDEXCEPTION);
+						}
+						Set_invalidflag();
+						inexact = FALSE;
+					}
+			      		else result++;
+				}
+				break;
+			}
+		}
+	}
+	*dstptr = result;
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Floating-point to Double Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfu(
+		    sgl_floating_point *srcptr,
+		    unsigned int *nullptr,
+		    dbl_unsigned *dstptr,
+		    unsigned int *status)
+{
+	register int src_exponent;
+	register unsigned int src, resultp1, resultp2;
+	register boolean inexact = FALSE;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP + 1) {
+		if (Sgl_isone_sign(src)) {
+			resultp1 = resultp2 = 0;
+		} else {
+			resultp1 = resultp2 = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+    		Duint_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Sgl_isone_sign(src)) {
+			resultp1 = resultp2 = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+    			Duint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		Sgl_clear_signexponent_set_hidden(src);
+		Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				Duint_increment(resultp1,resultp2);
+				break;
+			case ROUNDMINUS: /* never negative */
+				break;
+			case ROUNDNEAREST:
+				if (Sgl_isone_roundbit(src,src_exponent) &&
+				    (Sgl_isone_stickybit(src,src_exponent) || 
+				     Duint_isone_lowp2(resultp2))) {
+					Duint_increment(resultp1,resultp2);
+				}
+				break;
+			}
+		}
+	} else {
+		Duint_setzero(resultp1,resultp2);
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				if (Sgl_iszero_sign(src)) {
+					Duint_increment(resultp1,resultp2);
+				}
+				break;
+			case ROUNDMINUS:
+				if (Sgl_isone_sign(src)) {
+					resultp1 = resultp2 = 0;
+					if (Is_invalidtrap_enabled()) {
+						return(INVALIDEXCEPTION);
+					}
+					Set_invalidflag();
+					inexact = FALSE;
+				}
+				break;
+			case ROUNDNEAREST:
+				if (src_exponent == -1 &&
+				    Sgl_isnotzero_mantissa(src)) {
+					if (Sgl_isone_sign(src)) {
+						resultp1 = 0;
+						resultp2 = 0;
+						if (Is_invalidtrap_enabled()) {
+							return(INVALIDEXCEPTION);
+						}
+						Set_invalidflag();
+						inexact = FALSE;
+					}
+					else Duint_increment(resultp1,resultp2);
+				}
+			}
+		}
+	}
+	Duint_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Single Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
+		   unsigned int *dstptr, unsigned int *status)
+{
+	register unsigned int srcp1, srcp2, result;
+	register int src_exponent;
+	register boolean inexact = FALSE;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP + 1) {
+		if (Dbl_isone_sign(srcp1)) {
+			result = 0;
+		} else {
+			result = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Dbl_isone_sign(srcp1)) {
+			result = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+		Dbl_clear_signexponent_set_hidden(srcp1);
+		Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     result++;
+			     break;
+			case ROUNDMINUS: /* never negative */
+			     break;
+			case ROUNDNEAREST:
+			     if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
+				(Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
+				 result&1))
+				   result++;
+			     break;
+			}
+			/* check for overflow */
+			if (result == 0) {
+				result = 0xffffffff;
+				if (Is_invalidtrap_enabled()) {
+					return(INVALIDEXCEPTION);
+				}
+				Set_invalidflag();
+				*dstptr = result;
+				return(NOEXCEPTION);
+			}
+		}
+	} else {
+		result = 0;
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				if (Dbl_iszero_sign(srcp1)) result++;
+				break;
+			case ROUNDMINUS:
+				if (Dbl_isone_sign(srcp1)) {
+					result = 0;
+					if (Is_invalidtrap_enabled()) {
+						return(INVALIDEXCEPTION);
+					}
+					Set_invalidflag();
+					inexact = FALSE;
+				}
+				break;
+			case ROUNDNEAREST:
+				if (src_exponent == -1 &&
+				    Dbl_isnotzero_mantissa(srcp1,srcp2))
+					if (Dbl_isone_sign(srcp1)) {
+						result = 0;
+						if (Is_invalidtrap_enabled()) {
+							return(INVALIDEXCEPTION);
+						}
+						Set_invalidflag();
+						inexact = FALSE;
+					}
+					else result++;
+			}
+		}
+	}
+	*dstptr = result;
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Double Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
+		   dbl_unsigned * dstptr, unsigned int *status)
+{
+	register int src_exponent;
+	register unsigned int srcp1, srcp2, resultp1, resultp2;
+	register boolean inexact = FALSE;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP + 1) {
+		if (Dbl_isone_sign(srcp1)) {
+			resultp1 = resultp2 = 0;
+		} else {
+			resultp1 = resultp2 = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+    		Duint_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+ 
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Dbl_isone_sign(srcp1)) {
+			resultp1 = resultp2 = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+    			Duint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		Dbl_clear_signexponent_set_hidden(srcp1);
+		Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
+		  resultp2);
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				Duint_increment(resultp1,resultp2);
+				break;
+			case ROUNDMINUS: /* never negative */
+				break;
+			case ROUNDNEAREST:
+				if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+				  if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
+				     Duint_isone_lowp2(resultp2))
+					Duint_increment(resultp1,resultp2);
+			} 
+		}
+	} else {
+		Duint_setzero(resultp1,resultp2);
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				if (Dbl_iszero_sign(srcp1)) {
+					Duint_increment(resultp1,resultp2);
+				}
+				break;
+			case ROUNDMINUS:
+				if (Dbl_isone_sign(srcp1)) {
+					resultp1 = resultp2 = 0;
+					if (Is_invalidtrap_enabled()) {
+						return(INVALIDEXCEPTION);
+					}
+					Set_invalidflag();
+					inexact = FALSE;
+				}
+				break;
+			case ROUNDNEAREST:
+				if (src_exponent == -1 &&
+				    Dbl_isnotzero_mantissa(srcp1,srcp2))
+					if (Dbl_iszero_sign(srcp1)) {
+						Duint_increment(resultp1,resultp2);
+					} else {
+						resultp1 = 0;
+						resultp2 = 0;
+						if (Is_invalidtrap_enabled()) {
+							return(INVALIDEXCEPTION);
+						}
+						Set_invalidflag();
+						inexact = FALSE;
+					}
+			}
+		}
+	}
+	Duint_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvfut.c linux/arch/parisc/math-emu/fcnvfut.c
--- linux.orig/arch/parisc/math-emu/fcnvfut.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvfut.c	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,332 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvfut.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Floating-point to Unsigned Fixed-point Converts with Truncation
+ *
+ *  External Interfaces:
+ *	dbl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
+ *	dbl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvfut(srcptr,nullptr,dstptr,status)
+ *	sgl_to_sgl_fcnvfut(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/************************************************************************
+ *  Floating-point to Unsigned Fixed-point Converts with Truncation	*
+ ************************************************************************/
+
+/*
+ *  Convert single floating-point to single fixed-point format
+ *  with truncated result
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
+		    unsigned int *dstptr, unsigned int *status)
+{
+	register unsigned int src, result;
+	register int src_exponent;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP + 1) {
+		if (Sgl_isone_sign(src)) {
+			result = 0;
+		} else {
+			result = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Sgl_isone_sign(src)) {
+			result = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+		Sgl_clear_signexponent_set_hidden(src);
+		Suint_from_sgl_mantissa(src,src_exponent,result);
+		*dstptr = result;
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		*dstptr = 0;
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Floating-point to Double Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfut (sgl_floating_point * srcptr, unsigned int *nullptr,
+		    dbl_unsigned * dstptr, unsigned int *status)
+{
+	register int src_exponent;
+	register unsigned int src, resultp1, resultp2;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP + 1) {
+		if (Sgl_isone_sign(src)) {
+			resultp1 = resultp2 = 0;
+		} else {
+			resultp1 = resultp2 = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+    		Duint_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Sgl_isone_sign(src)) {
+			resultp1 = resultp2 = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+    			Duint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		Sgl_clear_signexponent_set_hidden(src);
+		Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
+		Duint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		Duint_setzero(resultp1,resultp2);
+		Duint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Single Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
+		    unsigned int *dstptr, unsigned int *status)
+{
+	register unsigned int srcp1, srcp2, result;
+	register int src_exponent;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP + 1) {
+		if (Dbl_isone_sign(srcp1)) {
+			result = 0;
+		} else {
+			result = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Dbl_isone_sign(srcp1)) {
+			result = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+		Dbl_clear_signexponent_set_hidden(srcp1);
+		Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
+		*dstptr = result;
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		*dstptr = 0;
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Double Unsigned Fixed 
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfut (dbl_floating_point * srcptr, unsigned int *nullptr,
+		    dbl_unsigned * dstptr, unsigned int *status)
+{
+	register int src_exponent;
+	register unsigned int srcp1, srcp2, resultp1, resultp2;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP + 1) {
+		if (Dbl_isone_sign(srcp1)) {
+			resultp1 = resultp2 = 0;
+		} else {
+			resultp1 = resultp2 = 0xffffffff;
+		}
+		if (Is_invalidtrap_enabled()) {
+			return(INVALIDEXCEPTION);
+		}
+		Set_invalidflag();
+    		Duint_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		/* 
+		 * Check sign.
+		 * If negative, trap unimplemented.
+		 */
+		if (Dbl_isone_sign(srcp1)) {
+			resultp1 = resultp2 = 0;
+			if (Is_invalidtrap_enabled()) {
+				return(INVALIDEXCEPTION);
+			}
+			Set_invalidflag();
+    			Duint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		Dbl_clear_signexponent_set_hidden(srcp1);
+		Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,
+		  resultp1,resultp2);
+		Duint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		Duint_setzero(resultp1,resultp2);
+		Duint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvfx.c linux/arch/parisc/math-emu/fcnvfx.c
--- linux.orig/arch/parisc/math-emu/fcnvfx.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvfx.c	2002-08-12 22:14:04.000000000 +0000
@@ -0,0 +1,501 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvfx.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Floating-point to Single Fixed-point
+ *	Single Floating-point to Double Fixed-point 
+ *	Double Floating-point to Single Fixed-point 
+ *	Double Floating-point to Double Fixed-point 
+ *
+ *  External Interfaces:
+ *	dbl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
+ *	dbl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvfx(srcptr,nullptr,dstptr,status)
+ *	sgl_to_sgl_fcnvfx(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ *  Single Floating-point to Single Fixed-point 
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfx(
+		    sgl_floating_point *srcptr,
+		    sgl_floating_point *nullptr,
+		    int *dstptr,
+		    sgl_floating_point *status)
+{
+	register unsigned int src, temp;
+	register int src_exponent, result;
+	register boolean inexact = FALSE;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP) {
+		/* check for MININT */
+		if ((src_exponent > SGL_FX_MAX_EXP + 1) || 
+		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+                        if (Sgl_iszero_sign(src)) result = 0x7fffffff;
+                        else result = 0x80000000; 
+
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+       		}
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		temp = src;
+		Sgl_clear_signexponent_set_hidden(temp);
+		Int_from_sgl_mantissa(temp,src_exponent);
+		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
+		else result = Sgl_all(temp);
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_fix(src,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     if (Sgl_iszero_sign(src)) result++;
+			     break;
+			case ROUNDMINUS:
+			     if (Sgl_isone_sign(src)) result--;
+			     break;
+			case ROUNDNEAREST:
+			     if (Sgl_isone_roundbit(src,src_exponent)) {
+			        if (Sgl_isone_stickybit(src,src_exponent) 
+				|| (Sgl_isone_lowmantissa(temp)))
+			           if (Sgl_iszero_sign(src)) result++;
+			           else result--;
+			     }
+			} 
+		}
+	}
+	else {
+		result = 0;
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     if (Sgl_iszero_sign(src)) result++;
+			     break;
+			case ROUNDMINUS:
+			     if (Sgl_isone_sign(src)) result--;
+			     break;
+			case ROUNDNEAREST:
+			     if (src_exponent == -1)
+			        if (Sgl_isnotzero_mantissa(src))
+			           if (Sgl_iszero_sign(src)) result++;
+			           else result--;
+			} 
+		}
+	}
+	*dstptr = result;
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Floating-point to Double Fixed-point 
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfx(
+		sgl_floating_point *srcptr,
+		unsigned int *nullptr,
+		dbl_integer *dstptr,
+		unsigned int *status)
+{
+	register int src_exponent, resultp1;
+	register unsigned int src, temp, resultp2;
+	register boolean inexact = FALSE;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP) {
+		/* check for MININT */
+		if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
+		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+                        if (Sgl_iszero_sign(src)) {
+                              resultp1 = 0x7fffffff;
+			      resultp2 = 0xffffffff;
+			}
+                        else {
+			    resultp1 = 0x80000000; 
+			    resultp2 = 0;
+			}
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+    		        Dint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		Dint_set_minint(resultp1,resultp2);
+		Dint_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		temp = src;
+		Sgl_clear_signexponent_set_hidden(temp);
+		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
+		if (Sgl_isone_sign(src)) {
+			Dint_setone_sign(resultp1,resultp2);
+		}
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_fix(src,src_exponent)) {
+			inexact = TRUE;
+                        /*  round result  */
+                        switch (Rounding_mode()) {
+                        case ROUNDPLUS:
+                             if (Sgl_iszero_sign(src)) {
+				Dint_increment(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDMINUS:
+                             if (Sgl_isone_sign(src)) {
+				Dint_decrement(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDNEAREST:
+                             if (Sgl_isone_roundbit(src,src_exponent))
+                                if (Sgl_isone_stickybit(src,src_exponent) || 
+				(Dint_isone_lowp2(resultp2)))
+				   if (Sgl_iszero_sign(src)) {
+				      Dint_increment(resultp1,resultp2);
+				   }
+                                   else {
+				      Dint_decrement(resultp1,resultp2);
+				   }
+                        }
+                }
+        }
+	else {
+		Dint_setzero(resultp1,resultp2);
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			inexact = TRUE;
+                        /*  round result  */
+                        switch (Rounding_mode()) {
+                        case ROUNDPLUS:
+                             if (Sgl_iszero_sign(src)) {
+				Dint_increment(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDMINUS:
+                             if (Sgl_isone_sign(src)) {
+				Dint_decrement(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDNEAREST:
+                             if (src_exponent == -1)
+                                if (Sgl_isnotzero_mantissa(src))
+                                   if (Sgl_iszero_sign(src)) {
+				      Dint_increment(resultp1,resultp2);
+				   }
+                                   else {
+				      Dint_decrement(resultp1,resultp2);
+				   }
+			}
+		}
+	}
+	Dint_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Single Fixed-point 
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfx(
+		    dbl_floating_point *srcptr,
+		    unsigned int *nullptr,
+		    int *dstptr,
+		    unsigned int *status)
+{
+	register unsigned int srcp1,srcp2, tempp1,tempp2;
+	register int src_exponent, result;
+	register boolean inexact = FALSE;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP) {
+		/* check for MININT */
+		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
+                        if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
+                        else result = 0x80000000; 
+
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		tempp1 = srcp1;
+		tempp2 = srcp2;
+		Dbl_clear_signexponent_set_hidden(tempp1);
+		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
+		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
+			result = -Dbl_allp1(tempp1);
+		else result = Dbl_allp1(tempp1);
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+                        inexact = TRUE;
+                        /*  round result  */
+                        switch (Rounding_mode()) {
+                        case ROUNDPLUS:
+                             if (Dbl_iszero_sign(srcp1)) result++;
+                             break;
+                        case ROUNDMINUS:
+                             if (Dbl_isone_sign(srcp1)) result--;
+                             break;
+                        case ROUNDNEAREST:
+                             if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+                                if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
+				(Dbl_isone_lowmantissap1(tempp1)))
+                                   if (Dbl_iszero_sign(srcp1)) result++;
+                                   else result--;
+                        } 
+			/* check for overflow */
+			if ((Dbl_iszero_sign(srcp1) && result < 0) ||
+			    (Dbl_isone_sign(srcp1) && result > 0)) {
+			        
+                          if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
+                          else result = 0x80000000; 
+
+	                  if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                          }
+                          Set_invalidflag();
+			  *dstptr = result;
+			  return(NOEXCEPTION);
+			}
+                }
+	}
+	else {
+		result = 0;
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+                        inexact = TRUE;
+                        /*  round result  */
+                        switch (Rounding_mode()) {
+                        case ROUNDPLUS:
+                             if (Dbl_iszero_sign(srcp1)) result++;
+                             break;
+                        case ROUNDMINUS:
+                             if (Dbl_isone_sign(srcp1)) result--;
+                             break;
+                        case ROUNDNEAREST:
+                             if (src_exponent == -1)
+                                if (Dbl_isnotzero_mantissa(srcp1,srcp2))
+                                   if (Dbl_iszero_sign(srcp1)) result++;
+                                   else result--;
+			}
+                }
+	}
+	*dstptr = result;
+        if (inexact) {
+                if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+        }
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Double Fixed-point 
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfx(
+		    dbl_floating_point *srcptr,
+		    unsigned int *nullptr,
+		    dbl_integer *dstptr,
+		    unsigned int *status)
+{
+	register int src_exponent, resultp1;
+	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
+	register boolean inexact = FALSE;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP) {
+		/* check for MININT */
+		if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
+		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
+                        if (Dbl_iszero_sign(srcp1)) {
+                              resultp1 = 0x7fffffff;
+			      resultp2 = 0xffffffff;
+			}
+                        else {
+			    resultp1 = 0x80000000; 
+			    resultp2 = 0;
+			}
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+    		        Dint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+ 
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		tempp1 = srcp1;
+		tempp2 = srcp2;
+		Dbl_clear_signexponent_set_hidden(tempp1);
+		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,resultp1,
+		resultp2);
+		if (Dbl_isone_sign(srcp1)) {
+			Dint_setone_sign(resultp1,resultp2);
+		}
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+                        inexact = TRUE;
+                        /*  round result  */
+                        switch (Rounding_mode()) {
+                        case ROUNDPLUS:
+                             if (Dbl_iszero_sign(srcp1)) {
+				Dint_increment(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDMINUS:
+                             if (Dbl_isone_sign(srcp1)) {
+				Dint_decrement(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDNEAREST:
+                             if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+                                if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
+				(Dint_isone_lowp2(resultp2)))
+                                   if (Dbl_iszero_sign(srcp1)) {
+				      Dint_increment(resultp1,resultp2);
+				   }
+                                   else {
+				      Dint_decrement(resultp1,resultp2);
+				   }
+                        } 
+                }
+	}
+	else {
+		Dint_setzero(resultp1,resultp2);
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+                        inexact = TRUE;
+                        /*  round result  */
+                        switch (Rounding_mode()) {
+                        case ROUNDPLUS:
+                             if (Dbl_iszero_sign(srcp1)) {
+				Dint_increment(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDMINUS:
+                             if (Dbl_isone_sign(srcp1)) {
+				Dint_decrement(resultp1,resultp2);
+			     }
+                             break;
+                        case ROUNDNEAREST:
+                             if (src_exponent == -1)
+                                if (Dbl_isnotzero_mantissa(srcp1,srcp2))
+                                   if (Dbl_iszero_sign(srcp1)) {
+				      Dint_increment(resultp1,resultp2);
+				   }
+                                   else {
+				      Dint_decrement(resultp1,resultp2);
+				   }
+			}
+                }
+	}
+	Dint_copytoptr(resultp1,resultp2,dstptr);
+        if (inexact) {
+                if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+        	else Set_inexactflag();
+        }
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvfxt.c linux/arch/parisc/math-emu/fcnvfxt.c
--- linux.orig/arch/parisc/math-emu/fcnvfxt.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvfxt.c	2002-08-12 22:14:05.000000000 +0000
@@ -0,0 +1,328 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvfxt.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Floating-point to Single Fixed-point /w truncated result
+ *	Single Floating-point to Double Fixed-point /w truncated result
+ *	Double Floating-point to Single Fixed-point /w truncated result
+ *	Double Floating-point to Double Fixed-point /w truncated result
+ *
+ *  External Interfaces:
+ *	dbl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ *	dbl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ *	sgl_to_sgl_fcnvfxt(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ *  Convert single floating-point to single fixed-point format
+ *  with truncated result
+ */
+/*ARGSUSED*/
+int
+sgl_to_sgl_fcnvfxt(
+		    sgl_floating_point *srcptr,
+		    unsigned int *nullptr,
+		    int *dstptr,
+		    unsigned int *status)
+{
+	register unsigned int src, temp;
+	register int src_exponent, result;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP) {
+		/* check for MININT */
+		if ((src_exponent > SGL_FX_MAX_EXP + 1) || 
+		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+                        if (Sgl_iszero_sign(src)) result = 0x7fffffff;
+                        else result = 0x80000000; 
+
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		temp = src;
+		Sgl_clear_signexponent_set_hidden(temp);
+		Int_from_sgl_mantissa(temp,src_exponent);
+		if (Sgl_isone_sign(src))  result = -Sgl_all(temp);
+		else result = Sgl_all(temp);
+		*dstptr = result;
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_fix(src,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		*dstptr = 0;
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Floating-point to Double Fixed-point 
+ */
+/*ARGSUSED*/
+int
+sgl_to_dbl_fcnvfxt(
+		    sgl_floating_point *srcptr,
+		    unsigned int *nullptr,
+		    dbl_integer *dstptr,
+		    unsigned int *status)
+{
+	register int src_exponent, resultp1;
+	register unsigned int src, temp, resultp2;
+
+	src = *srcptr;
+	src_exponent = Sgl_exponent(src) - SGL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP) {
+		/* check for MININT */
+		if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
+		Sgl_isnotzero_mantissa(src) || Sgl_iszero_sign(src)) {
+                        if (Sgl_iszero_sign(src)) {
+                              resultp1 = 0x7fffffff;
+			      resultp2 = 0xffffffff;
+			}
+                        else {
+			    resultp1 = 0x80000000; 
+			    resultp2 = 0;
+			}
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+    		        Dint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+		Dint_set_minint(resultp1,resultp2);
+		Dint_copytoptr(resultp1,resultp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		temp = src;
+		Sgl_clear_signexponent_set_hidden(temp);
+		Dint_from_sgl_mantissa(temp,src_exponent,resultp1,resultp2);
+		if (Sgl_isone_sign(src)) {
+			Dint_setone_sign(resultp1,resultp2);
+		}
+		Dint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Sgl_isinexact_to_fix(src,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		Dint_setzero(resultp1,resultp2);
+		Dint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Single Fixed-point 
+ */
+/*ARGSUSED*/
+int
+dbl_to_sgl_fcnvfxt(
+			dbl_floating_point *srcptr,
+			unsigned int *nullptr,
+			int *dstptr,
+			unsigned int *status)
+{
+	register unsigned int srcp1, srcp2, tempp1, tempp2;
+	register int src_exponent, result;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > SGL_FX_MAX_EXP) {
+		/* check for MININT */
+		if (Dbl_isoverflow_to_int(src_exponent,srcp1,srcp2)) {
+                        if (Dbl_iszero_sign(srcp1)) result = 0x7fffffff;
+                        else result = 0x80000000; 
+
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		tempp1 = srcp1;
+		tempp2 = srcp2;
+		Dbl_clear_signexponent_set_hidden(tempp1);
+		Int_from_dbl_mantissa(tempp1,tempp2,src_exponent);
+		if (Dbl_isone_sign(srcp1) && (src_exponent <= SGL_FX_MAX_EXP))
+			result = -Dbl_allp1(tempp1);
+		else result = Dbl_allp1(tempp1);
+		*dstptr = result;
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		*dstptr = 0;
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point to Double Fixed-point 
+ */
+/*ARGSUSED*/
+int
+dbl_to_dbl_fcnvfxt(
+			dbl_floating_point *srcptr,
+			unsigned int *nullptr,
+			dbl_integer *dstptr,
+			unsigned int *status)
+{
+	register int src_exponent, resultp1;
+	register unsigned int srcp1, srcp2, tempp1, tempp2, resultp2;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
+
+	/* 
+	 * Test for overflow
+	 */
+	if (src_exponent > DBL_FX_MAX_EXP) {
+		/* check for MININT */
+		if ((src_exponent > DBL_FX_MAX_EXP + 1) || 
+		Dbl_isnotzero_mantissa(srcp1,srcp2) || Dbl_iszero_sign(srcp1)) {
+                        if (Dbl_iszero_sign(srcp1)) {
+                              resultp1 = 0x7fffffff;
+			      resultp2 = 0xffffffff;
+			}
+                        else {
+			    resultp1 = 0x80000000; 
+			    resultp2 = 0;
+			}
+	                if (Is_invalidtrap_enabled()) {
+                            return(INVALIDEXCEPTION);
+                        }
+                        Set_invalidflag();
+    		        Dint_copytoptr(resultp1,resultp2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		tempp1 = srcp1;
+		tempp2 = srcp2;
+		Dbl_clear_signexponent_set_hidden(tempp1);
+		Dint_from_dbl_mantissa(tempp1,tempp2,src_exponent,
+		resultp1,resultp2);
+		if (Dbl_isone_sign(srcp1)) {
+			Dint_setone_sign(resultp1,resultp2);
+		}
+		Dint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	else {
+		Dint_setzero(resultp1,resultp2);
+		Dint_copytoptr(resultp1,resultp2,dstptr);
+
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+			else Set_inexactflag();
+		}
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvuf.c linux/arch/parisc/math-emu/fcnvuf.c
--- linux.orig/arch/parisc/math-emu/fcnvuf.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvuf.c	2002-08-12 22:14:15.000000000 +0000
@@ -0,0 +1,318 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvuf.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Fixed point to Floating-point Converts
+ *
+ *  External Interfaces:
+ *	dbl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
+ *	dbl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvuf(srcptr,nullptr,dstptr,status)
+ *	sgl_to_sgl_fcnvuf(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/************************************************************************
+ *  Fixed point to Floating-point Converts				*
+ ************************************************************************/
+
+/*
+ *  Convert Single Unsigned Fixed to Single Floating-point format
+ */
+
+int
+sgl_to_sgl_fcnvuf(
+			unsigned int *srcptr,
+			unsigned int *nullptr,
+			sgl_floating_point *dstptr,
+			unsigned int *status)
+{
+	register unsigned int src, result = 0;
+	register int dst_exponent;
+
+	src = *srcptr;
+
+	/* Check for zero */ 
+	if (src == 0) { 
+	       	Sgl_setzero(result); 
+		*dstptr = result;
+	       	return(NOEXCEPTION); 
+	} 
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	/*
+	 * Check word for most significant bit set.  Returns
+	 * a value in dst_exponent indicating the bit position,
+	 * between -1 and 30.
+	 */
+	Find_ms_one_bit(src,dst_exponent);
+	/*  left justify source, with msb at bit position 0  */
+	src <<= dst_exponent+1;
+	Sgl_set_mantissa(result, src >> SGL_EXP_LENGTH);
+	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
+
+	/* check for inexact */
+	if (Suint_isinexact_to_sgl(src)) {
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				Sgl_increment(result);
+				break;
+			case ROUNDMINUS: /* never negative */
+				break;
+			case ROUNDNEAREST:
+				Sgl_roundnearest_from_suint(src,result);
+				break;
+		}
+		if (Is_inexacttrap_enabled()) {
+			*dstptr = result;
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	*dstptr = result;
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Unsigned Fixed to Double Floating-point 
+ */
+
+int
+sgl_to_dbl_fcnvuf(
+			unsigned int *srcptr,
+			unsigned int *nullptr,
+			dbl_floating_point *dstptr,
+			unsigned int *status)
+{
+	register int dst_exponent;
+	register unsigned int src, resultp1 = 0, resultp2 = 0;
+
+	src = *srcptr;
+
+	/* Check for zero */
+	if (src == 0) {
+	       	Dbl_setzero(resultp1,resultp2);
+	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	       	return(NOEXCEPTION);
+	}
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	/*
+	 * Check word for most significant bit set.  Returns
+	 * a value in dst_exponent indicating the bit position,
+	 * between -1 and 30.
+	 */
+	Find_ms_one_bit(src,dst_exponent);
+	/*  left justify source, with msb at bit position 0  */
+	src <<= dst_exponent+1;
+	Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH);
+	Dbl_set_mantissap2(resultp2, src << (32-DBL_EXP_LENGTH));
+	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Unsigned Fixed to Single Floating-point 
+ */
+
+int
+dbl_to_sgl_fcnvuf(
+			dbl_unsigned *srcptr,
+			unsigned int *nullptr,
+			sgl_floating_point *dstptr,
+			unsigned int *status)
+{
+	int dst_exponent;
+	unsigned int srcp1, srcp2, result = 0;
+
+	Duint_copyfromptr(srcptr,srcp1,srcp2);
+
+	/* Check for zero */
+	if (srcp1 == 0 && srcp2 == 0) {
+	       	Sgl_setzero(result);
+	       	*dstptr = result;
+	       	return(NOEXCEPTION);
+	}
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	if (srcp1 == 0) {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 */
+		Find_ms_one_bit(srcp2,dst_exponent);
+		/*  left justify source, with msb at bit position 0  */
+		srcp1 = srcp2 << dst_exponent+1;    
+		srcp2 = 0;
+		/*
+		 *  since msb set is in second word, need to 
+		 *  adjust bit position count
+		 */
+		dst_exponent += 32;
+	}
+	else {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 *
+		 */
+		Find_ms_one_bit(srcp1,dst_exponent);
+		/*  left justify source, with msb at bit position 0  */
+		if (dst_exponent >= 0) {
+			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
+			 srcp1); 
+			srcp2 <<= dst_exponent+1;
+		}
+	}
+	Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH);
+	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
+
+	/* check for inexact */
+	if (Duint_isinexact_to_sgl(srcp1,srcp2)) {
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				Sgl_increment(result);
+				break;
+			case ROUNDMINUS: /* never negative */
+				break;
+			case ROUNDNEAREST:
+				Sgl_roundnearest_from_duint(srcp1,srcp2,result);
+				break;
+		}
+		if (Is_inexacttrap_enabled()) {
+			*dstptr = result;
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	*dstptr = result;
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Unsigned Fixed to Double Floating-point 
+ */
+
+int
+dbl_to_dbl_fcnvuf(
+		    dbl_unsigned *srcptr,
+		    unsigned int *nullptr,
+		    dbl_floating_point *dstptr,
+		    unsigned int *status)
+{
+	register int dst_exponent;
+	register unsigned int srcp1, srcp2, resultp1 = 0, resultp2 = 0;
+
+	Duint_copyfromptr(srcptr,srcp1,srcp2);
+
+	/* Check for zero */
+	if (srcp1 == 0 && srcp2 ==0) {
+	       	Dbl_setzero(resultp1,resultp2);
+	       	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	       	return(NOEXCEPTION);
+	}
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	if (srcp1 == 0) {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 */
+		Find_ms_one_bit(srcp2,dst_exponent);
+		/*  left justify source, with msb at bit position 0  */
+		srcp1 = srcp2 << dst_exponent+1;
+		srcp2 = 0;
+		/*
+		 *  since msb set is in second word, need to 
+		 *  adjust bit position count
+		 */
+		dst_exponent += 32;
+	}
+	else {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 */
+		Find_ms_one_bit(srcp1,dst_exponent);
+		/*  left justify source, with msb at bit position 0  */
+		if (dst_exponent >= 0) {
+			Variable_shift_double(srcp1,srcp2,(31-dst_exponent),
+			 srcp1); 
+			srcp2 <<= dst_exponent+1;
+		}
+	}
+	Dbl_set_mantissap1(resultp1, srcp1 >> DBL_EXP_LENGTH);
+	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH,resultp2);
+	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
+
+	/* check for inexact */
+	if (Duint_isinexact_to_dbl(srcp2)) {
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				Dbl_increment(resultp1,resultp2);
+				break;
+			case ROUNDMINUS: /* never negative */
+				break;
+			case ROUNDNEAREST:
+				Dbl_roundnearest_from_duint(srcp2,resultp1,
+				resultp2);
+				break;
+		}
+		if (Is_inexacttrap_enabled()) {
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fcnvxf.c linux/arch/parisc/math-emu/fcnvxf.c
--- linux.orig/arch/parisc/math-emu/fcnvxf.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fcnvxf.c	2002-08-12 22:14:09.000000000 +0000
@@ -0,0 +1,386 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fcnvxf.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Fixed-point to Single Floating-point
+ *	Single Fixed-point to Double Floating-point 
+ *	Double Fixed-point to Single Floating-point 
+ *	Double Fixed-point to Double Floating-point 
+ *
+ *  External Interfaces:
+ *	dbl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
+ *	dbl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
+ *	sgl_to_dbl_fcnvxf(srcptr,nullptr,dstptr,status)
+ *	sgl_to_sgl_fcnvxf(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ *  Convert single fixed-point to single floating-point format
+ */
+
+int
+sgl_to_sgl_fcnvxf(
+		    int *srcptr,
+		    unsigned int *nullptr,
+		    sgl_floating_point *dstptr,
+		    unsigned int *status)
+{
+	register int src, dst_exponent;
+	register unsigned int result = 0;
+
+	src = *srcptr;
+	/* 
+	 * set sign bit of result and get magnitude of source 
+	 */
+	if (src < 0) {
+		Sgl_setone_sign(result);  
+		Int_negate(src);
+	}
+	else {
+		Sgl_setzero_sign(result);
+        	/* Check for zero */ 
+        	if (src == 0) { 
+                	Sgl_setzero(result); 
+			*dstptr = result;
+                	return(NOEXCEPTION); 
+        	} 
+	}
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	/*
+	 * Check word for most significant bit set.  Returns
+	 * a value in dst_exponent indicating the bit position,
+	 * between -1 and 30.
+	 */
+	Find_ms_one_bit(src,dst_exponent);
+	/*  left justify source, with msb at bit position 1  */
+	if (dst_exponent >= 0) src <<= dst_exponent;
+	else src = 1 << 30;
+	Sgl_set_mantissa(result, src >> (SGL_EXP_LENGTH-1));
+	Sgl_set_exponent(result, 30+SGL_BIAS - dst_exponent);
+
+	/* check for inexact */
+	if (Int_isinexact_to_sgl(src)) {
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) 
+					Sgl_increment(result);
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) 
+					Sgl_increment(result);
+				break;
+			case ROUNDNEAREST:
+				Sgl_roundnearest_from_int(src,result);
+		}
+		if (Is_inexacttrap_enabled()) {
+			*dstptr = result;
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	*dstptr = result;
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Fixed-point to Double Floating-point 
+ */
+
+int
+sgl_to_dbl_fcnvxf(
+		    int *srcptr,
+		    unsigned int *nullptr,
+		    dbl_floating_point *dstptr,
+		    unsigned int *status)
+{
+	register int src, dst_exponent;
+	register unsigned int resultp1 = 0, resultp2 = 0;
+
+	src = *srcptr;
+	/* 
+	 * set sign bit of result and get magnitude of source 
+	 */
+	if (src < 0) {
+		Dbl_setone_sign(resultp1);  
+		Int_negate(src);
+	}
+	else {
+		Dbl_setzero_sign(resultp1);
+        	/* Check for zero */
+        	if (src == 0) {
+                	Dbl_setzero(resultp1,resultp2);
+                	Dbl_copytoptr(resultp1,resultp2,dstptr);
+                	return(NOEXCEPTION);
+        	}
+	}
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	/*
+	 * Check word for most significant bit set.  Returns
+	 * a value in dst_exponent indicating the bit position,
+	 * between -1 and 30.
+	 */
+	Find_ms_one_bit(src,dst_exponent);
+	/*  left justify source, with msb at bit position 1  */
+	if (dst_exponent >= 0) src <<= dst_exponent;
+	else src = 1 << 30;
+	Dbl_set_mantissap1(resultp1, src >> DBL_EXP_LENGTH - 1);
+	Dbl_set_mantissap2(resultp2, src << (33-DBL_EXP_LENGTH));
+	Dbl_set_exponent(resultp1, (30+DBL_BIAS) - dst_exponent);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Fixed-point to Single Floating-point 
+ */
+
+int
+dbl_to_sgl_fcnvxf(
+			dbl_integer *srcptr,
+			unsigned int *nullptr,
+			sgl_floating_point *dstptr,
+			unsigned int *status)
+{
+	int dst_exponent, srcp1;
+	unsigned int result = 0, srcp2;
+
+	Dint_copyfromptr(srcptr,srcp1,srcp2);
+	/* 
+	 * set sign bit of result and get magnitude of source 
+	 */
+	if (srcp1 < 0) {
+		Sgl_setone_sign(result);  
+		Dint_negate(srcp1,srcp2);
+	}
+	else {
+		Sgl_setzero_sign(result);
+        	/* Check for zero */
+        	if (srcp1 == 0 && srcp2 == 0) {
+                	Sgl_setzero(result);
+                	*dstptr = result;
+                	return(NOEXCEPTION);
+		}
+        }
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	if (srcp1 == 0) {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 */
+		Find_ms_one_bit(srcp2,dst_exponent);
+		/*  left justify source, with msb at bit position 1  */
+		if (dst_exponent >= 0) {
+			srcp1 = srcp2 << dst_exponent;    
+			srcp2 = 0;
+		}
+		else {
+			srcp1 = srcp2 >> 1;
+			srcp2 <<= 31; 
+		}
+		/*
+		 *  since msb set is in second word, need to 
+		 *  adjust bit position count
+		 */
+		dst_exponent += 32;
+	}
+	else {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 *
+		 */
+		Find_ms_one_bit(srcp1,dst_exponent);
+		/*  left justify source, with msb at bit position 1  */
+		if (dst_exponent > 0) {
+			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
+			 srcp1); 
+			srcp2 <<= dst_exponent;
+		}
+		/*
+		 * If dst_exponent = 0, we don't need to shift anything.
+		 * If dst_exponent = -1, src = - 2**63 so we won't need to 
+		 * shift srcp2.
+		 */
+		else srcp1 >>= -(dst_exponent);
+	}
+	Sgl_set_mantissa(result, srcp1 >> SGL_EXP_LENGTH - 1);
+	Sgl_set_exponent(result, (62+SGL_BIAS) - dst_exponent);
+
+	/* check for inexact */
+	if (Dint_isinexact_to_sgl(srcp1,srcp2)) {
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) 
+					Sgl_increment(result);
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) 
+					Sgl_increment(result);
+				break;
+			case ROUNDNEAREST:
+				Sgl_roundnearest_from_dint(srcp1,srcp2,result);
+		}
+		if (Is_inexacttrap_enabled()) {
+			*dstptr = result;
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	*dstptr = result;
+	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Fixed-point to Double Floating-point 
+ */
+
+int
+dbl_to_dbl_fcnvxf(
+		    dbl_integer *srcptr,
+		    unsigned int *nullptr,
+		    dbl_floating_point *dstptr,
+		    unsigned int *status)
+{
+	register int srcp1, dst_exponent;
+	register unsigned int srcp2, resultp1 = 0, resultp2 = 0;
+
+	Dint_copyfromptr(srcptr,srcp1,srcp2);
+	/* 
+	 * set sign bit of result and get magnitude of source 
+	 */
+	if (srcp1 < 0) {
+		Dbl_setone_sign(resultp1);
+		Dint_negate(srcp1,srcp2);
+	}
+	else {
+		Dbl_setzero_sign(resultp1);
+        	/* Check for zero */
+        	if (srcp1 == 0 && srcp2 ==0) {
+                	Dbl_setzero(resultp1,resultp2);
+                	Dbl_copytoptr(resultp1,resultp2,dstptr);
+                	return(NOEXCEPTION);
+		}
+        }
+	/*
+	 * Generate exponent and normalized mantissa
+	 */
+	dst_exponent = 16;    /* initialize for normalization */
+	if (srcp1 == 0) {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 */
+		Find_ms_one_bit(srcp2,dst_exponent);
+		/*  left justify source, with msb at bit position 1  */
+		if (dst_exponent >= 0) {
+			srcp1 = srcp2 << dst_exponent;    
+			srcp2 = 0;
+		}
+		else {
+			srcp1 = srcp2 >> 1;
+			srcp2 <<= 31;
+		}
+		/*
+		 *  since msb set is in second word, need to 
+		 *  adjust bit position count
+		 */
+		dst_exponent += 32;
+	}
+	else {
+		/*
+		 * Check word for most significant bit set.  Returns
+		 * a value in dst_exponent indicating the bit position,
+		 * between -1 and 30.
+		 */
+		Find_ms_one_bit(srcp1,dst_exponent);
+		/*  left justify source, with msb at bit position 1  */
+		if (dst_exponent > 0) {
+			Variable_shift_double(srcp1,srcp2,(32-dst_exponent),
+			 srcp1); 
+			srcp2 <<= dst_exponent;
+		}
+		/*
+		 * If dst_exponent = 0, we don't need to shift anything.
+		 * If dst_exponent = -1, src = - 2**63 so we won't need to 
+		 * shift srcp2.
+		 */
+		else srcp1 >>= -(dst_exponent);
+	}
+	Dbl_set_mantissap1(resultp1, srcp1 >> (DBL_EXP_LENGTH-1));
+	Shiftdouble(srcp1,srcp2,DBL_EXP_LENGTH-1,resultp2);
+	Dbl_set_exponent(resultp1, (62+DBL_BIAS) - dst_exponent);
+
+	/* check for inexact */
+	if (Dint_isinexact_to_dbl(srcp2)) {
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Dbl_iszero_sign(resultp1)) {
+					Dbl_increment(resultp1,resultp2);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Dbl_isone_sign(resultp1)) {
+					Dbl_increment(resultp1,resultp2);
+				}
+				break;
+			case ROUNDNEAREST:
+				Dbl_roundnearest_from_dint(srcp2,resultp1,
+				resultp2);
+		}
+		if (Is_inexacttrap_enabled()) {
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/float.h linux/arch/parisc/math-emu/float.h
--- linux.orig/arch/parisc/math-emu/float.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/float.h	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,582 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ * 
+ *  File: 
+ *      @(#)	pa/spmath/float.h		$Revision: 1.2 $
+ * 
+ *  Purpose:
+ *      <<please update with a synopis of the functionality provided by this file>>
+ * 
+ *  BE header:  no
+ *
+ *  Shipped:  yes
+ *	/usr/conf/pa/spmath/float.h
+ *
+ * END_DESC  
+*/
+
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+#include "fpbits.h"
+#include "hppa.h"
+/*
+ * Want to pick up the FPU capability flags, not the PDC structures.
+ * 'LOCORE' isn't really true in this case, but we don't want the C structures
+ * so it suits our purposes
+ */
+#define LOCORE
+#include "fpu.h"
+
+/*
+ * Declare the basic structures for the 3 different
+ * floating-point precisions.
+ *        
+ * Single number  
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s|       exp     |               mantissa                      |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define	Sall(object) (object)
+#define	Ssign(object) Bitfield_extract( 0,  1,object)
+#define	Ssignedsign(object) Bitfield_signed_extract( 0,  1,object)
+#define	Sexponent(object) Bitfield_extract( 1,  8,object)
+#define	Smantissa(object) Bitfield_mask( 9, 23,object)
+#define	Ssignaling(object) Bitfield_extract( 9,  1,object)
+#define	Ssignalingnan(object) Bitfield_extract( 1,  9,object)
+#define	Shigh2mantissa(object) Bitfield_extract( 9,  2,object)
+#define	Sexponentmantissa(object) Bitfield_mask( 1, 31,object)
+#define	Ssignexponent(object) Bitfield_extract( 0,  9,object)
+#define	Shidden(object) Bitfield_extract( 8,  1,object)
+#define	Shiddenoverflow(object) Bitfield_extract( 7,  1,object)
+#define	Shiddenhigh7mantissa(object) Bitfield_extract( 8,  8,object)
+#define	Shiddenhigh3mantissa(object) Bitfield_extract( 8,  4,object)
+#define	Slow(object) Bitfield_mask( 31,  1,object)
+#define	Slow4(object) Bitfield_mask( 28,  4,object)
+#define	Slow31(object) Bitfield_mask( 1, 31,object)
+#define	Shigh31(object) Bitfield_extract( 0, 31,object)
+#define	Ssignedhigh31(object) Bitfield_signed_extract( 0, 31,object)
+#define	Shigh4(object) Bitfield_extract( 0,  4,object)
+#define	Sbit24(object) Bitfield_extract( 24,  1,object)
+#define	Sbit28(object) Bitfield_extract( 28,  1,object)
+#define	Sbit29(object) Bitfield_extract( 29,  1,object)
+#define	Sbit30(object) Bitfield_extract( 30,  1,object)
+#define	Sbit31(object) Bitfield_mask( 31,  1,object)
+
+#define Deposit_ssign(object,value) Bitfield_deposit(value,0,1,object)
+#define Deposit_sexponent(object,value) Bitfield_deposit(value,1,8,object)
+#define Deposit_smantissa(object,value) Bitfield_deposit(value,9,23,object)
+#define Deposit_shigh2mantissa(object,value) Bitfield_deposit(value,9,2,object)
+#define Deposit_sexponentmantissa(object,value) \
+    Bitfield_deposit(value,1,31,object)
+#define Deposit_ssignexponent(object,value) Bitfield_deposit(value,0,9,object)
+#define Deposit_slow(object,value) Bitfield_deposit(value,31,1,object)
+#define Deposit_shigh4(object,value) Bitfield_deposit(value,0,4,object)
+
+#define	Is_ssign(object) Bitfield_mask( 0,  1,object)
+#define	Is_ssignaling(object) Bitfield_mask( 9,  1,object)
+#define	Is_shidden(object) Bitfield_mask( 8,  1,object)
+#define	Is_shiddenoverflow(object) Bitfield_mask( 7,  1,object)
+#define	Is_slow(object) Bitfield_mask( 31,  1,object)
+#define	Is_sbit24(object) Bitfield_mask( 24,  1,object)
+#define	Is_sbit28(object) Bitfield_mask( 28,  1,object)
+#define	Is_sbit29(object) Bitfield_mask( 29,  1,object)
+#define	Is_sbit30(object) Bitfield_mask( 30,  1,object)
+#define	Is_sbit31(object) Bitfield_mask( 31,  1,object)
+
+/* 
+ * Double number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s|       exponent      |          mantissa part 1              |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    mantissa part 2                            |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Dallp1(object) (object)
+#define Dsign(object) Bitfield_extract( 0,  1,object)
+#define Dsignedsign(object) Bitfield_signed_extract( 0,  1,object)
+#define Dexponent(object) Bitfield_extract( 1,  11,object)
+#define Dmantissap1(object) Bitfield_mask( 12, 20,object)
+#define Dsignaling(object) Bitfield_extract( 12,  1,object)
+#define Dsignalingnan(object) Bitfield_extract( 1,  12,object)
+#define Dhigh2mantissa(object) Bitfield_extract( 12,  2,object)
+#define Dexponentmantissap1(object) Bitfield_mask( 1, 31,object)
+#define Dsignexponent(object) Bitfield_extract( 0, 12,object)
+#define Dhidden(object) Bitfield_extract( 11,  1,object)
+#define Dhiddenoverflow(object) Bitfield_extract( 10,  1,object)
+#define Dhiddenhigh7mantissa(object) Bitfield_extract( 11,  8,object)
+#define Dhiddenhigh3mantissa(object) Bitfield_extract( 11,  4,object)
+#define Dlowp1(object) Bitfield_mask( 31,  1,object)
+#define Dlow31p1(object) Bitfield_mask( 1, 31,object)
+#define Dhighp1(object) Bitfield_extract( 0,  1,object)
+#define Dhigh4p1(object) Bitfield_extract( 0,  4,object)
+#define Dhigh31p1(object) Bitfield_extract( 0, 31,object)
+#define Dsignedhigh31p1(object) Bitfield_signed_extract( 0, 31,object)
+#define Dbit3p1(object) Bitfield_extract( 3,  1,object)
+
+#define Deposit_dsign(object,value) Bitfield_deposit(value,0,1,object)
+#define Deposit_dexponent(object,value) Bitfield_deposit(value,1,11,object)
+#define Deposit_dmantissap1(object,value) Bitfield_deposit(value,12,20,object)
+#define Deposit_dhigh2mantissa(object,value) Bitfield_deposit(value,12,2,object)
+#define Deposit_dexponentmantissap1(object,value) \
+    Bitfield_deposit(value,1,31,object)
+#define Deposit_dsignexponent(object,value) Bitfield_deposit(value,0,12,object)
+#define Deposit_dlowp1(object,value) Bitfield_deposit(value,31,1,object)
+#define Deposit_dhigh4p1(object,value) Bitfield_deposit(value,0,4,object)
+
+#define Is_dsign(object) Bitfield_mask( 0,  1,object)
+#define Is_dsignaling(object) Bitfield_mask( 12,  1,object)
+#define Is_dhidden(object) Bitfield_mask( 11,  1,object)
+#define Is_dhiddenoverflow(object) Bitfield_mask( 10,  1,object)
+#define Is_dlowp1(object) Bitfield_mask( 31,  1,object)
+#define Is_dhighp1(object) Bitfield_mask( 0,  1,object)
+#define Is_dbit3p1(object) Bitfield_mask( 3,  1,object)
+
+#define Dallp2(object) (object)
+#define Dmantissap2(object) (object)
+#define Dlowp2(object) Bitfield_mask( 31,  1,object)
+#define Dlow4p2(object) Bitfield_mask( 28,  4,object)
+#define Dlow31p2(object) Bitfield_mask( 1, 31,object)
+#define Dhighp2(object) Bitfield_extract( 0,  1,object)
+#define Dhigh31p2(object) Bitfield_extract( 0, 31,object)
+#define Dbit2p2(object) Bitfield_extract( 2,  1,object)
+#define Dbit3p2(object) Bitfield_extract( 3,  1,object)
+#define Dbit21p2(object) Bitfield_extract( 21,  1,object)
+#define Dbit28p2(object) Bitfield_extract( 28,  1,object)
+#define Dbit29p2(object) Bitfield_extract( 29,  1,object)
+#define Dbit30p2(object) Bitfield_extract( 30,  1,object)
+#define Dbit31p2(object) Bitfield_mask( 31,  1,object)
+
+#define Deposit_dlowp2(object,value) Bitfield_deposit(value,31,1,object)
+
+#define Is_dlowp2(object) Bitfield_mask( 31,  1,object)
+#define Is_dhighp2(object) Bitfield_mask( 0,  1,object)
+#define Is_dbit2p2(object) Bitfield_mask( 2,  1,object)
+#define Is_dbit3p2(object) Bitfield_mask( 3,  1,object)
+#define Is_dbit21p2(object) Bitfield_mask( 21,  1,object)
+#define Is_dbit28p2(object) Bitfield_mask( 28,  1,object)
+#define Is_dbit29p2(object) Bitfield_mask( 29,  1,object)
+#define Is_dbit30p2(object) Bitfield_mask( 30,  1,object)
+#define Is_dbit31p2(object) Bitfield_mask( 31,  1,object)
+
+/* 
+ * Quad number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s|          exponent           |      mantissa part 1          |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    mantissa part 2                            |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    mantissa part 3                            |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    mantissa part 4                            |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+typedef struct
+    {
+    union
+	{
+	struct { unsigned qallp1; } u_qallp1;
+/* Not needed for now...
+	Bitfield_extract( 0,  1,u_qsign,qsign)
+	Bitfield_signed_extract( 0,  1,u_qsignedsign,qsignedsign)
+	Bitfield_extract( 1, 15,u_qexponent,qexponent)
+	Bitfield_extract(16, 16,u_qmantissap1,qmantissap1)
+	Bitfield_extract(16,  1,u_qsignaling,qsignaling)
+	Bitfield_extract(1,  16,u_qsignalingnan,qsignalingnan)
+	Bitfield_extract(16,  2,u_qhigh2mantissa,qhigh2mantissa)
+	Bitfield_extract( 1, 31,u_qexponentmantissap1,qexponentmantissap1)
+	Bitfield_extract( 0, 16,u_qsignexponent,qsignexponent)
+	Bitfield_extract(15,  1,u_qhidden,qhidden)
+	Bitfield_extract(14,  1,u_qhiddenoverflow,qhiddenoverflow)
+	Bitfield_extract(15,  8,u_qhiddenhigh7mantissa,qhiddenhigh7mantissa)
+	Bitfield_extract(15,  4,u_qhiddenhigh3mantissa,qhiddenhigh3mantissa)
+	Bitfield_extract(31,  1,u_qlowp1,qlowp1)
+	Bitfield_extract( 1, 31,u_qlow31p1,qlow31p1)
+	Bitfield_extract( 0,  1,u_qhighp1,qhighp1)
+	Bitfield_extract( 0,  4,u_qhigh4p1,qhigh4p1)
+	Bitfield_extract( 0, 31,u_qhigh31p1,qhigh31p1)
+  */
+	} quad_u1;
+    union
+	{
+	struct { unsigned qallp2; } u_qallp2;
+  /* Not needed for now...
+	Bitfield_extract(31,  1,u_qlowp2,qlowp2)
+	Bitfield_extract( 1, 31,u_qlow31p2,qlow31p2)
+	Bitfield_extract( 0,  1,u_qhighp2,qhighp2)
+	Bitfield_extract( 0, 31,u_qhigh31p2,qhigh31p2)
+   */
+	} quad_u2;
+    union
+	{
+	struct { unsigned qallp3; } u_qallp3;
+  /* Not needed for now...
+	Bitfield_extract(31,  1,u_qlowp3,qlowp3)
+	Bitfield_extract( 1, 31,u_qlow31p3,qlow31p3)
+	Bitfield_extract( 0,  1,u_qhighp3,qhighp3)
+	Bitfield_extract( 0, 31,u_qhigh31p3,qhigh31p3)
+   */ 
+	} quad_u3;
+    union
+	{
+	struct { unsigned qallp4; } u_qallp4;
+    /* Not need for now...
+	Bitfield_extract(31,  1,u_qlowp4,qlowp4)
+	Bitfield_extract( 1, 31,u_qlow31p4,qlow31p4)
+	Bitfield_extract( 0,  1,u_qhighp4,qhighp4)
+	Bitfield_extract( 0, 31,u_qhigh31p4,qhigh31p4)
+     */
+	} quad_u4;
+    } quad_floating_point;
+
+/* Extension - An additional structure to hold the guard, round and
+ *             sticky bits during computations.
+ */
+#define Extall(object) (object)
+#define Extsign(object) Bitfield_extract( 0,  1,object)
+#define Exthigh31(object) Bitfield_extract( 0, 31,object)
+#define Extlow31(object) Bitfield_extract( 1, 31,object)
+#define Extlow(object) Bitfield_extract( 31,  1,object)
+
+/*
+ * Single extended - The upper word is just like single precision,
+ *                 but one additional word of mantissa is needed.
+ */
+#define Sextallp1(object) (object)
+#define Sextallp2(object) (object)
+#define Sextlowp1(object) Bitfield_extract( 31,  1,object)
+#define Sexthighp2(object) Bitfield_extract( 0,  1,object)
+#define Sextlow31p2(object) Bitfield_extract( 1, 31,object)
+#define Sexthiddenoverflow(object) Bitfield_extract( 4,  1,object)
+#define Is_sexthiddenoverflow(object) Bitfield_mask( 4,  1,object)
+
+/*
+ * Double extended - The upper two words are just like double precision,
+ *		     but two additional words of mantissa are needed.
+ */
+#define Dextallp1(object) (object)
+#define Dextallp2(object) (object)
+#define Dextallp3(object) (object)
+#define Dextallp4(object) (object)
+#define Dextlowp2(object) Bitfield_extract( 31,  1,object)
+#define Dexthighp3(object) Bitfield_extract( 0,  1,object)
+#define Dextlow31p3(object) Bitfield_extract( 1, 31,object)
+#define Dexthiddenoverflow(object) Bitfield_extract( 10,  1,object)
+#define Is_dexthiddenoverflow(object) Bitfield_mask( 10,  1,object)
+#define Deposit_dextlowp4(object,value) Bitfield_deposit(value,31,1,object)
+
+/*
+ * Declare the basic structures for the 3 different
+ * fixed-point precisions.
+ *        
+ * Single number  
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s|                    integer                                  |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+typedef int sgl_integer;
+
+/* 
+ * Double number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s|                     high integer                            |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                       low integer                             |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+struct dint {
+        int  wd0;
+        unsigned int wd1;
+};
+
+struct dblwd {
+        unsigned int wd0;
+        unsigned int wd1;
+};
+
+/* 
+ * Quad number.
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |s|                  integer part1                              |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    integer part 2                             |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    integer part 3                             |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                    integer part 4                             |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+
+struct quadwd {
+        int  wd0;
+        unsigned int wd1;
+        unsigned int wd2;
+        unsigned int wd3;
+};
+
+typedef struct quadwd quad_integer;
+
+
+/* useful typedefs */
+typedef unsigned int sgl_floating_point;
+typedef struct dblwd dbl_floating_point;
+typedef struct dint dbl_integer;
+typedef struct dblwd dbl_unsigned;
+
+/* 
+ * Define the different precisions' parameters.
+ */
+#define SGL_BITLENGTH 32
+#define SGL_EMAX 127
+#define SGL_EMIN (-126)
+#define SGL_BIAS 127
+#define SGL_WRAP 192
+#define SGL_INFINITY_EXPONENT (SGL_EMAX+SGL_BIAS+1)
+#define SGL_THRESHOLD 32
+#define SGL_EXP_LENGTH 8
+#define SGL_P 24
+
+#define DBL_BITLENGTH 64
+#define DBL_EMAX 1023
+#define DBL_EMIN (-1022)
+#define DBL_BIAS 1023
+#define DBL_WRAP 1536
+#define DBL_INFINITY_EXPONENT (DBL_EMAX+DBL_BIAS+1)
+#define DBL_THRESHOLD 64
+#define DBL_EXP_LENGTH 11
+#define DBL_P 53
+
+#define QUAD_BITLENGTH 128
+#define QUAD_EMAX 16383
+#define QUAD_EMIN (-16382)
+#define QUAD_BIAS 16383
+#define QUAD_WRAP 24576
+#define QUAD_INFINITY_EXPONENT (QUAD_EMAX+QUAD_BIAS+1)
+#define QUAD_P 113
+
+/* Boolean Values etc. */
+#define FALSE 0
+#define TRUE (!FALSE)
+#define NOT !
+#define XOR ^
+
+/* other constants */
+#undef NULL
+#define NULL 0
+#define NIL 0
+#define SGL 0
+#define DBL 1
+#define BADFMT 2
+#define QUAD 3
+
+
+/* Types */
+typedef int boolean;
+typedef int FORMAT;
+typedef int VOID;
+
+
+/* Declare status register equivalent to FPUs architecture.
+ *
+ *  0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |V|Z|O|U|I|C|  rsv  |  model    | version |RM |rsv|T|r|V|Z|O|U|I|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Cbit(object) Bitfield_extract( 5, 1,object)
+#define Tbit(object) Bitfield_extract( 25, 1,object)
+#define Roundingmode(object) Bitfield_extract( 21, 2,object)
+#define Invalidtrap(object) Bitfield_extract( 27, 1,object)
+#define Divisionbyzerotrap(object) Bitfield_extract( 28, 1,object)
+#define Overflowtrap(object) Bitfield_extract( 29, 1,object)
+#define Underflowtrap(object) Bitfield_extract( 30, 1,object)
+#define Inexacttrap(object) Bitfield_extract( 31, 1,object)
+#define Invalidflag(object) Bitfield_extract( 0, 1,object)
+#define Divisionbyzeroflag(object) Bitfield_extract( 1, 1,object)
+#define Overflowflag(object) Bitfield_extract( 2, 1,object)
+#define Underflowflag(object) Bitfield_extract( 3, 1,object)
+#define Inexactflag(object) Bitfield_extract( 4, 1,object)
+#define Allflags(object) Bitfield_extract( 0, 5,object)
+
+/* Definitions relevant to the status register */
+
+/* Rounding Modes */
+#define ROUNDNEAREST 0
+#define ROUNDZERO    1
+#define ROUNDPLUS    2
+#define ROUNDMINUS   3
+
+/* Exceptions */
+#define NOEXCEPTION		0x0
+#define INVALIDEXCEPTION	0x20
+#define DIVISIONBYZEROEXCEPTION	0x10
+#define OVERFLOWEXCEPTION	0x08
+#define UNDERFLOWEXCEPTION	0x04
+#define INEXACTEXCEPTION	0x02
+#define UNIMPLEMENTEDEXCEPTION	0x01
+
+/* New exceptions for the 2E Opcode */
+#define OPC_2E_INVALIDEXCEPTION     0x30
+#define OPC_2E_OVERFLOWEXCEPTION    0x18
+#define OPC_2E_UNDERFLOWEXCEPTION   0x0c
+#define OPC_2E_INEXACTEXCEPTION     0x12
+
+/* Declare exception registers equivalent to FPUs architecture 
+ *
+ *  0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |excepttype |  r1     | r2/ext  |  operation  |parm |n| t/cond  |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Allexception(object) (object)
+#define Exceptiontype(object) Bitfield_extract( 0, 6,object)
+#define Instructionfield(object) Bitfield_mask( 6,26,object)
+#define Parmfield(object) Bitfield_extract( 23, 3,object)
+#define Rabit(object) Bitfield_extract( 24, 1,object)
+#define Ibit(object) Bitfield_extract( 25, 1,object)
+
+#define Set_exceptiontype(object,value) Bitfield_deposit(value, 0, 6,object)
+#define Set_parmfield(object,value) Bitfield_deposit(value, 23, 3,object)
+#define Set_exceptiontype_and_instr_field(exception,instruction,object) \
+    object = exception << 26 | instruction
+
+/* Declare the condition field
+ *
+ *  0 1 2 3 4 5 6 7 8 910 1 2 3 4 5 6 7 8 920 1 2 3 4 5 6 7 8 930 1
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |                                                     |G|L|E|U|X|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#define Allexception(object) (object)
+#define Greaterthanbit(object) Bitfield_extract( 27, 1,object)
+#define Lessthanbit(object) Bitfield_extract( 28, 1,object)
+#define Equalbit(object) Bitfield_extract( 29, 1,object)
+#define Unorderedbit(object) Bitfield_extract( 30, 1,object)
+#define Exceptionbit(object) Bitfield_extract( 31, 1,object)
+
+/* An alias name for the status register */
+#define Fpustatus_register (*status)
+
+/**************************************************
+ * Status register referencing and manipulation.  *
+ **************************************************/
+
+/* Rounding mode */
+#define Rounding_mode()  Roundingmode(Fpustatus_register)
+#define Is_rounding_mode(rmode) \
+    (Roundingmode(Fpustatus_register) == rmode)
+#define Set_rounding_mode(value) \
+    Bitfield_deposit(value,21,2,Fpustatus_register)
+
+/* Boolean testing of the trap enable bits */
+#define Is_invalidtrap_enabled() Invalidtrap(Fpustatus_register)
+#define Is_divisionbyzerotrap_enabled() Divisionbyzerotrap(Fpustatus_register)
+#define Is_overflowtrap_enabled() Overflowtrap(Fpustatus_register)
+#define Is_underflowtrap_enabled() Underflowtrap(Fpustatus_register)
+#define Is_inexacttrap_enabled() Inexacttrap(Fpustatus_register)
+
+/* Set the indicated flags in the status register */
+#define Set_invalidflag() Bitfield_deposit(1,0,1,Fpustatus_register)
+#define Set_divisionbyzeroflag() Bitfield_deposit(1,1,1,Fpustatus_register)
+#define Set_overflowflag() Bitfield_deposit(1,2,1,Fpustatus_register)
+#define Set_underflowflag() Bitfield_deposit(1,3,1,Fpustatus_register)
+#define Set_inexactflag() Bitfield_deposit(1,4,1,Fpustatus_register)
+
+#define Clear_all_flags() Bitfield_deposit(0,0,5,Fpustatus_register)
+
+/* Manipulate the trap and condition code bits (tbit and cbit) */
+#define Set_tbit() Bitfield_deposit(1,25,1,Fpustatus_register)
+#define Clear_tbit() Bitfield_deposit(0,25,1,Fpustatus_register)
+#define Is_tbit_set() Tbit(Fpustatus_register)
+#define Is_cbit_set() Cbit(Fpustatus_register)
+
+#define Set_status_cbit(value)  \
+        Bitfield_deposit(value,5,1,Fpustatus_register)
+
+/*******************************
+ * Condition field referencing *
+ *******************************/
+#define Unordered(cond) Unorderedbit(cond)
+#define Equal(cond) Equalbit(cond)
+#define Lessthan(cond) Lessthanbit(cond)
+#define Greaterthan(cond) Greaterthanbit(cond)
+#define Exception(cond) Exceptionbit(cond)
+
+
+/* Defines for the extension */
+#define Ext_isone_sign(extent) (Extsign(extent))
+#define Ext_isnotzero(extent) \
+    (Extall(extent))
+#define Ext_isnotzero_lower(extent) \
+    (Extlow31(extent))
+#define Ext_leftshiftby1(extent) \
+    Extall(extent) <<= 1
+#define Ext_negate(extent) \
+    (int )Extall(extent) = 0 - (int )Extall(extent)
+#define Ext_setone_low(extent) Bitfield_deposit(1,31,1,extent)
+#define Ext_setzero(extent) Extall(extent) = 0
+
+typedef int operation;
+
+/* error messages */
+
+#define		NONE		0
+#define		UNDEFFPINST	1
+
+/* Function definitions: opcode, opclass */
+#define FTEST	(1<<2) | 0
+#define FCPY	(2<<2) | 0
+#define FABS	(3<<2) | 0
+#define FSQRT   (4<<2) | 0
+#define FRND    (5<<2) | 0
+
+#define FCNVFF	(0<<2) | 1
+#define FCNVXF	(1<<2) | 1
+#define FCNVFX	(2<<2) | 1
+#define FCNVFXT	(3<<2) | 1
+
+#define FCMP    (0<<2) | 2
+
+#define FADD	(0<<2) | 3
+#define FSUB	(1<<2) | 3
+#define FMPY	(2<<2) | 3
+#define FDIV	(3<<2) | 3
+#define FREM	(4<<2) | 3
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fmpyfadd.c linux/arch/parisc/math-emu/fmpyfadd.c
--- linux.orig/arch/parisc/math-emu/fmpyfadd.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fmpyfadd.c	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,2655 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/fmpyfadd.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Double Floating-point Multiply Fused Add
+ *	Double Floating-point Multiply Negate Fused Add
+ *	Single Floating-point Multiply Fused Add
+ *	Single Floating-point Multiply Negate Fused Add
+ *
+ *  External Interfaces:
+ *	dbl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ *	dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ *	sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ *	sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+
+
+/*
+ *  Double Floating-point Multiply Fused Add
+ */
+
+int
+dbl_fmpyfadd(
+	    dbl_floating_point *src1ptr,
+	    dbl_floating_point *src2ptr,
+	    dbl_floating_point *src3ptr,
+	    unsigned int *status,
+	    dbl_floating_point *dstptr)
+{
+	unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
+	register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
+	unsigned int rightp1, rightp2, rightp3, rightp4;
+	unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
+	register int mpy_exponent, add_exponent, count;
+	boolean inexact = FALSE, is_tiny = FALSE;
+
+	unsigned int signlessleft1, signlessright1, save;
+	register int result_exponent, diff_exponent;
+	int sign_save, jumpsize;
+	
+	Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
+	Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
+	Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
+
+	/* 
+	 * set sign bit of result of multiply
+	 */
+	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
+		Dbl_setnegativezerop1(resultp1); 
+	else Dbl_setzerop1(resultp1);
+
+	/*
+	 * Generate multiply exponent 
+	 */
+	mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
+
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd1p1)) {
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
+			    Dbl_isnotnan(opnd3p1,opnd3p2)) {
+				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+					/* 
+					 * invalid since operands are infinity 
+					 * and zero 
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+			 	 * return infinity
+			 	 */
+				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+		 	 * is NaN; signaling or quiet?
+		 	 */
+			if (Dbl_isone_signaling(opnd1p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled()) 
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd1p1);
+			}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd2p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd2p1);
+				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd3p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd3p1);
+				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/*
+		 	 * return quiet NaN
+		 	 */
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd2p1)) {
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
+				if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+					/* 
+					 * invalid since multiply operands are
+					 * zero & infinity
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Dbl_makequietnan(opnd2p1,opnd2p2);
+					Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+				       		return(OPC_2E_INVALIDEXCEPTION);
+				       	Set_invalidflag();
+				       	Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * return infinity
+				 */
+				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Dbl_isone_signaling(opnd2p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd2p1);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd3p1)) {
+			       	/* trap if INVALIDTRAP enabled */
+			       	if (Is_invalidtrap_enabled())
+				   		return(OPC_2E_INVALIDEXCEPTION);
+			       	/* make NaN quiet */
+			       	Set_invalidflag();
+			       	Dbl_set_quiet(opnd3p1);
+				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+		       		return(NOEXCEPTION);
+			}
+			/*
+			 * return quiet NaN
+			 */
+			Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check third operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd3p1)) {
+		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+			/* return infinity */
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		} else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Dbl_isone_signaling(opnd3p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd3p1);
+			}
+			/*
+			 * return quiet NaN
+ 			 */
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		}
+    	}
+
+	/*
+	 * Generate multiply mantissa
+	 */
+	if (Dbl_isnotzero_exponent(opnd1p1)) {
+		/* set hidden bit */
+		Dbl_clear_signexponent_set_hidden(opnd1p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Dbl_or_signs(opnd3p1,resultp1);
+				} else {
+					Dbl_and_signs(opnd3p1,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Dbl_iszero_exponent(opnd3p1) &&
+			         Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Dbl_signextendedsign(opnd3p1);
+				result_exponent = 0;
+                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
+                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+							unfl);
+                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized, adjust exponent */
+		Dbl_clear_signexponent(opnd1p1);
+		Dbl_leftshiftby1(opnd1p1,opnd1p2);
+		Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Dbl_isnotzero_exponent(opnd2p1)) {
+		Dbl_clear_signexponent_set_hidden(opnd2p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Dbl_or_signs(opnd3p1,resultp1);
+				} else {
+					Dbl_and_signs(opnd3p1,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Dbl_iszero_exponent(opnd3p1) &&
+			    Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Dbl_signextendedsign(opnd3p1);
+				result_exponent = 0;
+                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
+                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+							unfl);
+                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+                    		/* inexact = FALSE */
+				return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized; want to normalize */
+		Dbl_clear_signexponent(opnd2p1);
+		Dbl_leftshiftby1(opnd2p1,opnd2p2);
+		Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
+	}
+
+	/* Multiply the first two source mantissas together */
+
+	/* 
+	 * The intermediate result will be kept in tmpres,
+	 * which needs enough room for 106 bits of mantissa,
+	 * so lets call it a Double extended.
+	 */
+	Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+
+	/* 
+	 * Four bits at a time are inspected in each loop, and a 
+	 * simple shift and add multiply algorithm is used. 
+	 */ 
+	for (count = DBL_P-1; count >= 0; count -= 4) {
+		Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+		if (Dbit28p2(opnd1p2)) {
+	 		/* Fourword_add should be an ADD followed by 3 ADDC's */
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 
+			 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
+		}
+		if (Dbit29p2(opnd1p2)) {
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+			 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
+		}
+		if (Dbit30p2(opnd1p2)) {
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+			 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
+		}
+		if (Dbit31p2(opnd1p2)) {
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+			 opnd2p1, opnd2p2, 0, 0);
+		}
+		Dbl_rightshiftby4(opnd1p1,opnd1p2);
+	}
+	if (Is_dexthiddenoverflow(tmpresp1)) {
+		/* result mantissa >= 2 (mantissa overflow) */
+		mpy_exponent++;
+		Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+	}
+
+	/*
+	 * Restore the sign of the mpy result which was saved in resultp1.
+	 * The exponent will continue to be kept in mpy_exponent.
+	 */
+	Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
+
+	/* 
+	 * No rounding is required, since the result of the multiply
+	 * is exact in the extended format.
+	 */
+
+	/*
+	 * Now we are ready to perform the add portion of the operation.
+	 *
+	 * The exponents need to be kept as integers for now, since the
+	 * multiply result might not fit into the exponent field.  We
+	 * can't overflow or underflow because of this yet, since the
+	 * add could bring the final result back into range.
+	 */
+	add_exponent = Dbl_exponent(opnd3p1);
+
+	/*
+	 * Check for denormalized or zero add operand.
+	 */
+	if (add_exponent == 0) {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+			/* right is zero */
+			/* Left can't be zero and must be result.
+			 *
+			 * The final result is now in tmpres and mpy_exponent,
+			 * and needs to be rounded and squeezed back into
+			 * double precision format from double extended.
+			 */
+			result_exponent = mpy_exponent;
+			Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+				resultp1,resultp2,resultp3,resultp4);
+			sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
+			goto round;
+		}
+
+		/* 
+		 * Neither are zeroes.  
+		 * Adjust exponent and normalize add operand.
+		 */
+		sign_save = Dbl_signextendedsign(opnd3p1);	/* save sign */
+		Dbl_clear_signexponent(opnd3p1);
+		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+		Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
+		Dbl_set_sign(opnd3p1,sign_save);	/* restore sign */
+	} else {
+		Dbl_clear_exponent_set_hidden(opnd3p1);
+	}
+	/*
+	 * Copy opnd3 to the double extended variable called right.
+	 */
+	Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
+
+	/*
+	 * A zero "save" helps discover equal operands (for later),
+	 * and is used in swapping operands (if needed).
+	 */
+	Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+	/*
+	 * Compare magnitude of operands.
+	 */
+	Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
+	Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
+	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+	    Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
+		/*
+		 * Set the left operand to the larger one by XOR swap.
+		 * First finish the first word "save".
+		 */
+		Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
+		Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+		Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
+			rightp2,rightp3,rightp4);
+		/* also setup exponents used in rest of routine */
+		diff_exponent = add_exponent - mpy_exponent;
+		result_exponent = add_exponent;
+	} else {
+		/* also setup exponents used in rest of routine */
+		diff_exponent = mpy_exponent - add_exponent;
+		result_exponent = mpy_exponent;
+	}
+	/* Invariant: left is not smaller than right. */
+
+	/*
+	 * Special case alignment of operands that would force alignment
+	 * beyond the extent of the extension.  A further optimization
+	 * could special case this but only reduces the path length for
+	 * this infrequent case.
+	 */
+	if (diff_exponent > DBLEXT_THRESHOLD) {
+		diff_exponent = DBLEXT_THRESHOLD;
+	}
+
+	/* Align right operand by shifting it to the right */
+	Dblext_clear_sign(rightp1);
+	Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
+		/*shifted by*/diff_exponent);
+	
+	/* Treat sum and difference of the operands separately. */
+	if ((int)save < 0) {
+		/*
+		 * Difference of the two operands.  Overflow can occur if the
+		 * multiply overflowed.  A borrow can occur out of the hidden
+		 * bit and force a post normalization phase.
+		 */
+		Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+			rightp1,rightp2,rightp3,rightp4,
+			resultp1,resultp2,resultp3,resultp4);
+		sign_save = Dbl_signextendedsign(resultp1);
+		if (Dbl_iszero_hidden(resultp1)) {
+			/* Handle normalization */
+		/* A straight foward algorithm would now shift the
+		 * result and extension left until the hidden bit
+		 * becomes one.  Not all of the extension bits need
+		 * participate in the shift.  Only the two most 
+		 * significant bits (round and guard) are needed.
+		 * If only a single shift is needed then the guard
+		 * bit becomes a significant low order bit and the
+		 * extension must participate in the rounding.
+		 * If more than a single shift is needed, then all
+		 * bits to the right of the guard bit are zeros, 
+		 * and the guard bit may or may not be zero. */
+			Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+				resultp4);
+
+			/* Need to check for a zero result.  The sign and
+			 * exponent fields have already been zeroed.  The more
+			 * efficient test of the full object can be used.
+			 */
+			 if(Dblext_iszero(resultp1,resultp2,resultp3,resultp4)){
+				/* Must have been "x-x" or "x+(-x)". */
+				if (Is_rounding_mode(ROUNDMINUS))
+					Dbl_setone_sign(resultp1);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+			result_exponent--;
+
+			/* Look to see if normalization is finished. */
+			if (Dbl_isone_hidden(resultp1)) {
+				/* No further normalization is needed */
+				goto round;
+			}
+
+			/* Discover first one bit to determine shift amount.
+			 * Use a modified binary search.  We have already
+			 * shifted the result one position right and still
+			 * not found a one so the remainder of the extension
+			 * must be zero and simplifies rounding. */
+			/* Scan bytes */
+			while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
+				Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
+				result_exponent -= 8;
+			}
+			/* Now narrow it down to the nibble */
+			if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
+				/* The lower nibble contains the
+				 * normalizing one */
+				Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
+				result_exponent -= 4;
+			}
+			/* Select case where first bit is set (already
+			 * normalized) otherwise select the proper shift. */
+			jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
+			if (jumpsize <= 7) switch(jumpsize) {
+			case 1:
+				Dblext_leftshiftby3(resultp1,resultp2,resultp3,
+					resultp4);
+				result_exponent -= 3;
+				break;
+			case 2:
+			case 3:
+				Dblext_leftshiftby2(resultp1,resultp2,resultp3,
+					resultp4);
+				result_exponent -= 2;
+				break;
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+				Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+					resultp4);
+				result_exponent -= 1;
+				break;
+			}
+		} /* end if (hidden...)... */
+	/* Fall through and round */
+	} /* end if (save < 0)... */
+	else {
+		/* Add magnitudes */
+		Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+			rightp1,rightp2,rightp3,rightp4,
+			/*to*/resultp1,resultp2,resultp3,resultp4);
+		sign_save = Dbl_signextendedsign(resultp1);
+		if (Dbl_isone_hiddenoverflow(resultp1)) {
+	    		/* Prenormalization required. */
+	    		Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
+				resultp4);
+	    		result_exponent++;
+		} /* end if hiddenoverflow... */
+	} /* end else ...add magnitudes... */
+
+	/* Round the result.  If the extension and lower two words are
+	 * all zeros, then the result is exact.  Otherwise round in the
+	 * correct direction.  Underflow is possible. If a postnormalization
+	 * is necessary, then the mantissa is all zeros so no shift is needed.
+	 */
+  round:
+	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+		Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
+			result_exponent,is_tiny);
+	}
+	Dbl_set_sign(resultp1,/*using*/sign_save);
+	if (Dblext_isnotzero_mantissap3(resultp3) || 
+	    Dblext_isnotzero_mantissap4(resultp4)) {
+		inexact = TRUE;
+		switch(Rounding_mode()) {
+		case ROUNDNEAREST: /* The default. */
+			if (Dblext_isone_highp3(resultp3)) {
+				/* at least 1/2 ulp */
+				if (Dblext_isnotzero_low31p3(resultp3) ||
+				    Dblext_isnotzero_mantissap4(resultp4) ||
+				    Dblext_isone_lowp2(resultp2)) {
+					/* either exactly half way and odd or
+					 * more than 1/2ulp */
+					Dbl_increment(resultp1,resultp2);
+				}
+			}
+	    		break;
+
+		case ROUNDPLUS:
+	    		if (Dbl_iszero_sign(resultp1)) {
+				/* Round up positive results */
+				Dbl_increment(resultp1,resultp2);
+			}
+			break;
+	    
+		case ROUNDMINUS:
+	    		if (Dbl_isone_sign(resultp1)) {
+				/* Round down negative results */
+				Dbl_increment(resultp1,resultp2);
+			}
+	    
+		case ROUNDZERO:;
+			/* truncate is simple */
+		} /* end switch... */
+		if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+	}
+	if (result_exponent >= DBL_INFINITY_EXPONENT) {
+                /* trap if OVERFLOWTRAP enabled */
+                if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+                        Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_OVERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return (OPC_2E_OVERFLOWEXCEPTION);
+                }
+                inexact = TRUE;
+                Set_overflowflag();
+                /* set result to infinity or largest number */
+                Dbl_setoverflow(resultp1,resultp2);
+
+	} else if (result_exponent <= 0) {	/* underflow case */
+		if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                	Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_UNDERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+	    		return(OPC_2E_UNDERFLOWEXCEPTION);
+		}
+		else if (inexact && is_tiny) Set_underflowflag();
+	}
+	else Dbl_set_exponent(resultp1,result_exponent);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) 
+		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+		else Set_inexactflag();
+    	return(NOEXCEPTION);
+}
+
+/*
+ *  Double Floating-point Multiply Negate Fused Add
+ */
+
+dbl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+
+dbl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
+unsigned int *status;
+{
+	unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2, opnd3p1, opnd3p2;
+	register unsigned int tmpresp1, tmpresp2, tmpresp3, tmpresp4;
+	unsigned int rightp1, rightp2, rightp3, rightp4;
+	unsigned int resultp1, resultp2 = 0, resultp3 = 0, resultp4 = 0;
+	register int mpy_exponent, add_exponent, count;
+	boolean inexact = FALSE, is_tiny = FALSE;
+
+	unsigned int signlessleft1, signlessright1, save;
+	register int result_exponent, diff_exponent;
+	int sign_save, jumpsize;
+	
+	Dbl_copyfromptr(src1ptr,opnd1p1,opnd1p2);
+	Dbl_copyfromptr(src2ptr,opnd2p1,opnd2p2);
+	Dbl_copyfromptr(src3ptr,opnd3p1,opnd3p2);
+
+	/* 
+	 * set sign bit of result of multiply
+	 */
+	if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 
+		Dbl_setzerop1(resultp1);
+	else
+		Dbl_setnegativezerop1(resultp1); 
+
+	/*
+	 * Generate multiply exponent 
+	 */
+	mpy_exponent = Dbl_exponent(opnd1p1) + Dbl_exponent(opnd2p1) - DBL_BIAS;
+
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd1p1)) {
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			if (Dbl_isnotnan(opnd2p1,opnd2p2) &&
+			    Dbl_isnotnan(opnd3p1,opnd3p2)) {
+				if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) {
+					/* 
+					 * invalid since operands are infinity 
+					 * and zero 
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+			 	 * return infinity
+			 	 */
+				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+		 	 * is NaN; signaling or quiet?
+		 	 */
+			if (Dbl_isone_signaling(opnd1p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled()) 
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd1p1);
+			}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd2p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd2p1);
+				Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd3p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd3p1);
+				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/*
+		 	 * return quiet NaN
+		 	 */
+			Dbl_copytoptr(opnd1p1,opnd1p2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd2p1)) {
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			if (Dbl_isnotnan(opnd3p1,opnd3p2)) {
+				if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) {
+					/* 
+					 * invalid since multiply operands are
+					 * zero & infinity
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Dbl_makequietnan(opnd2p1,opnd2p2);
+					Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Dbl_isinfinity(opnd3p1,opnd3p2) &&
+				    (Dbl_sign(resultp1) ^ Dbl_sign(opnd3p1))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+				       		return(OPC_2E_INVALIDEXCEPTION);
+				       	Set_invalidflag();
+				       	Dbl_makequietnan(resultp1,resultp2);
+					Dbl_copytoptr(resultp1,resultp2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * return infinity
+				 */
+				Dbl_setinfinity_exponentmantissa(resultp1,resultp2);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Dbl_isone_signaling(opnd2p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd2p1);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Dbl_is_signalingnan(opnd3p1)) {
+			       	/* trap if INVALIDTRAP enabled */
+			       	if (Is_invalidtrap_enabled())
+				   		return(OPC_2E_INVALIDEXCEPTION);
+			       	/* make NaN quiet */
+			       	Set_invalidflag();
+			       	Dbl_set_quiet(opnd3p1);
+				Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+		       		return(NOEXCEPTION);
+			}
+			/*
+			 * return quiet NaN
+			 */
+			Dbl_copytoptr(opnd2p1,opnd2p2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check third operand for NaN's or infinity
+	 */
+	if (Dbl_isinfinity_exponent(opnd3p1)) {
+		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+			/* return infinity */
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		} else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Dbl_isone_signaling(opnd3p1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Dbl_set_quiet(opnd3p1);
+			}
+			/*
+			 * return quiet NaN
+ 			 */
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		}
+    	}
+
+	/*
+	 * Generate multiply mantissa
+	 */
+	if (Dbl_isnotzero_exponent(opnd1p1)) {
+		/* set hidden bit */
+		Dbl_clear_signexponent_set_hidden(opnd1p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Dbl_or_signs(opnd3p1,resultp1);
+				} else {
+					Dbl_and_signs(opnd3p1,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Dbl_iszero_exponent(opnd3p1) &&
+			         Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Dbl_signextendedsign(opnd3p1);
+				result_exponent = 0;
+                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
+                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+							unfl);
+                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized, adjust exponent */
+		Dbl_clear_signexponent(opnd1p1);
+		Dbl_leftshiftby1(opnd1p1,opnd1p2);
+		Dbl_normalize(opnd1p1,opnd1p2,mpy_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Dbl_isnotzero_exponent(opnd2p1)) {
+		Dbl_clear_signexponent_set_hidden(opnd2p1);
+	}
+	else {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Dbl_iszero_exponentmantissa(opnd3p1,opnd3p2)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Dbl_or_signs(opnd3p1,resultp1);
+				} else {
+					Dbl_and_signs(opnd3p1,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Dbl_iszero_exponent(opnd3p1) &&
+			    Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Dbl_signextendedsign(opnd3p1);
+				result_exponent = 0;
+                    		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+                    		Dbl_normalize(opnd3p1,opnd3p2,result_exponent);
+                    		Dbl_set_sign(opnd3p1,/*using*/sign_save);
+                    		Dbl_setwrapped_exponent(opnd3p1,result_exponent,
+							unfl);
+                    		Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Dbl_copytoptr(opnd3p1,opnd3p2,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized; want to normalize */
+		Dbl_clear_signexponent(opnd2p1);
+		Dbl_leftshiftby1(opnd2p1,opnd2p2);
+		Dbl_normalize(opnd2p1,opnd2p2,mpy_exponent);
+	}
+
+	/* Multiply the first two source mantissas together */
+
+	/* 
+	 * The intermediate result will be kept in tmpres,
+	 * which needs enough room for 106 bits of mantissa,
+	 * so lets call it a Double extended.
+	 */
+	Dblext_setzero(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+
+	/* 
+	 * Four bits at a time are inspected in each loop, and a 
+	 * simple shift and add multiply algorithm is used. 
+	 */ 
+	for (count = DBL_P-1; count >= 0; count -= 4) {
+		Dblext_rightshiftby4(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+		if (Dbit28p2(opnd1p2)) {
+	 		/* Fourword_add should be an ADD followed by 3 ADDC's */
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4, 
+			 opnd2p1<<3 | opnd2p2>>29, opnd2p2<<3, 0, 0);
+		}
+		if (Dbit29p2(opnd1p2)) {
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+			 opnd2p1<<2 | opnd2p2>>30, opnd2p2<<2, 0, 0);
+		}
+		if (Dbit30p2(opnd1p2)) {
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+			 opnd2p1<<1 | opnd2p2>>31, opnd2p2<<1, 0, 0);
+		}
+		if (Dbit31p2(opnd1p2)) {
+			Fourword_add(tmpresp1, tmpresp2, tmpresp3, tmpresp4,
+			 opnd2p1, opnd2p2, 0, 0);
+		}
+		Dbl_rightshiftby4(opnd1p1,opnd1p2);
+	}
+	if (Is_dexthiddenoverflow(tmpresp1)) {
+		/* result mantissa >= 2 (mantissa overflow) */
+		mpy_exponent++;
+		Dblext_rightshiftby1(tmpresp1,tmpresp2,tmpresp3,tmpresp4);
+	}
+
+	/*
+	 * Restore the sign of the mpy result which was saved in resultp1.
+	 * The exponent will continue to be kept in mpy_exponent.
+	 */
+	Dblext_set_sign(tmpresp1,Dbl_sign(resultp1));
+
+	/* 
+	 * No rounding is required, since the result of the multiply
+	 * is exact in the extended format.
+	 */
+
+	/*
+	 * Now we are ready to perform the add portion of the operation.
+	 *
+	 * The exponents need to be kept as integers for now, since the
+	 * multiply result might not fit into the exponent field.  We
+	 * can't overflow or underflow because of this yet, since the
+	 * add could bring the final result back into range.
+	 */
+	add_exponent = Dbl_exponent(opnd3p1);
+
+	/*
+	 * Check for denormalized or zero add operand.
+	 */
+	if (add_exponent == 0) {
+		/* check for zero */
+		if (Dbl_iszero_mantissa(opnd3p1,opnd3p2)) {
+			/* right is zero */
+			/* Left can't be zero and must be result.
+			 *
+			 * The final result is now in tmpres and mpy_exponent,
+			 * and needs to be rounded and squeezed back into
+			 * double precision format from double extended.
+			 */
+			result_exponent = mpy_exponent;
+			Dblext_copy(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+				resultp1,resultp2,resultp3,resultp4);
+			sign_save = Dbl_signextendedsign(resultp1);/*save sign*/
+			goto round;
+		}
+
+		/* 
+		 * Neither are zeroes.  
+		 * Adjust exponent and normalize add operand.
+		 */
+		sign_save = Dbl_signextendedsign(opnd3p1);	/* save sign */
+		Dbl_clear_signexponent(opnd3p1);
+		Dbl_leftshiftby1(opnd3p1,opnd3p2);
+		Dbl_normalize(opnd3p1,opnd3p2,add_exponent);
+		Dbl_set_sign(opnd3p1,sign_save);	/* restore sign */
+	} else {
+		Dbl_clear_exponent_set_hidden(opnd3p1);
+	}
+	/*
+	 * Copy opnd3 to the double extended variable called right.
+	 */
+	Dbl_copyto_dblext(opnd3p1,opnd3p2,rightp1,rightp2,rightp3,rightp4);
+
+	/*
+	 * A zero "save" helps discover equal operands (for later),
+	 * and is used in swapping operands (if needed).
+	 */
+	Dblext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+	/*
+	 * Compare magnitude of operands.
+	 */
+	Dblext_copytoint_exponentmantissap1(tmpresp1,signlessleft1);
+	Dblext_copytoint_exponentmantissap1(rightp1,signlessright1);
+	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+	    Dblext_ismagnitudeless(tmpresp2,rightp2,signlessleft1,signlessright1)){
+		/*
+		 * Set the left operand to the larger one by XOR swap.
+		 * First finish the first word "save".
+		 */
+		Dblext_xorfromintp1(save,rightp1,/*to*/rightp1);
+		Dblext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+		Dblext_swap_lower(tmpresp2,tmpresp3,tmpresp4,
+			rightp2,rightp3,rightp4);
+		/* also setup exponents used in rest of routine */
+		diff_exponent = add_exponent - mpy_exponent;
+		result_exponent = add_exponent;
+	} else {
+		/* also setup exponents used in rest of routine */
+		diff_exponent = mpy_exponent - add_exponent;
+		result_exponent = mpy_exponent;
+	}
+	/* Invariant: left is not smaller than right. */
+
+	/*
+	 * Special case alignment of operands that would force alignment
+	 * beyond the extent of the extension.  A further optimization
+	 * could special case this but only reduces the path length for
+	 * this infrequent case.
+	 */
+	if (diff_exponent > DBLEXT_THRESHOLD) {
+		diff_exponent = DBLEXT_THRESHOLD;
+	}
+
+	/* Align right operand by shifting it to the right */
+	Dblext_clear_sign(rightp1);
+	Dblext_right_align(rightp1,rightp2,rightp3,rightp4,
+		/*shifted by*/diff_exponent);
+	
+	/* Treat sum and difference of the operands separately. */
+	if ((int)save < 0) {
+		/*
+		 * Difference of the two operands.  Overflow can occur if the
+		 * multiply overflowed.  A borrow can occur out of the hidden
+		 * bit and force a post normalization phase.
+		 */
+		Dblext_subtract(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+			rightp1,rightp2,rightp3,rightp4,
+			resultp1,resultp2,resultp3,resultp4);
+		sign_save = Dbl_signextendedsign(resultp1);
+		if (Dbl_iszero_hidden(resultp1)) {
+			/* Handle normalization */
+		/* A straight foward algorithm would now shift the
+		 * result and extension left until the hidden bit
+		 * becomes one.  Not all of the extension bits need
+		 * participate in the shift.  Only the two most 
+		 * significant bits (round and guard) are needed.
+		 * If only a single shift is needed then the guard
+		 * bit becomes a significant low order bit and the
+		 * extension must participate in the rounding.
+		 * If more than a single shift is needed, then all
+		 * bits to the right of the guard bit are zeros, 
+		 * and the guard bit may or may not be zero. */
+			Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+				resultp4);
+
+			/* Need to check for a zero result.  The sign and
+			 * exponent fields have already been zeroed.  The more
+			 * efficient test of the full object can be used.
+			 */
+			 if (Dblext_iszero(resultp1,resultp2,resultp3,resultp4)) {
+				/* Must have been "x-x" or "x+(-x)". */
+				if (Is_rounding_mode(ROUNDMINUS))
+					Dbl_setone_sign(resultp1);
+				Dbl_copytoptr(resultp1,resultp2,dstptr);
+				return(NOEXCEPTION);
+			}
+			result_exponent--;
+
+			/* Look to see if normalization is finished. */
+			if (Dbl_isone_hidden(resultp1)) {
+				/* No further normalization is needed */
+				goto round;
+			}
+
+			/* Discover first one bit to determine shift amount.
+			 * Use a modified binary search.  We have already
+			 * shifted the result one position right and still
+			 * not found a one so the remainder of the extension
+			 * must be zero and simplifies rounding. */
+			/* Scan bytes */
+			while (Dbl_iszero_hiddenhigh7mantissa(resultp1)) {
+				Dblext_leftshiftby8(resultp1,resultp2,resultp3,resultp4);
+				result_exponent -= 8;
+			}
+			/* Now narrow it down to the nibble */
+			if (Dbl_iszero_hiddenhigh3mantissa(resultp1)) {
+				/* The lower nibble contains the
+				 * normalizing one */
+				Dblext_leftshiftby4(resultp1,resultp2,resultp3,resultp4);
+				result_exponent -= 4;
+			}
+			/* Select case where first bit is set (already
+			 * normalized) otherwise select the proper shift. */
+			jumpsize = Dbl_hiddenhigh3mantissa(resultp1);
+			if (jumpsize <= 7) switch(jumpsize) {
+			case 1:
+				Dblext_leftshiftby3(resultp1,resultp2,resultp3,
+					resultp4);
+				result_exponent -= 3;
+				break;
+			case 2:
+			case 3:
+				Dblext_leftshiftby2(resultp1,resultp2,resultp3,
+					resultp4);
+				result_exponent -= 2;
+				break;
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+				Dblext_leftshiftby1(resultp1,resultp2,resultp3,
+					resultp4);
+				result_exponent -= 1;
+				break;
+			}
+		} /* end if (hidden...)... */
+	/* Fall through and round */
+	} /* end if (save < 0)... */
+	else {
+		/* Add magnitudes */
+		Dblext_addition(tmpresp1,tmpresp2,tmpresp3,tmpresp4,
+			rightp1,rightp2,rightp3,rightp4,
+			/*to*/resultp1,resultp2,resultp3,resultp4);
+		sign_save = Dbl_signextendedsign(resultp1);
+		if (Dbl_isone_hiddenoverflow(resultp1)) {
+	    		/* Prenormalization required. */
+	    		Dblext_arithrightshiftby1(resultp1,resultp2,resultp3,
+				resultp4);
+	    		result_exponent++;
+		} /* end if hiddenoverflow... */
+	} /* end else ...add magnitudes... */
+
+	/* Round the result.  If the extension and lower two words are
+	 * all zeros, then the result is exact.  Otherwise round in the
+	 * correct direction.  Underflow is possible. If a postnormalization
+	 * is necessary, then the mantissa is all zeros so no shift is needed.
+	 */
+  round:
+	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+		Dblext_denormalize(resultp1,resultp2,resultp3,resultp4,
+			result_exponent,is_tiny);
+	}
+	Dbl_set_sign(resultp1,/*using*/sign_save);
+	if (Dblext_isnotzero_mantissap3(resultp3) || 
+	    Dblext_isnotzero_mantissap4(resultp4)) {
+		inexact = TRUE;
+		switch(Rounding_mode()) {
+		case ROUNDNEAREST: /* The default. */
+			if (Dblext_isone_highp3(resultp3)) {
+				/* at least 1/2 ulp */
+				if (Dblext_isnotzero_low31p3(resultp3) ||
+				    Dblext_isnotzero_mantissap4(resultp4) ||
+				    Dblext_isone_lowp2(resultp2)) {
+					/* either exactly half way and odd or
+					 * more than 1/2ulp */
+					Dbl_increment(resultp1,resultp2);
+				}
+			}
+	    		break;
+
+		case ROUNDPLUS:
+	    		if (Dbl_iszero_sign(resultp1)) {
+				/* Round up positive results */
+				Dbl_increment(resultp1,resultp2);
+			}
+			break;
+	    
+		case ROUNDMINUS:
+	    		if (Dbl_isone_sign(resultp1)) {
+				/* Round down negative results */
+				Dbl_increment(resultp1,resultp2);
+			}
+	    
+		case ROUNDZERO:;
+			/* truncate is simple */
+		} /* end switch... */
+		if (Dbl_isone_hiddenoverflow(resultp1)) result_exponent++;
+	}
+	if (result_exponent >= DBL_INFINITY_EXPONENT) {
+		/* Overflow */
+		if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Dbl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+                        Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_OVERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return (OPC_2E_OVERFLOWEXCEPTION);
+		}
+		inexact = TRUE;
+		Set_overflowflag();
+		Dbl_setoverflow(resultp1,resultp2);
+	} else if (result_exponent <= 0) {	/* underflow case */
+		if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                	Dbl_setwrapped_exponent(resultp1,result_exponent,unfl);
+			Dbl_copytoptr(resultp1,resultp2,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_UNDERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+	    		return(OPC_2E_UNDERFLOWEXCEPTION);
+		}
+		else if (inexact && is_tiny) Set_underflowflag();
+	}
+	else Dbl_set_exponent(resultp1,result_exponent);
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) 
+		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+		else Set_inexactflag();
+    	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Floating-point Multiply Fused Add
+ */
+
+sgl_fmpyfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+
+sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
+unsigned int *status;
+{
+	unsigned int opnd1, opnd2, opnd3;
+	register unsigned int tmpresp1, tmpresp2;
+	unsigned int rightp1, rightp2;
+	unsigned int resultp1, resultp2 = 0;
+	register int mpy_exponent, add_exponent, count;
+	boolean inexact = FALSE, is_tiny = FALSE;
+
+	unsigned int signlessleft1, signlessright1, save;
+	register int result_exponent, diff_exponent;
+	int sign_save, jumpsize;
+	
+	Sgl_copyfromptr(src1ptr,opnd1);
+	Sgl_copyfromptr(src2ptr,opnd2);
+	Sgl_copyfromptr(src3ptr,opnd3);
+
+	/* 
+	 * set sign bit of result of multiply
+	 */
+	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) 
+		Sgl_setnegativezero(resultp1); 
+	else Sgl_setzero(resultp1);
+
+	/*
+	 * Generate multiply exponent 
+	 */
+	mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
+
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd1)) {
+		if (Sgl_iszero_mantissa(opnd1)) {
+			if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
+				if (Sgl_iszero_exponentmantissa(opnd2)) {
+					/* 
+					 * invalid since operands are infinity 
+					 * and zero 
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Sgl_makequietnan(resultp1);
+					Sgl_copytoptr(resultp1,dstptr);
+					return(NOEXCEPTION);
+				}
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Sgl_isinfinity(opnd3) &&
+				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Sgl_makequietnan(resultp1);
+					Sgl_copytoptr(resultp1,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+			 	 * return infinity
+			 	 */
+				Sgl_setinfinity_exponentmantissa(resultp1);
+				Sgl_copytoptr(resultp1,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+		 	 * is NaN; signaling or quiet?
+		 	 */
+			if (Sgl_isone_signaling(opnd1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled()) 
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd1);
+			}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd2)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd2);
+				Sgl_copytoptr(opnd2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd3)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd3);
+				Sgl_copytoptr(opnd3,dstptr);
+				return(NOEXCEPTION);
+			}
+			/*
+		 	 * return quiet NaN
+		 	 */
+			Sgl_copytoptr(opnd1,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd2)) {
+		if (Sgl_iszero_mantissa(opnd2)) {
+			if (Sgl_isnotnan(opnd3)) {
+				if (Sgl_iszero_exponentmantissa(opnd1)) {
+					/* 
+					 * invalid since multiply operands are
+					 * zero & infinity
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Sgl_makequietnan(opnd2);
+					Sgl_copytoptr(opnd2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Sgl_isinfinity(opnd3) &&
+				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+				       		return(OPC_2E_INVALIDEXCEPTION);
+				       	Set_invalidflag();
+				       	Sgl_makequietnan(resultp1);
+					Sgl_copytoptr(resultp1,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * return infinity
+				 */
+				Sgl_setinfinity_exponentmantissa(resultp1);
+				Sgl_copytoptr(resultp1,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Sgl_isone_signaling(opnd2)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd2);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd3)) {
+			       	/* trap if INVALIDTRAP enabled */
+			       	if (Is_invalidtrap_enabled())
+				   		return(OPC_2E_INVALIDEXCEPTION);
+			       	/* make NaN quiet */
+			       	Set_invalidflag();
+			       	Sgl_set_quiet(opnd3);
+				Sgl_copytoptr(opnd3,dstptr);
+		       		return(NOEXCEPTION);
+			}
+			/*
+			 * return quiet NaN
+			 */
+			Sgl_copytoptr(opnd2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check third operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd3)) {
+		if (Sgl_iszero_mantissa(opnd3)) {
+			/* return infinity */
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		} else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Sgl_isone_signaling(opnd3)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd3);
+			}
+			/*
+			 * return quiet NaN
+ 			 */
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		}
+    	}
+
+	/*
+	 * Generate multiply mantissa
+	 */
+	if (Sgl_isnotzero_exponent(opnd1)) {
+		/* set hidden bit */
+		Sgl_clear_signexponent_set_hidden(opnd1);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd1)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Sgl_iszero_exponentmantissa(opnd3)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Sgl_or_signs(opnd3,resultp1);
+				} else {
+					Sgl_and_signs(opnd3,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Sgl_iszero_exponent(opnd3) &&
+			         Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Sgl_signextendedsign(opnd3);
+				result_exponent = 0;
+                    		Sgl_leftshiftby1(opnd3);
+                    		Sgl_normalize(opnd3,result_exponent);
+                    		Sgl_set_sign(opnd3,/*using*/sign_save);
+                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
+							unfl);
+                    		Sgl_copytoptr(opnd3,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized, adjust exponent */
+		Sgl_clear_signexponent(opnd1);
+		Sgl_leftshiftby1(opnd1);
+		Sgl_normalize(opnd1,mpy_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Sgl_isnotzero_exponent(opnd2)) {
+		Sgl_clear_signexponent_set_hidden(opnd2);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd2)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Sgl_iszero_exponentmantissa(opnd3)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Sgl_or_signs(opnd3,resultp1);
+				} else {
+					Sgl_and_signs(opnd3,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Sgl_iszero_exponent(opnd3) &&
+			    Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Sgl_signextendedsign(opnd3);
+				result_exponent = 0;
+                    		Sgl_leftshiftby1(opnd3);
+                    		Sgl_normalize(opnd3,result_exponent);
+                    		Sgl_set_sign(opnd3,/*using*/sign_save);
+                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
+							unfl);
+                    		Sgl_copytoptr(opnd3,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized; want to normalize */
+		Sgl_clear_signexponent(opnd2);
+		Sgl_leftshiftby1(opnd2);
+		Sgl_normalize(opnd2,mpy_exponent);
+	}
+
+	/* Multiply the first two source mantissas together */
+
+	/* 
+	 * The intermediate result will be kept in tmpres,
+	 * which needs enough room for 106 bits of mantissa,
+	 * so lets call it a Double extended.
+	 */
+	Sglext_setzero(tmpresp1,tmpresp2);
+
+	/* 
+	 * Four bits at a time are inspected in each loop, and a 
+	 * simple shift and add multiply algorithm is used. 
+	 */ 
+	for (count = SGL_P-1; count >= 0; count -= 4) {
+		Sglext_rightshiftby4(tmpresp1,tmpresp2);
+		if (Sbit28(opnd1)) {
+	 		/* Twoword_add should be an ADD followed by 2 ADDC's */
+			Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
+		}
+		if (Sbit29(opnd1)) {
+			Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
+		}
+		if (Sbit30(opnd1)) {
+			Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
+		}
+		if (Sbit31(opnd1)) {
+			Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
+		}
+		Sgl_rightshiftby4(opnd1);
+	}
+	if (Is_sexthiddenoverflow(tmpresp1)) {
+		/* result mantissa >= 2 (mantissa overflow) */
+		mpy_exponent++;
+		Sglext_rightshiftby4(tmpresp1,tmpresp2);
+	} else {
+		Sglext_rightshiftby3(tmpresp1,tmpresp2);
+	}
+
+	/*
+	 * Restore the sign of the mpy result which was saved in resultp1.
+	 * The exponent will continue to be kept in mpy_exponent.
+	 */
+	Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
+
+	/* 
+	 * No rounding is required, since the result of the multiply
+	 * is exact in the extended format.
+	 */
+
+	/*
+	 * Now we are ready to perform the add portion of the operation.
+	 *
+	 * The exponents need to be kept as integers for now, since the
+	 * multiply result might not fit into the exponent field.  We
+	 * can't overflow or underflow because of this yet, since the
+	 * add could bring the final result back into range.
+	 */
+	add_exponent = Sgl_exponent(opnd3);
+
+	/*
+	 * Check for denormalized or zero add operand.
+	 */
+	if (add_exponent == 0) {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd3)) {
+			/* right is zero */
+			/* Left can't be zero and must be result.
+			 *
+			 * The final result is now in tmpres and mpy_exponent,
+			 * and needs to be rounded and squeezed back into
+			 * double precision format from double extended.
+			 */
+			result_exponent = mpy_exponent;
+			Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
+			sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
+			goto round;
+		}
+
+		/* 
+		 * Neither are zeroes.  
+		 * Adjust exponent and normalize add operand.
+		 */
+		sign_save = Sgl_signextendedsign(opnd3);	/* save sign */
+		Sgl_clear_signexponent(opnd3);
+		Sgl_leftshiftby1(opnd3);
+		Sgl_normalize(opnd3,add_exponent);
+		Sgl_set_sign(opnd3,sign_save);		/* restore sign */
+	} else {
+		Sgl_clear_exponent_set_hidden(opnd3);
+	}
+	/*
+	 * Copy opnd3 to the double extended variable called right.
+	 */
+	Sgl_copyto_sglext(opnd3,rightp1,rightp2);
+
+	/*
+	 * A zero "save" helps discover equal operands (for later),
+	 * and is used in swapping operands (if needed).
+	 */
+	Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+	/*
+	 * Compare magnitude of operands.
+	 */
+	Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
+	Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
+	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+	    Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
+		/*
+		 * Set the left operand to the larger one by XOR swap.
+		 * First finish the first word "save".
+		 */
+		Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
+		Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+		Sglext_swap_lower(tmpresp2,rightp2);
+		/* also setup exponents used in rest of routine */
+		diff_exponent = add_exponent - mpy_exponent;
+		result_exponent = add_exponent;
+	} else {
+		/* also setup exponents used in rest of routine */
+		diff_exponent = mpy_exponent - add_exponent;
+		result_exponent = mpy_exponent;
+	}
+	/* Invariant: left is not smaller than right. */
+
+	/*
+	 * Special case alignment of operands that would force alignment
+	 * beyond the extent of the extension.  A further optimization
+	 * could special case this but only reduces the path length for
+	 * this infrequent case.
+	 */
+	if (diff_exponent > SGLEXT_THRESHOLD) {
+		diff_exponent = SGLEXT_THRESHOLD;
+	}
+
+	/* Align right operand by shifting it to the right */
+	Sglext_clear_sign(rightp1);
+	Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
+	
+	/* Treat sum and difference of the operands separately. */
+	if ((int)save < 0) {
+		/*
+		 * Difference of the two operands.  Overflow can occur if the
+		 * multiply overflowed.  A borrow can occur out of the hidden
+		 * bit and force a post normalization phase.
+		 */
+		Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
+			resultp1,resultp2);
+		sign_save = Sgl_signextendedsign(resultp1);
+		if (Sgl_iszero_hidden(resultp1)) {
+			/* Handle normalization */
+		/* A straight foward algorithm would now shift the
+		 * result and extension left until the hidden bit
+		 * becomes one.  Not all of the extension bits need
+		 * participate in the shift.  Only the two most 
+		 * significant bits (round and guard) are needed.
+		 * If only a single shift is needed then the guard
+		 * bit becomes a significant low order bit and the
+		 * extension must participate in the rounding.
+		 * If more than a single shift is needed, then all
+		 * bits to the right of the guard bit are zeros, 
+		 * and the guard bit may or may not be zero. */
+			Sglext_leftshiftby1(resultp1,resultp2);
+
+			/* Need to check for a zero result.  The sign and
+			 * exponent fields have already been zeroed.  The more
+			 * efficient test of the full object can be used.
+			 */
+			 if (Sglext_iszero(resultp1,resultp2)) {
+				/* Must have been "x-x" or "x+(-x)". */
+				if (Is_rounding_mode(ROUNDMINUS))
+					Sgl_setone_sign(resultp1);
+				Sgl_copytoptr(resultp1,dstptr);
+				return(NOEXCEPTION);
+			}
+			result_exponent--;
+
+			/* Look to see if normalization is finished. */
+			if (Sgl_isone_hidden(resultp1)) {
+				/* No further normalization is needed */
+				goto round;
+			}
+
+			/* Discover first one bit to determine shift amount.
+			 * Use a modified binary search.  We have already
+			 * shifted the result one position right and still
+			 * not found a one so the remainder of the extension
+			 * must be zero and simplifies rounding. */
+			/* Scan bytes */
+			while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
+				Sglext_leftshiftby8(resultp1,resultp2);
+				result_exponent -= 8;
+			}
+			/* Now narrow it down to the nibble */
+			if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
+				/* The lower nibble contains the
+				 * normalizing one */
+				Sglext_leftshiftby4(resultp1,resultp2);
+				result_exponent -= 4;
+			}
+			/* Select case where first bit is set (already
+			 * normalized) otherwise select the proper shift. */
+			jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
+			if (jumpsize <= 7) switch(jumpsize) {
+			case 1:
+				Sglext_leftshiftby3(resultp1,resultp2);
+				result_exponent -= 3;
+				break;
+			case 2:
+			case 3:
+				Sglext_leftshiftby2(resultp1,resultp2);
+				result_exponent -= 2;
+				break;
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+				Sglext_leftshiftby1(resultp1,resultp2);
+				result_exponent -= 1;
+				break;
+			}
+		} /* end if (hidden...)... */
+	/* Fall through and round */
+	} /* end if (save < 0)... */
+	else {
+		/* Add magnitudes */
+		Sglext_addition(tmpresp1,tmpresp2,
+			rightp1,rightp2, /*to*/resultp1,resultp2);
+		sign_save = Sgl_signextendedsign(resultp1);
+		if (Sgl_isone_hiddenoverflow(resultp1)) {
+	    		/* Prenormalization required. */
+	    		Sglext_arithrightshiftby1(resultp1,resultp2);
+	    		result_exponent++;
+		} /* end if hiddenoverflow... */
+	} /* end else ...add magnitudes... */
+
+	/* Round the result.  If the extension and lower two words are
+	 * all zeros, then the result is exact.  Otherwise round in the
+	 * correct direction.  Underflow is possible. If a postnormalization
+	 * is necessary, then the mantissa is all zeros so no shift is needed.
+	 */
+  round:
+	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+		Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
+	}
+	Sgl_set_sign(resultp1,/*using*/sign_save);
+	if (Sglext_isnotzero_mantissap2(resultp2)) {
+		inexact = TRUE;
+		switch(Rounding_mode()) {
+		case ROUNDNEAREST: /* The default. */
+			if (Sglext_isone_highp2(resultp2)) {
+				/* at least 1/2 ulp */
+				if (Sglext_isnotzero_low31p2(resultp2) ||
+				    Sglext_isone_lowp1(resultp1)) {
+					/* either exactly half way and odd or
+					 * more than 1/2ulp */
+					Sgl_increment(resultp1);
+				}
+			}
+	    		break;
+
+		case ROUNDPLUS:
+	    		if (Sgl_iszero_sign(resultp1)) {
+				/* Round up positive results */
+				Sgl_increment(resultp1);
+			}
+			break;
+	    
+		case ROUNDMINUS:
+	    		if (Sgl_isone_sign(resultp1)) {
+				/* Round down negative results */
+				Sgl_increment(resultp1);
+			}
+	    
+		case ROUNDZERO:;
+			/* truncate is simple */
+		} /* end switch... */
+		if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
+	}
+	if (result_exponent >= SGL_INFINITY_EXPONENT) {
+		/* Overflow */
+		if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+                        Sgl_copytoptr(resultp1,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_OVERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return (OPC_2E_OVERFLOWEXCEPTION);
+		}
+		inexact = TRUE;
+		Set_overflowflag();
+		Sgl_setoverflow(resultp1);
+	} else if (result_exponent <= 0) {	/* underflow case */
+		if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                	Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
+			Sgl_copytoptr(resultp1,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_UNDERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+	    		return(OPC_2E_UNDERFLOWEXCEPTION);
+		}
+		else if (inexact && is_tiny) Set_underflowflag();
+	}
+	else Sgl_set_exponent(resultp1,result_exponent);
+	Sgl_copytoptr(resultp1,dstptr);
+	if (inexact) 
+		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+		else Set_inexactflag();
+    	return(NOEXCEPTION);
+}
+
+/*
+ *  Single Floating-point Multiply Negate Fused Add
+ */
+
+sgl_fmpynfadd(src1ptr,src2ptr,src3ptr,status,dstptr)
+
+sgl_floating_point *src1ptr, *src2ptr, *src3ptr, *dstptr;
+unsigned int *status;
+{
+	unsigned int opnd1, opnd2, opnd3;
+	register unsigned int tmpresp1, tmpresp2;
+	unsigned int rightp1, rightp2;
+	unsigned int resultp1, resultp2 = 0;
+	register int mpy_exponent, add_exponent, count;
+	boolean inexact = FALSE, is_tiny = FALSE;
+
+	unsigned int signlessleft1, signlessright1, save;
+	register int result_exponent, diff_exponent;
+	int sign_save, jumpsize;
+	
+	Sgl_copyfromptr(src1ptr,opnd1);
+	Sgl_copyfromptr(src2ptr,opnd2);
+	Sgl_copyfromptr(src3ptr,opnd3);
+
+	/* 
+	 * set sign bit of result of multiply
+	 */
+	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) 
+		Sgl_setzero(resultp1);
+	else 
+		Sgl_setnegativezero(resultp1); 
+
+	/*
+	 * Generate multiply exponent 
+	 */
+	mpy_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
+
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd1)) {
+		if (Sgl_iszero_mantissa(opnd1)) {
+			if (Sgl_isnotnan(opnd2) && Sgl_isnotnan(opnd3)) {
+				if (Sgl_iszero_exponentmantissa(opnd2)) {
+					/* 
+					 * invalid since operands are infinity 
+					 * and zero 
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Sgl_makequietnan(resultp1);
+					Sgl_copytoptr(resultp1,dstptr);
+					return(NOEXCEPTION);
+				}
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Sgl_isinfinity(opnd3) &&
+				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Sgl_makequietnan(resultp1);
+					Sgl_copytoptr(resultp1,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+			 	 * return infinity
+			 	 */
+				Sgl_setinfinity_exponentmantissa(resultp1);
+				Sgl_copytoptr(resultp1,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+		 	 * is NaN; signaling or quiet?
+		 	 */
+			if (Sgl_isone_signaling(opnd1)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled()) 
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd1);
+			}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd2)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd2);
+				Sgl_copytoptr(opnd2,dstptr);
+				return(NOEXCEPTION);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd3)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+			    		return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd3);
+				Sgl_copytoptr(opnd3,dstptr);
+				return(NOEXCEPTION);
+			}
+			/*
+		 	 * return quiet NaN
+		 	 */
+			Sgl_copytoptr(opnd1,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd2)) {
+		if (Sgl_iszero_mantissa(opnd2)) {
+			if (Sgl_isnotnan(opnd3)) {
+				if (Sgl_iszero_exponentmantissa(opnd1)) {
+					/* 
+					 * invalid since multiply operands are
+					 * zero & infinity
+					 */
+					if (Is_invalidtrap_enabled())
+						return(OPC_2E_INVALIDEXCEPTION);
+					Set_invalidflag();
+					Sgl_makequietnan(opnd2);
+					Sgl_copytoptr(opnd2,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * Check third operand for infinity with a
+				 *  sign opposite of the multiply result
+				 */
+				if (Sgl_isinfinity(opnd3) &&
+				    (Sgl_sign(resultp1) ^ Sgl_sign(opnd3))) {
+					/* 
+					 * invalid since attempting a magnitude
+					 * subtraction of infinities
+					 */
+					if (Is_invalidtrap_enabled())
+				       		return(OPC_2E_INVALIDEXCEPTION);
+				       	Set_invalidflag();
+				       	Sgl_makequietnan(resultp1);
+					Sgl_copytoptr(resultp1,dstptr);
+					return(NOEXCEPTION);
+				}
+
+				/*
+				 * return infinity
+				 */
+				Sgl_setinfinity_exponentmantissa(resultp1);
+				Sgl_copytoptr(resultp1,dstptr);
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Sgl_isone_signaling(opnd2)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd2);
+			}
+			/* 
+			 * is third operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd3)) {
+			       	/* trap if INVALIDTRAP enabled */
+			       	if (Is_invalidtrap_enabled())
+				   		return(OPC_2E_INVALIDEXCEPTION);
+			       	/* make NaN quiet */
+			       	Set_invalidflag();
+			       	Sgl_set_quiet(opnd3);
+				Sgl_copytoptr(opnd3,dstptr);
+		       		return(NOEXCEPTION);
+			}
+			/*
+			 * return quiet NaN
+			 */
+			Sgl_copytoptr(opnd2,dstptr);
+			return(NOEXCEPTION);
+		}
+	}
+
+	/*
+	 * check third operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd3)) {
+		if (Sgl_iszero_mantissa(opnd3)) {
+			/* return infinity */
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		} else {
+			/*
+			 * is NaN; signaling or quiet?
+			 */
+			if (Sgl_isone_signaling(opnd3)) {
+				/* trap if INVALIDTRAP enabled */
+				if (Is_invalidtrap_enabled())
+					return(OPC_2E_INVALIDEXCEPTION);
+				/* make NaN quiet */
+				Set_invalidflag();
+				Sgl_set_quiet(opnd3);
+			}
+			/*
+			 * return quiet NaN
+ 			 */
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		}
+    	}
+
+	/*
+	 * Generate multiply mantissa
+	 */
+	if (Sgl_isnotzero_exponent(opnd1)) {
+		/* set hidden bit */
+		Sgl_clear_signexponent_set_hidden(opnd1);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd1)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Sgl_iszero_exponentmantissa(opnd3)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Sgl_or_signs(opnd3,resultp1);
+				} else {
+					Sgl_and_signs(opnd3,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Sgl_iszero_exponent(opnd3) &&
+			         Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Sgl_signextendedsign(opnd3);
+				result_exponent = 0;
+                    		Sgl_leftshiftby1(opnd3);
+                    		Sgl_normalize(opnd3,result_exponent);
+                    		Sgl_set_sign(opnd3,/*using*/sign_save);
+                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
+							unfl);
+                    		Sgl_copytoptr(opnd3,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized, adjust exponent */
+		Sgl_clear_signexponent(opnd1);
+		Sgl_leftshiftby1(opnd1);
+		Sgl_normalize(opnd1,mpy_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Sgl_isnotzero_exponent(opnd2)) {
+		Sgl_clear_signexponent_set_hidden(opnd2);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd2)) {
+			/*
+			 * Perform the add opnd3 with zero here.
+			 */
+			if (Sgl_iszero_exponentmantissa(opnd3)) {
+				if (Is_rounding_mode(ROUNDMINUS)) {
+					Sgl_or_signs(opnd3,resultp1);
+				} else {
+					Sgl_and_signs(opnd3,resultp1);
+				}
+			}
+			/*
+			 * Now let's check for trapped underflow case.
+			 */
+			else if (Sgl_iszero_exponent(opnd3) &&
+			    Is_underflowtrap_enabled()) {
+                    		/* need to normalize results mantissa */
+                    		sign_save = Sgl_signextendedsign(opnd3);
+				result_exponent = 0;
+                    		Sgl_leftshiftby1(opnd3);
+                    		Sgl_normalize(opnd3,result_exponent);
+                    		Sgl_set_sign(opnd3,/*using*/sign_save);
+                    		Sgl_setwrapped_exponent(opnd3,result_exponent,
+							unfl);
+                    		Sgl_copytoptr(opnd3,dstptr);
+                    		/* inexact = FALSE */
+                    		return(OPC_2E_UNDERFLOWEXCEPTION);
+			}
+			Sgl_copytoptr(opnd3,dstptr);
+			return(NOEXCEPTION);
+		}
+		/* is denormalized; want to normalize */
+		Sgl_clear_signexponent(opnd2);
+		Sgl_leftshiftby1(opnd2);
+		Sgl_normalize(opnd2,mpy_exponent);
+	}
+
+	/* Multiply the first two source mantissas together */
+
+	/* 
+	 * The intermediate result will be kept in tmpres,
+	 * which needs enough room for 106 bits of mantissa,
+	 * so lets call it a Double extended.
+	 */
+	Sglext_setzero(tmpresp1,tmpresp2);
+
+	/* 
+	 * Four bits at a time are inspected in each loop, and a 
+	 * simple shift and add multiply algorithm is used. 
+	 */ 
+	for (count = SGL_P-1; count >= 0; count -= 4) {
+		Sglext_rightshiftby4(tmpresp1,tmpresp2);
+		if (Sbit28(opnd1)) {
+	 		/* Twoword_add should be an ADD followed by 2 ADDC's */
+			Twoword_add(tmpresp1, tmpresp2, opnd2<<3, 0);
+		}
+		if (Sbit29(opnd1)) {
+			Twoword_add(tmpresp1, tmpresp2, opnd2<<2, 0);
+		}
+		if (Sbit30(opnd1)) {
+			Twoword_add(tmpresp1, tmpresp2, opnd2<<1, 0);
+		}
+		if (Sbit31(opnd1)) {
+			Twoword_add(tmpresp1, tmpresp2, opnd2, 0);
+		}
+		Sgl_rightshiftby4(opnd1);
+	}
+	if (Is_sexthiddenoverflow(tmpresp1)) {
+		/* result mantissa >= 2 (mantissa overflow) */
+		mpy_exponent++;
+		Sglext_rightshiftby4(tmpresp1,tmpresp2);
+	} else {
+		Sglext_rightshiftby3(tmpresp1,tmpresp2);
+	}
+
+	/*
+	 * Restore the sign of the mpy result which was saved in resultp1.
+	 * The exponent will continue to be kept in mpy_exponent.
+	 */
+	Sglext_set_sign(tmpresp1,Sgl_sign(resultp1));
+
+	/* 
+	 * No rounding is required, since the result of the multiply
+	 * is exact in the extended format.
+	 */
+
+	/*
+	 * Now we are ready to perform the add portion of the operation.
+	 *
+	 * The exponents need to be kept as integers for now, since the
+	 * multiply result might not fit into the exponent field.  We
+	 * can't overflow or underflow because of this yet, since the
+	 * add could bring the final result back into range.
+	 */
+	add_exponent = Sgl_exponent(opnd3);
+
+	/*
+	 * Check for denormalized or zero add operand.
+	 */
+	if (add_exponent == 0) {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd3)) {
+			/* right is zero */
+			/* Left can't be zero and must be result.
+			 *
+			 * The final result is now in tmpres and mpy_exponent,
+			 * and needs to be rounded and squeezed back into
+			 * double precision format from double extended.
+			 */
+			result_exponent = mpy_exponent;
+			Sglext_copy(tmpresp1,tmpresp2,resultp1,resultp2);
+			sign_save = Sgl_signextendedsign(resultp1);/*save sign*/
+			goto round;
+		}
+
+		/* 
+		 * Neither are zeroes.  
+		 * Adjust exponent and normalize add operand.
+		 */
+		sign_save = Sgl_signextendedsign(opnd3);	/* save sign */
+		Sgl_clear_signexponent(opnd3);
+		Sgl_leftshiftby1(opnd3);
+		Sgl_normalize(opnd3,add_exponent);
+		Sgl_set_sign(opnd3,sign_save);		/* restore sign */
+	} else {
+		Sgl_clear_exponent_set_hidden(opnd3);
+	}
+	/*
+	 * Copy opnd3 to the double extended variable called right.
+	 */
+	Sgl_copyto_sglext(opnd3,rightp1,rightp2);
+
+	/*
+	 * A zero "save" helps discover equal operands (for later),
+	 * and is used in swapping operands (if needed).
+	 */
+	Sglext_xortointp1(tmpresp1,rightp1,/*to*/save);
+
+	/*
+	 * Compare magnitude of operands.
+	 */
+	Sglext_copytoint_exponentmantissa(tmpresp1,signlessleft1);
+	Sglext_copytoint_exponentmantissa(rightp1,signlessright1);
+	if (mpy_exponent < add_exponent || mpy_exponent == add_exponent &&
+	    Sglext_ismagnitudeless(signlessleft1,signlessright1)) {
+		/*
+		 * Set the left operand to the larger one by XOR swap.
+		 * First finish the first word "save".
+		 */
+		Sglext_xorfromintp1(save,rightp1,/*to*/rightp1);
+		Sglext_xorfromintp1(save,tmpresp1,/*to*/tmpresp1);
+		Sglext_swap_lower(tmpresp2,rightp2);
+		/* also setup exponents used in rest of routine */
+		diff_exponent = add_exponent - mpy_exponent;
+		result_exponent = add_exponent;
+	} else {
+		/* also setup exponents used in rest of routine */
+		diff_exponent = mpy_exponent - add_exponent;
+		result_exponent = mpy_exponent;
+	}
+	/* Invariant: left is not smaller than right. */
+
+	/*
+	 * Special case alignment of operands that would force alignment
+	 * beyond the extent of the extension.  A further optimization
+	 * could special case this but only reduces the path length for
+	 * this infrequent case.
+	 */
+	if (diff_exponent > SGLEXT_THRESHOLD) {
+		diff_exponent = SGLEXT_THRESHOLD;
+	}
+
+	/* Align right operand by shifting it to the right */
+	Sglext_clear_sign(rightp1);
+	Sglext_right_align(rightp1,rightp2,/*shifted by*/diff_exponent);
+	
+	/* Treat sum and difference of the operands separately. */
+	if ((int)save < 0) {
+		/*
+		 * Difference of the two operands.  Overflow can occur if the
+		 * multiply overflowed.  A borrow can occur out of the hidden
+		 * bit and force a post normalization phase.
+		 */
+		Sglext_subtract(tmpresp1,tmpresp2, rightp1,rightp2,
+			resultp1,resultp2);
+		sign_save = Sgl_signextendedsign(resultp1);
+		if (Sgl_iszero_hidden(resultp1)) {
+			/* Handle normalization */
+		/* A straight foward algorithm would now shift the
+		 * result and extension left until the hidden bit
+		 * becomes one.  Not all of the extension bits need
+		 * participate in the shift.  Only the two most 
+		 * significant bits (round and guard) are needed.
+		 * If only a single shift is needed then the guard
+		 * bit becomes a significant low order bit and the
+		 * extension must participate in the rounding.
+		 * If more than a single shift is needed, then all
+		 * bits to the right of the guard bit are zeros, 
+		 * and the guard bit may or may not be zero. */
+			Sglext_leftshiftby1(resultp1,resultp2);
+
+			/* Need to check for a zero result.  The sign and
+			 * exponent fields have already been zeroed.  The more
+			 * efficient test of the full object can be used.
+			 */
+			 if (Sglext_iszero(resultp1,resultp2)) {
+				/* Must have been "x-x" or "x+(-x)". */
+				if (Is_rounding_mode(ROUNDMINUS))
+					Sgl_setone_sign(resultp1);
+				Sgl_copytoptr(resultp1,dstptr);
+				return(NOEXCEPTION);
+			}
+			result_exponent--;
+
+			/* Look to see if normalization is finished. */
+			if (Sgl_isone_hidden(resultp1)) {
+				/* No further normalization is needed */
+				goto round;
+			}
+
+			/* Discover first one bit to determine shift amount.
+			 * Use a modified binary search.  We have already
+			 * shifted the result one position right and still
+			 * not found a one so the remainder of the extension
+			 * must be zero and simplifies rounding. */
+			/* Scan bytes */
+			while (Sgl_iszero_hiddenhigh7mantissa(resultp1)) {
+				Sglext_leftshiftby8(resultp1,resultp2);
+				result_exponent -= 8;
+			}
+			/* Now narrow it down to the nibble */
+			if (Sgl_iszero_hiddenhigh3mantissa(resultp1)) {
+				/* The lower nibble contains the
+				 * normalizing one */
+				Sglext_leftshiftby4(resultp1,resultp2);
+				result_exponent -= 4;
+			}
+			/* Select case where first bit is set (already
+			 * normalized) otherwise select the proper shift. */
+			jumpsize = Sgl_hiddenhigh3mantissa(resultp1);
+			if (jumpsize <= 7) switch(jumpsize) {
+			case 1:
+				Sglext_leftshiftby3(resultp1,resultp2);
+				result_exponent -= 3;
+				break;
+			case 2:
+			case 3:
+				Sglext_leftshiftby2(resultp1,resultp2);
+				result_exponent -= 2;
+				break;
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+				Sglext_leftshiftby1(resultp1,resultp2);
+				result_exponent -= 1;
+				break;
+			}
+		} /* end if (hidden...)... */
+	/* Fall through and round */
+	} /* end if (save < 0)... */
+	else {
+		/* Add magnitudes */
+		Sglext_addition(tmpresp1,tmpresp2,
+			rightp1,rightp2, /*to*/resultp1,resultp2);
+		sign_save = Sgl_signextendedsign(resultp1);
+		if (Sgl_isone_hiddenoverflow(resultp1)) {
+	    		/* Prenormalization required. */
+	    		Sglext_arithrightshiftby1(resultp1,resultp2);
+	    		result_exponent++;
+		} /* end if hiddenoverflow... */
+	} /* end else ...add magnitudes... */
+
+	/* Round the result.  If the extension and lower two words are
+	 * all zeros, then the result is exact.  Otherwise round in the
+	 * correct direction.  Underflow is possible. If a postnormalization
+	 * is necessary, then the mantissa is all zeros so no shift is needed.
+	 */
+  round:
+	if (result_exponent <= 0 && !Is_underflowtrap_enabled()) {
+		Sglext_denormalize(resultp1,resultp2,result_exponent,is_tiny);
+	}
+	Sgl_set_sign(resultp1,/*using*/sign_save);
+	if (Sglext_isnotzero_mantissap2(resultp2)) {
+		inexact = TRUE;
+		switch(Rounding_mode()) {
+		case ROUNDNEAREST: /* The default. */
+			if (Sglext_isone_highp2(resultp2)) {
+				/* at least 1/2 ulp */
+				if (Sglext_isnotzero_low31p2(resultp2) ||
+				    Sglext_isone_lowp1(resultp1)) {
+					/* either exactly half way and odd or
+					 * more than 1/2ulp */
+					Sgl_increment(resultp1);
+				}
+			}
+	    		break;
+
+		case ROUNDPLUS:
+	    		if (Sgl_iszero_sign(resultp1)) {
+				/* Round up positive results */
+				Sgl_increment(resultp1);
+			}
+			break;
+	    
+		case ROUNDMINUS:
+	    		if (Sgl_isone_sign(resultp1)) {
+				/* Round down negative results */
+				Sgl_increment(resultp1);
+			}
+	    
+		case ROUNDZERO:;
+			/* truncate is simple */
+		} /* end switch... */
+		if (Sgl_isone_hiddenoverflow(resultp1)) result_exponent++;
+	}
+	if (result_exponent >= SGL_INFINITY_EXPONENT) {
+		/* Overflow */
+		if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Sgl_setwrapped_exponent(resultp1,result_exponent,ovfl);
+                        Sgl_copytoptr(resultp1,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_OVERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return (OPC_2E_OVERFLOWEXCEPTION);
+		}
+		inexact = TRUE;
+		Set_overflowflag();
+		Sgl_setoverflow(resultp1);
+	} else if (result_exponent <= 0) {	/* underflow case */
+		if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                	Sgl_setwrapped_exponent(resultp1,result_exponent,unfl);
+			Sgl_copytoptr(resultp1,dstptr);
+                        if (inexact)
+                            if (Is_inexacttrap_enabled())
+                                return (OPC_2E_UNDERFLOWEXCEPTION |
+					OPC_2E_INEXACTEXCEPTION);
+                            else Set_inexactflag();
+	    		return(OPC_2E_UNDERFLOWEXCEPTION);
+		}
+		else if (inexact && is_tiny) Set_underflowflag();
+	}
+	else Sgl_set_exponent(resultp1,result_exponent);
+	Sgl_copytoptr(resultp1,dstptr);
+	if (inexact) 
+		if (Is_inexacttrap_enabled()) return(OPC_2E_INEXACTEXCEPTION);
+		else Set_inexactflag();
+    	return(NOEXCEPTION);
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fpbits.h linux/arch/parisc/math-emu/fpbits.h
--- linux.orig/arch/parisc/math-emu/fpbits.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fpbits.h	2002-08-12 22:14:25.000000000 +0000
@@ -0,0 +1,65 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+
+/*
+ *  These macros are designed to be portable to all machines that have
+ *  a wordsize greater than or equal to 32 bits that support the portable
+ *  C compiler and the standard C preprocessor.  Wordsize (default 32)
+ *  and bitfield assignment (default left-to-right,  unlike VAX, PDP-11)
+ *  should be predefined using the constants HOSTWDSZ and BITFRL and
+ *  the C compiler "-D" flag (e.g., -DHOSTWDSZ=36 -DBITFLR for the DEC-20).
+ *  Note that the macro arguments assume that the integer being referenced
+ *  is a 32-bit integer (right-justified on the 20) and that bit 0 is the
+ *  most significant bit.
+ */
+
+#ifndef HOSTWDSZ
+#define	HOSTWDSZ	32
+#endif
+
+
+/*###########################  Macros  ######################################*/
+
+/*-------------------------------------------------------------------------
+ * NewDeclareBitField_Reference - Declare a structure similar to the simulator
+ * function "DeclBitfR" except its use is restricted to occur within a larger
+ * enclosing structure or union definition.  This declaration is an unnamed
+ * structure with the argument, name, as the member name and the argument,
+ * uname, as the element name. 
+ *----------------------------------------------------------------------- */
+#define Bitfield_extract(start, length, object) 	\
+    ((object) >> (HOSTWDSZ - (start) - (length)) & 	\
+    ((unsigned)-1 >> (HOSTWDSZ - (length))))
+
+#define Bitfield_signed_extract(start, length, object) \
+    ((int)((object) << start) >> (HOSTWDSZ - (length)))
+
+#define Bitfield_mask(start, len, object)		\
+    ((object) & (((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len)))
+
+#define Bitfield_deposit(value,start,len,object)  object = \
+    ((object) & ~(((unsigned)-1 >> (HOSTWDSZ-len)) << (HOSTWDSZ-start-len))) | \
+    (((value) & ((unsigned)-1 >> (HOSTWDSZ-len))) << (HOSTWDSZ-start-len))
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fpu.h linux/arch/parisc/math-emu/fpu.h
--- linux.orig/arch/parisc/math-emu/fpu.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fpu.h	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,76 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ * 
+ *  File: 
+ *      @(#)	pa/fp/fpu.h		$Revision: 1.2 $
+ * 
+ *  Purpose:
+ *      <<please update with a synopis of the functionality provided by this file>>
+ * 
+ * 
+ * END_DESC  
+*/
+
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+
+#ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */
+#define _MACHINE_FPU_INCLUDED
+
+#if 0
+#ifndef _SYS_STDSYMS_INCLUDED
+#    include <sys/stdsyms.h>
+#endif   /* _SYS_STDSYMS_INCLUDED  */
+#include  <machine/pdc/pdc_rqsts.h>
+#endif
+
+#define PA83_FPU_FLAG    0x00000001
+#define PA89_FPU_FLAG    0x00000002
+#define PA2_0_FPU_FLAG   0x00000010
+
+#define TIMEX_EXTEN_FLAG 0x00000004
+
+#define ROLEX_EXTEN_FLAG 0x00000008
+#define COPR_FP 	0x00000080	/* Floating point -- Coprocessor 0 */
+#define SFU_MPY_DIVIDE	0x00008000	/* Multiply/Divide __ SFU 0 */
+
+
+#define EM_FPU_TYPE_OFFSET 272
+
+/* version of EMULATION software for COPR,0,0 instruction */
+#define EMULATION_VERSION 4
+
+/*
+ * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T)
+ * is thorough the potential type field from the PDC_MODEL call.  The 
+ * following flags are used at assist this differeniation.
+ */
+
+#define ROLEX_POTENTIAL_KEY_FLAGS	PDC_MODEL_CPU_KEY_WORD_TO_IO
+#define TIMEX_POTENTIAL_KEY_FLAGS	(PDC_MODEL_CPU_KEY_QUAD_STORE | \
+					 PDC_MODEL_CPU_KEY_RECIP_SQRT)
+
+
+#endif /* ! _MACHINE_FPU_INCLUDED */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/fpudispatch.c linux/arch/parisc/math-emu/fpudispatch.c
--- linux.orig/arch/parisc/math-emu/fpudispatch.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/fpudispatch.c	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,1425 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/fp/fpudispatch.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	<<please update with a synopsis of the functionality provided by this file>>
+ *
+ *  External Interfaces:
+ *	<<the following list was autogenerated, please review>>
+ *	emfpudispatch(ir, dummy1, dummy2, fpregs)
+ *	fpudispatch(ir, excp_code, holder, fpregs)
+ *
+ *  Internal Interfaces:
+ *	<<the following list was autogenerated, please review>>
+ *	static u_int decode_06(u_int, u_int *)
+ *	static u_int decode_0c(u_int, u_int, u_int, u_int *)
+ *	static u_int decode_0e(u_int, u_int, u_int, u_int *)
+ *	static u_int decode_26(u_int, u_int *)
+ *	static u_int decode_2e(u_int, u_int *)
+ *	static void update_status_cbit(u_int *, u_int, u_int, u_int)
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+#define FPUDEBUG 0
+
+#include "float.h"
+#include "types.h"
+/* #include <sys/debug.h> */
+/* #include <machine/sys/mdep_private.h> */
+
+#define COPR_INST 0x30000000
+
+/*
+ * definition of extru macro.  If pos and len are constants, the compiler
+ * will generate an extru instruction when optimized
+ */
+#define extru(r,pos,len)	(((r) >> (31-(pos))) & (( 1 << (len)) - 1))
+/* definitions of bit field locations in the instruction */
+#define fpmajorpos 5
+#define fpr1pos	10
+#define fpr2pos 15
+#define fptpos	31
+#define fpsubpos 18
+#define fpclass1subpos 16
+#define fpclasspos 22
+#define fpfmtpos 20
+#define fpdfpos 18
+#define fpnulpos 26
+/*
+ * the following are the extra bits for the 0E major op
+ */
+#define fpxr1pos 24
+#define fpxr2pos 19
+#define fpxtpos 25
+#define fpxpos 23
+#define fp0efmtpos 20
+/*
+ * the following are for the multi-ops
+ */
+#define fprm1pos 10
+#define fprm2pos 15
+#define fptmpos 31
+#define fprapos 25
+#define fptapos 20
+#define fpmultifmt 26
+/*
+ * the following are for the fused FP instructions
+ */
+     /* fprm1pos 10 */
+     /* fprm2pos 15 */
+#define fpraupos 18
+#define fpxrm2pos 19
+     /* fpfmtpos 20 */
+#define fpralpos 23
+#define fpxrm1pos 24
+     /* fpxtpos 25 */
+#define fpfusedsubop 26
+     /* fptpos	31 */
+
+/*
+ * offset to constant zero in the FP emulation registers
+ */
+#define fpzeroreg (32*sizeof(double)/sizeof(u_int))
+
+/*
+ * extract the major opcode from the instruction
+ */
+#define get_major(op) extru(op,fpmajorpos,6)
+/*
+ * extract the two bit class field from the FP instruction. The class is at bit
+ * positions 21-22
+ */
+#define get_class(op) extru(op,fpclasspos,2)
+/*
+ * extract the 3 bit subop field.  For all but class 1 instructions, it is
+ * located at bit positions 16-18
+ */
+#define get_subop(op) extru(op,fpsubpos,3)
+/*
+ * extract the 2 or 3 bit subop field from class 1 instructions.  It is located
+ * at bit positions 15-16 (PA1.1) or 14-16 (PA2.0)
+ */
+#define get_subop1_PA1_1(op) extru(op,fpclass1subpos,2)	/* PA89 (1.1) fmt */
+#define get_subop1_PA2_0(op) extru(op,fpclass1subpos,3)	/* PA 2.0 fmt */
+
+/* definitions of unimplemented exceptions */
+#define MAJOR_0C_EXCP	0x09
+#define MAJOR_0E_EXCP	0x0b
+#define MAJOR_06_EXCP	0x03
+#define MAJOR_26_EXCP	0x23
+#define MAJOR_2E_EXCP	0x2b
+#define PA83_UNIMP_EXCP	0x01
+
+/*
+ * Special Defines for TIMEX specific code
+ */
+
+#define FPU_TYPE_FLAG_POS (EM_FPU_TYPE_OFFSET>>2)
+#define TIMEX_ROLEX_FPU_MASK (TIMEX_EXTEN_FLAG|ROLEX_EXTEN_FLAG)
+
+/*
+ * Static function definitions
+ */
+#define _PROTOTYPES
+#if defined(_PROTOTYPES) || defined(_lint)
+static u_int decode_0c(u_int, u_int, u_int, u_int *);
+static u_int decode_0e(u_int, u_int, u_int, u_int *);
+static u_int decode_06(u_int, u_int *);
+static u_int decode_26(u_int, u_int *);
+static u_int decode_2e(u_int, u_int *);
+static void update_status_cbit(u_int *, u_int, u_int, u_int);
+#else /* !_PROTOTYPES&&!_lint */
+static u_int decode_0c();
+static u_int decode_0e();
+static u_int decode_06();
+static u_int decode_26();
+static u_int decode_2e();
+static void update_status_cbit();
+#endif /* _PROTOTYPES&&!_lint */
+
+#define VASSERT(x)
+
+/*
+ * this routine will decode the excepting floating point instruction and
+ * call the approiate emulation routine.
+ * It is called by decode_fpu with the following parameters:
+ * fpudispatch(current_ir, unimplemented_code, 0, &Fpu_register)
+ * where current_ir is the instruction to be emulated,
+ * unimplemented_code is the exception_code that the hardware generated
+ * and &Fpu_register is the address of emulated FP reg 0.
+ */
+u_int
+fpudispatch(u_int ir, u_int excp_code, u_int holder, u_int fpregs[])
+{
+	u_int class, subop;
+	u_int fpu_type_flags;
+
+	/* All FP emulation code assumes that ints are 4-bytes in length */
+	VASSERT(sizeof(int) == 4);
+
+	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
+
+	class = get_class(ir);
+	if (class == 1) {
+		if  (fpu_type_flags & PA2_0_FPU_FLAG)
+			subop = get_subop1_PA2_0(ir);
+		else
+			subop = get_subop1_PA1_1(ir);
+	}
+	else
+		subop = get_subop(ir);
+
+	if (FPUDEBUG) printk("class %d subop %d\n", class, subop);
+
+	switch (excp_code) {
+		case MAJOR_0C_EXCP:
+		case PA83_UNIMP_EXCP:
+			return(decode_0c(ir,class,subop,fpregs));
+		case MAJOR_0E_EXCP:
+			return(decode_0e(ir,class,subop,fpregs));
+		case MAJOR_06_EXCP:
+			return(decode_06(ir,fpregs));
+		case MAJOR_26_EXCP:
+			return(decode_26(ir,fpregs));
+		case MAJOR_2E_EXCP:
+			return(decode_2e(ir,fpregs));
+		default:
+			/* "crashme Night Gallery painting nr 2. (asm_crash.s).
+			 * This was fixed for multi-user kernels, but
+			 * workstation kernels had a panic here.  This allowed
+			 * any arbitrary user to panic the kernel by executing
+			 * setting the FP exception registers to strange values
+			 * and generating an emulation trap.  The emulation and
+			 * exception code must never be able to panic the
+			 * kernel.
+			 */
+			return(UNIMPLEMENTEDEXCEPTION);
+	}
+}
+
+/*
+ * this routine is called by $emulation_trap to emulate a coprocessor
+ * instruction if one doesn't exist
+ */
+u_int
+emfpudispatch(u_int ir, u_int dummy1, u_int dummy2, u_int fpregs[])
+{
+	u_int class, subop, major;
+	u_int fpu_type_flags;
+
+	/* All FP emulation code assumes that ints are 4-bytes in length */
+	VASSERT(sizeof(int) == 4);
+
+	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
+
+	major = get_major(ir);
+	class = get_class(ir);
+	if (class == 1) {
+		if  (fpu_type_flags & PA2_0_FPU_FLAG)
+			subop = get_subop1_PA2_0(ir);
+		else
+			subop = get_subop1_PA1_1(ir);
+	}
+	else
+		subop = get_subop(ir);
+	switch (major) {
+		case 0x0C:
+			return(decode_0c(ir,class,subop,fpregs));
+		case 0x0E:
+			return(decode_0e(ir,class,subop,fpregs));
+		case 0x06:
+			return(decode_06(ir,fpregs));
+		case 0x26:
+			return(decode_26(ir,fpregs));
+		case 0x2E:
+			return(decode_2e(ir,fpregs));
+		default:
+			return(PA83_UNIMP_EXCP);
+	}
+}
+	
+
+static u_int
+decode_0c(u_int ir, u_int class, u_int subop, u_int fpregs[])
+{
+	u_int r1,r2,t;		/* operand register offsets */ 
+	u_int fmt;		/* also sf for class 1 conversions */
+	u_int  df;		/* for class 1 conversions */
+	u_int *status;
+	u_int retval, local_status;
+	u_int fpu_type_flags;
+
+	if (ir == COPR_INST) {
+		fpregs[0] = EMULATION_VERSION << 11;
+		return(NOEXCEPTION);
+	}
+	status = &fpregs[0];	/* fp status register */
+	local_status = fpregs[0]; /* and local copy */
+	r1 = extru(ir,fpr1pos,5) * sizeof(double)/sizeof(u_int);
+	if (r1 == 0)		/* map fr0 source to constant zero */
+		r1 = fpzeroreg;
+	t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
+	if (t == 0 && class != 2)	/* don't allow fr0 as a dest */
+		return(MAJOR_0C_EXCP);
+	fmt = extru(ir,fpfmtpos,2);	/* get fmt completer */
+
+	switch (class) {
+	    case 0:
+		switch (subop) {
+			case 0:	/* COPR 0,0 emulated above*/
+			case 1:
+				return(MAJOR_0C_EXCP);
+			case 2:	/* FCPY */
+				switch (fmt) {
+				    case 2: /* illegal */
+					return(MAJOR_0C_EXCP);
+				    case 3: /* quad */
+					t &= ~3;  /* force to even reg #s */
+					r1 &= ~3;
+					fpregs[t+3] = fpregs[r1+3];
+					fpregs[t+2] = fpregs[r1+2];
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					fpregs[t] = fpregs[r1];
+					return(NOEXCEPTION);
+				}
+			case 3: /* FABS */
+				switch (fmt) {
+				    case 2: /* illegal */
+					return(MAJOR_0C_EXCP);
+				    case 3: /* quad */
+					t &= ~3;  /* force to even reg #s */
+					r1 &= ~3;
+					fpregs[t+3] = fpregs[r1+3];
+					fpregs[t+2] = fpregs[r1+2];
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					/* copy and clear sign bit */
+					fpregs[t] = fpregs[r1] & 0x7fffffff;
+					return(NOEXCEPTION);
+				}
+			case 6: /* FNEG */
+				switch (fmt) {
+				    case 2: /* illegal */
+					return(MAJOR_0C_EXCP);
+				    case 3: /* quad */
+					t &= ~3;  /* force to even reg #s */
+					r1 &= ~3;
+					fpregs[t+3] = fpregs[r1+3];
+					fpregs[t+2] = fpregs[r1+2];
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					/* copy and invert sign bit */
+					fpregs[t] = fpregs[r1] ^ 0x80000000;
+					return(NOEXCEPTION);
+				}
+			case 7: /* FNEGABS */
+				switch (fmt) {
+				    case 2: /* illegal */
+					return(MAJOR_0C_EXCP);
+				    case 3: /* quad */
+					t &= ~3;  /* force to even reg #s */
+					r1 &= ~3;
+					fpregs[t+3] = fpregs[r1+3];
+					fpregs[t+2] = fpregs[r1+2];
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					/* copy and set sign bit */
+					fpregs[t] = fpregs[r1] | 0x80000000;
+					return(NOEXCEPTION);
+				}
+			case 4: /* FSQRT */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fsqrt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fsqrt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2:
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			case 5: /* FRND */
+				switch (fmt) {
+				    case 0:
+					return(sgl_frnd(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_frnd(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2:
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+		} /* end of switch (subop) */
+
+	case 1: /* class 1 */
+		df = extru(ir,fpdfpos,2); /* get dest format */
+		if ((df & 2) || (fmt & 2)) {
+			/*
+			 * fmt's 2 and 3 are illegal of not implemented
+			 * quad conversions
+			 */
+			return(MAJOR_0C_EXCP);
+		}
+		/*
+		 * encode source and dest formats into 2 bits.
+		 * high bit is source, low bit is dest.
+		 * bit = 1 --> double precision
+		 */
+		fmt = (fmt << 1) | df;
+		switch (subop) {
+			case 0: /* FCNVFF */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(MAJOR_0C_EXCP);
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(MAJOR_0C_EXCP);
+				}
+			case 1: /* FCNVXF */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 2: /* FCNVFX */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 3: /* FCNVFXT */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 5: /* FCNVUF (PA2.0 only) */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 6: /* FCNVFU (PA2.0 only) */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 7: /* FCNVFUT (PA2.0 only) */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 4: /* undefined */
+				return(MAJOR_0C_EXCP);
+		} /* end of switch subop */
+
+	case 2: /* class 2 */
+		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
+		r2 = extru(ir, fpr2pos, 5) * sizeof(double)/sizeof(u_int);
+		if (r2 == 0)
+			r2 = fpzeroreg;
+		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
+			/* FTEST if nullify bit set, otherwise FCMP */
+			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
+				switch (fmt) {
+				    case 0:
+					/*
+					 * arg0 is not used
+					 * second param is the t field used for
+					 * ftest,acc and ftest,rej
+					 * third param is the subop (y-field)
+					 */
+					BUG();
+					/* Unsupported
+					 * return(ftest(0L,extru(ir,fptpos,5),
+					 *	 &fpregs[0],subop));
+					 */
+				    case 1:
+				    case 2:
+				    case 3:
+					return(MAJOR_0C_EXCP);
+				}
+			} else {  /* FCMP */
+				switch (fmt) {
+				    case 0:
+					retval = sgl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				    case 1:
+					retval = dbl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			}
+		}  /* end of if for PA2.0 */
+		else {	/* PA1.0 & PA1.1 */
+		    switch (subop) {
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+				return(MAJOR_0C_EXCP);
+			case 0: /* FCMP */
+				switch (fmt) {
+				    case 0:
+					retval = sgl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				    case 1:
+					retval = dbl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			case 1: /* FTEST */
+				switch (fmt) {
+				    case 0:
+					/*
+					 * arg0 is not used
+					 * second param is the t field used for
+					 * ftest,acc and ftest,rej
+					 * third param is the subop (y-field)
+					 */
+					BUG();
+					/* unsupported
+					 * return(ftest(0L,extru(ir,fptpos,5),
+					 *     &fpregs[0],subop));
+					 */
+				    case 1:
+				    case 2:
+				    case 3:
+					return(MAJOR_0C_EXCP);
+				}
+		    } /* end of switch subop */
+		} /* end of else for PA1.0 & PA1.1 */
+	case 3: /* class 3 */
+		r2 = extru(ir,fpr2pos,5) * sizeof(double)/sizeof(u_int);
+		if (r2 == 0)
+			r2 = fpzeroreg;
+		switch (subop) {
+			case 5:
+			case 6:
+			case 7:
+				return(MAJOR_0C_EXCP);
+			
+			case 0: /* FADD */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			case 1: /* FSUB */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			case 2: /* FMPY */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fmpy(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fmpy(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			case 3: /* FDIV */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+			case 4: /* FREM */
+				switch (fmt) {
+				    case 0:
+					return(sgl_frem(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_frem(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 2: /* illegal */
+				    case 3: /* quad not implemented */
+					return(MAJOR_0C_EXCP);
+				}
+		} /* end of class 3 switch */
+	} /* end of switch(class) */
+
+	/* If we get here, something is really wrong! */
+	return(MAJOR_0C_EXCP);
+}
+
+static u_int
+decode_0e(ir,class,subop,fpregs)
+u_int ir,class,subop;
+u_int fpregs[];
+{
+	u_int r1,r2,t;		/* operand register offsets */
+	u_int fmt;		/* also sf for class 1 conversions */
+	u_int df;		/* dest format for class 1 conversions */
+	u_int *status;
+	u_int retval, local_status;
+	u_int fpu_type_flags;
+
+	status = &fpregs[0];
+	local_status = fpregs[0];
+	r1 = ((extru(ir,fpr1pos,5)<<1)|(extru(ir,fpxr1pos,1)));
+	if (r1 == 0)
+		r1 = fpzeroreg;
+	t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
+	if (t == 0 && class != 2)
+		return(MAJOR_0E_EXCP);
+	if (class < 2)		/* class 0 or 1 has 2 bit fmt */
+		fmt = extru(ir,fpfmtpos,2);
+	else 			/* class 2 and 3 have 1 bit fmt */
+		fmt = extru(ir,fp0efmtpos,1);
+	/*
+	 * An undefined combination, double precision accessing the
+	 * right half of a FPR, can get us into trouble.  
+	 * Let's just force proper alignment on it.
+	 */
+	if (fmt == DBL) {
+		r1 &= ~1;
+		if (class != 1)
+			t &= ~1;
+	}
+
+	switch (class) {
+	    case 0:
+		switch (subop) {
+			case 0: /* unimplemented */
+			case 1:
+				return(MAJOR_0E_EXCP);
+			case 2: /* FCPY */
+				switch (fmt) {
+				    case 2:
+				    case 3:
+					return(MAJOR_0E_EXCP);
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					fpregs[t] = fpregs[r1];
+					return(NOEXCEPTION);
+				}
+			case 3: /* FABS */
+				switch (fmt) {
+				    case 2:
+				    case 3:
+					return(MAJOR_0E_EXCP);
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					fpregs[t] = fpregs[r1] & 0x7fffffff;
+					return(NOEXCEPTION);
+				}
+			case 6: /* FNEG */
+				switch (fmt) {
+				    case 2:
+				    case 3:
+					return(MAJOR_0E_EXCP);
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					fpregs[t] = fpregs[r1] ^ 0x80000000;
+					return(NOEXCEPTION);
+				}
+			case 7: /* FNEGABS */
+				switch (fmt) {
+				    case 2:
+				    case 3:
+					return(MAJOR_0E_EXCP);
+				    case 1: /* double */
+					fpregs[t+1] = fpregs[r1+1];
+				    case 0: /* single */
+					fpregs[t] = fpregs[r1] | 0x80000000;
+					return(NOEXCEPTION);
+				}
+			case 4: /* FSQRT */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fsqrt(&fpregs[r1],0,
+						&fpregs[t], status));
+				    case 1:
+					return(dbl_fsqrt(&fpregs[r1],0,
+						&fpregs[t], status));
+				    case 2:
+				    case 3:
+					return(MAJOR_0E_EXCP);
+				}
+			case 5: /* FRMD */
+				switch (fmt) {
+				    case 0:
+					return(sgl_frnd(&fpregs[r1],0,
+						&fpregs[t], status));
+				    case 1:
+					return(dbl_frnd(&fpregs[r1],0,
+						&fpregs[t], status));
+				    case 2:
+				    case 3:
+					return(MAJOR_0E_EXCP);
+				}
+		} /* end of switch (subop */
+	
+	case 1: /* class 1 */
+		df = extru(ir,fpdfpos,2); /* get dest format */
+		/*
+		 * Fix Crashme problem (writing to 31R in double precision)
+		 * here too.
+		 */
+		if (df == DBL) {
+			t &= ~1;
+		}
+		if ((df & 2) || (fmt & 2))
+			return(MAJOR_0E_EXCP);
+		
+		fmt = (fmt << 1) | df;
+		switch (subop) {
+			case 0: /* FCNVFF */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(MAJOR_0E_EXCP);
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvff(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvff(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(MAJOR_0E_EXCP);
+				}
+			case 1: /* FCNVXF */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvxf(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 2: /* FCNVFX */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfx(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 3: /* FCNVFXT */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfxt(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 5: /* FCNVUF (PA2.0 only) */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvuf(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 6: /* FCNVFU (PA2.0 only) */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfu(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 7: /* FCNVFUT (PA2.0 only) */
+				switch(fmt) {
+				    case 0: /* sgl/sgl */
+					return(sgl_to_sgl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 1: /* sgl/dbl */
+					return(sgl_to_dbl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 2: /* dbl/sgl */
+					return(dbl_to_sgl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				    case 3: /* dbl/dbl */
+					return(dbl_to_dbl_fcnvfut(&fpregs[r1],0,
+						&fpregs[t],status));
+				}
+			case 4: /* undefined */
+				return(MAJOR_0C_EXCP);
+		} /* end of switch subop */
+	case 2: /* class 2 */
+		/*
+		 * Be careful out there.
+		 * Crashme can generate cases where FR31R is specified
+		 * as the source or target of a double precision operation.
+		 * Since we just pass the address of the floating-point
+		 * register to the emulation routines, this can cause
+		 * corruption of fpzeroreg.
+		 */
+		if (fmt == DBL)
+			r2 = (extru(ir,fpr2pos,5)<<1);
+		else
+			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
+		fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];
+		if (r2 == 0)
+			r2 = fpzeroreg;
+		if  (fpu_type_flags & PA2_0_FPU_FLAG) {
+			/* FTEST if nullify bit set, otherwise FCMP */
+			if (extru(ir, fpnulpos, 1)) {  /* FTEST */
+				/* not legal */
+				return(MAJOR_0E_EXCP);
+			} else {  /* FCMP */
+			switch (fmt) {
+				    /*
+				     * fmt is only 1 bit long
+				     */
+				    case 0:
+					retval = sgl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				    case 1:
+					retval = dbl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				}
+			}
+		}  /* end of if for PA2.0 */
+		else {  /* PA1.0 & PA1.1 */
+		    switch (subop) {
+			case 1:
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+				return(MAJOR_0E_EXCP);
+			case 0: /* FCMP */
+				switch (fmt) {
+				    /*
+				     * fmt is only 1 bit long
+				     */
+				    case 0:
+					retval = sgl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				    case 1:
+					retval = dbl_fcmp(&fpregs[r1],
+						&fpregs[r2],extru(ir,fptpos,5),
+						&local_status);
+					update_status_cbit(status,local_status,
+						fpu_type_flags, subop);
+					return(retval);
+				}
+		    } /* end of switch subop */
+		} /* end of else for PA1.0 & PA1.1 */
+	case 3: /* class 3 */
+		/*
+		 * Be careful out there.
+		 * Crashme can generate cases where FR31R is specified
+		 * as the source or target of a double precision operation.
+		 * Since we just pass the address of the floating-point
+		 * register to the emulation routines, this can cause
+		 * corruption of fpzeroreg.
+		 */
+		if (fmt == DBL)
+			r2 = (extru(ir,fpr2pos,5)<<1);
+		else
+			r2 = ((extru(ir,fpr2pos,5)<<1)|(extru(ir,fpxr2pos,1)));
+		if (r2 == 0)
+			r2 = fpzeroreg;
+		switch (subop) {
+			case 5:
+			case 6:
+			case 7:
+				return(MAJOR_0E_EXCP);
+			
+			/*
+			 * Note that fmt is only 1 bit for class 3 */
+			case 0: /* FADD */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fadd(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fadd(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				}
+			case 1: /* FSUB */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fsub(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fsub(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				}
+			case 2: /* FMPY or XMPYU */
+				/*
+				 * check for integer multiply (x bit set)
+				 */
+				if (extru(ir,fpxpos,1)) {
+				    /*
+				     * emulate XMPYU
+				     */
+				    switch (fmt) {
+					case 0:
+					    /*
+					     * bad instruction if t specifies
+					     * the right half of a register
+					     */
+					    if (t & 1)
+						return(MAJOR_0E_EXCP);
+					    BUG();
+					    /* unsupported
+					     * impyu(&fpregs[r1],&fpregs[r2],
+						 * &fpregs[t]);
+					     */
+					    return(NOEXCEPTION);
+					case 1:
+						return(MAJOR_0E_EXCP);
+				    }
+				}
+				else { /* FMPY */
+				    switch (fmt) {
+				        case 0:
+					    return(sgl_fmpy(&fpregs[r1],
+					       &fpregs[r2],&fpregs[t],status));
+				        case 1:
+					    return(dbl_fmpy(&fpregs[r1],
+					       &fpregs[r2],&fpregs[t],status));
+				    }
+				}
+			case 3: /* FDIV */
+				switch (fmt) {
+				    case 0:
+					return(sgl_fdiv(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_fdiv(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				}
+			case 4: /* FREM */
+				switch (fmt) {
+				    case 0:
+					return(sgl_frem(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				    case 1:
+					return(dbl_frem(&fpregs[r1],&fpregs[r2],
+						&fpregs[t],status));
+				}
+		} /* end of class 3 switch */
+	} /* end of switch(class) */
+
+	/* If we get here, something is really wrong! */
+	return(MAJOR_0E_EXCP);
+}
+
+
+/*
+ * routine to decode the 06 (FMPYADD and FMPYCFXT) instruction
+ */
+static u_int
+decode_06(ir,fpregs)
+u_int ir;
+u_int fpregs[];
+{
+	u_int rm1, rm2, tm, ra, ta; /* operands */
+	u_int fmt;
+	u_int error = 0;
+	u_int status;
+	u_int fpu_type_flags;
+	union {
+		double dbl;
+		float flt;
+		struct { u_int i1; u_int i2; } ints;
+	} mtmp, atmp;
+
+
+	status = fpregs[0];		/* use a local copy of status reg */
+	fpu_type_flags=fpregs[FPU_TYPE_FLAG_POS];  /* get fpu type flags */
+	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
+	if (fmt == 0) { /* DBL */
+		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
+		if (rm1 == 0)
+			rm1 = fpzeroreg;
+		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
+		if (rm2 == 0)
+			rm2 = fpzeroreg;
+		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
+		if (tm == 0)
+			return(MAJOR_06_EXCP);
+		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
+		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
+		if (ta == 0)
+			return(MAJOR_06_EXCP);
+
+		if  (fpu_type_flags & TIMEX_ROLEX_FPU_MASK)  {
+
+			if (ra == 0) {
+			 	/* special case FMPYCFXT, see sgl case below */
+				if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],
+					&mtmp.ints.i1,&status))
+					error = 1;
+				if (dbl_to_sgl_fcnvfxt(&fpregs[ta],
+					&atmp.ints.i1,&atmp.ints.i1,&status))
+					error = 1;
+				}
+			else {
+
+			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+					&status))
+				error = 1;
+			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
+					&status))
+				error = 1;
+				}
+			}
+
+		else
+
+			{
+			if (ra == 0)
+				ra = fpzeroreg;
+
+			if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+					&status))
+				error = 1;
+			if (dbl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
+					&status))
+				error = 1;
+
+			}
+
+		if (error)
+			return(MAJOR_06_EXCP);
+		else {
+			/* copy results */
+			fpregs[tm] = mtmp.ints.i1;
+			fpregs[tm+1] = mtmp.ints.i2;
+			fpregs[ta] = atmp.ints.i1;
+			fpregs[ta+1] = atmp.ints.i2;
+			fpregs[0] = status;
+			return(NOEXCEPTION);
+		}
+	}
+	else { /* SGL */
+		/*
+		 * calculate offsets for single precision numbers
+		 * See table 6-14 in PA-89 architecture for mapping
+		 */
+		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
+		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
+
+		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
+		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
+
+		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
+		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
+
+		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
+		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
+
+		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
+		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
+		
+		if (ra == 0x20 &&(fpu_type_flags & TIMEX_ROLEX_FPU_MASK)) {
+			/* special case FMPYCFXT (really 0)
+			  * This instruction is only present on the Timex and
+			  * Rolex fpu's in so if it is the special case and
+			  * one of these fpu's we run the FMPYCFXT instruction
+			  */
+			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+					&status))
+				error = 1;
+			if (sgl_to_sgl_fcnvfxt(&fpregs[ta],&atmp.ints.i1,
+				&atmp.ints.i1,&status))
+				error = 1;
+		}
+		else {
+			if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,
+					&status))
+				error = 1;
+			if (sgl_fadd(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,
+					&status))
+				error = 1;
+		}
+		if (error)
+			return(MAJOR_06_EXCP);
+		else {
+			/* copy results */
+			fpregs[tm] = mtmp.ints.i1;
+			fpregs[ta] = atmp.ints.i1;
+			fpregs[0] = status;
+			return(NOEXCEPTION);
+		}
+	}
+}
+
+/*
+ * routine to decode the 26 (FMPYSUB) instruction
+ */
+static u_int
+decode_26(ir,fpregs)
+u_int ir;
+u_int fpregs[];
+{
+	u_int rm1, rm2, tm, ra, ta; /* operands */
+	u_int fmt;
+	u_int error = 0;
+	u_int status;
+	union {
+		double dbl;
+		float flt;
+		struct { u_int i1; u_int i2; } ints;
+	} mtmp, atmp;
+
+
+	status = fpregs[0];
+	fmt = extru(ir, fpmultifmt, 1);	/* get sgl/dbl flag */
+	if (fmt == 0) { /* DBL */
+		rm1 = extru(ir, fprm1pos, 5) * sizeof(double)/sizeof(u_int);
+		if (rm1 == 0)
+			rm1 = fpzeroreg;
+		rm2 = extru(ir, fprm2pos, 5) * sizeof(double)/sizeof(u_int);
+		if (rm2 == 0)
+			rm2 = fpzeroreg;
+		tm = extru(ir, fptmpos, 5) * sizeof(double)/sizeof(u_int);
+		if (tm == 0)
+			return(MAJOR_26_EXCP);
+		ra = extru(ir, fprapos, 5) * sizeof(double)/sizeof(u_int);
+		if (ra == 0)
+			return(MAJOR_26_EXCP);
+		ta = extru(ir, fptapos, 5) * sizeof(double)/sizeof(u_int);
+		if (ta == 0)
+			return(MAJOR_26_EXCP);
+		
+		if (dbl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
+			error = 1;
+		if (dbl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
+			error = 1;
+		if (error)
+			return(MAJOR_26_EXCP);
+		else {
+			/* copy results */
+			fpregs[tm] = mtmp.ints.i1;
+			fpregs[tm+1] = mtmp.ints.i2;
+			fpregs[ta] = atmp.ints.i1;
+			fpregs[ta+1] = atmp.ints.i2;
+			fpregs[0] = status;
+			return(NOEXCEPTION);
+		}
+	}
+	else { /* SGL */
+		/*
+		 * calculate offsets for single precision numbers
+		 * See table 6-14 in PA-89 architecture for mapping
+		 */
+		rm1 = (extru(ir,fprm1pos,4) | 0x10 ) << 1;	/* get offset */
+		rm1 |= extru(ir,fprm1pos-4,1);	/* add right word offset */
+
+		rm2 = (extru(ir,fprm2pos,4) | 0x10 ) << 1;	/* get offset */
+		rm2 |= extru(ir,fprm2pos-4,1);	/* add right word offset */
+
+		tm = (extru(ir,fptmpos,4) | 0x10 ) << 1;	/* get offset */
+		tm |= extru(ir,fptmpos-4,1);	/* add right word offset */
+
+		ra = (extru(ir,fprapos,4) | 0x10 ) << 1;	/* get offset */
+		ra |= extru(ir,fprapos-4,1);	/* add right word offset */
+
+		ta = (extru(ir,fptapos,4) | 0x10 ) << 1;	/* get offset */
+		ta |= extru(ir,fptapos-4,1);	/* add right word offset */
+		
+		if (sgl_fmpy(&fpregs[rm1],&fpregs[rm2],&mtmp.ints.i1,&status))
+			error = 1;
+		if (sgl_fsub(&fpregs[ta], &fpregs[ra], &atmp.ints.i1,&status))
+			error = 1;
+		if (error)
+			return(MAJOR_26_EXCP);
+		else {
+			/* copy results */
+			fpregs[tm] = mtmp.ints.i1;
+			fpregs[ta] = atmp.ints.i1;
+			fpregs[0] = status;
+			return(NOEXCEPTION);
+		}
+	}
+
+}
+
+/*
+ * routine to decode the 2E (FMPYFADD,FMPYNFADD) instructions
+ */
+static u_int
+decode_2e(ir,fpregs)
+u_int ir;
+u_int fpregs[];
+{
+	u_int rm1, rm2, ra, t; /* operands */
+	u_int fmt;
+
+	fmt = extru(ir,fpfmtpos,1);	/* get fmt completer */
+	if (fmt == DBL) { /* DBL */
+		rm1 = extru(ir,fprm1pos,5) * sizeof(double)/sizeof(u_int);
+		if (rm1 == 0)
+			rm1 = fpzeroreg;
+		rm2 = extru(ir,fprm2pos,5) * sizeof(double)/sizeof(u_int);
+		if (rm2 == 0)
+			rm2 = fpzeroreg;
+		ra = ((extru(ir,fpraupos,3)<<2)|(extru(ir,fpralpos,3)>>1)) *
+		     sizeof(double)/sizeof(u_int);
+		if (ra == 0)
+			ra = fpzeroreg;
+		t = extru(ir,fptpos,5) * sizeof(double)/sizeof(u_int);
+		if (t == 0)
+			return(MAJOR_2E_EXCP);
+
+		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
+			return(dbl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
+					&fpregs[ra], &fpregs[0], &fpregs[t]));
+		} else {
+			return(dbl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
+					&fpregs[ra], &fpregs[0], &fpregs[t]));
+		}
+	} /* end DBL */
+	else { /* SGL */
+		rm1 = (extru(ir,fprm1pos,5)<<1)|(extru(ir,fpxrm1pos,1));
+		if (rm1 == 0)
+			rm1 = fpzeroreg;
+		rm2 = (extru(ir,fprm2pos,5)<<1)|(extru(ir,fpxrm2pos,1));
+		if (rm2 == 0)
+			rm2 = fpzeroreg;
+		ra = (extru(ir,fpraupos,3)<<3)|extru(ir,fpralpos,3);
+		if (ra == 0)
+			ra = fpzeroreg;
+		t = ((extru(ir,fptpos,5)<<1)|(extru(ir,fpxtpos,1)));
+		if (t == 0)
+			return(MAJOR_2E_EXCP);
+
+		if (extru(ir,fpfusedsubop,1)) { /* fmpyfadd or fmpynfadd? */
+			return(sgl_fmpynfadd(&fpregs[rm1], &fpregs[rm2],
+					&fpregs[ra], &fpregs[0], &fpregs[t]));
+		} else {
+			return(sgl_fmpyfadd(&fpregs[rm1], &fpregs[rm2],
+					&fpregs[ra], &fpregs[0], &fpregs[t]));
+		}
+	} /* end SGL */
+}
+
+/*
+ * update_status_cbit
+ *
+ *	This routine returns the correct FP status register value in
+ *	*status, based on the C-bit & V-bit returned by the FCMP
+ *	emulation routine in new_status.  The architecture type
+ *	(PA83, PA89 or PA2.0) is available in fpu_type.  The y_field
+ *	and the architecture type are used to determine what flavor
+ *	of FCMP is being emulated.
+ */
+static void
+update_status_cbit(status, new_status, fpu_type, y_field)
+u_int *status, new_status;
+u_int fpu_type;
+u_int y_field;
+{
+	/*
+	 * For PA89 FPU's which implement the Compare Queue and
+	 * for PA2.0 FPU's, update the Compare Queue if the y-field = 0,
+	 * otherwise update the specified bit in the Compare Array.
+	 * Note that the y-field will always be 0 for non-PA2.0 FPU's.
+	 */
+	if ((fpu_type & TIMEX_EXTEN_FLAG) || 
+	    (fpu_type & ROLEX_EXTEN_FLAG) ||
+	    (fpu_type & PA2_0_FPU_FLAG)) {
+		if (y_field == 0) {
+			*status = ((*status & 0x04000000) >> 5) | /* old Cbit */
+				  ((*status & 0x003ff000) >> 1) | /* old CQ   */
+				  (new_status & 0xffc007ff); /* all other bits*/
+		} else {
+			*status = (*status & 0x04000000) |     /* old Cbit */
+				  ((new_status & 0x04000000) >> (y_field+4)) |
+				  (new_status & ~0x04000000 &  /* other bits */
+				   ~(0x04000000 >> (y_field+4)));
+		}
+	}
+	/* if PA83, just update the C-bit */
+	else {
+		*status = new_status;
+	}
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/frnd.c linux/arch/parisc/math-emu/frnd.c
--- linux.orig/arch/parisc/math-emu/frnd.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/frnd.c	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,252 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  Purpose:
+ *	Single Floating-point Round to Integer
+ *	Double Floating-point Round to Integer
+ *	Quad Floating-point Round to Integer (returns unimplemented)
+ *
+ *  External Interfaces:
+ *	dbl_frnd(srcptr,nullptr,dstptr,status)
+ *	sgl_frnd(srcptr,nullptr,dstptr,status)
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+#include "dbl_float.h"
+#include "cnv_float.h"
+
+/*
+ *  Single Floating-point Round to Integer
+ */
+
+/*ARGSUSED*/
+int
+sgl_frnd(sgl_floating_point *srcptr,
+	unsigned int *nullptr,
+	sgl_floating_point *dstptr,
+	unsigned int *status)
+{
+	register unsigned int src, result;
+	register int src_exponent;
+	register boolean inexact = FALSE;
+
+	src = *srcptr;
+        /*
+         * check source operand for NaN or infinity
+         */
+        if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
+                /*
+                 * is signaling NaN?
+                 */
+                if (Sgl_isone_signaling(src)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Sgl_set_quiet(src);
+                }
+                /*
+                 * return quiet NaN or infinity
+                 */
+                *dstptr = src;
+                return(NOEXCEPTION);
+        }
+	/* 
+	 * Need to round?
+	 */
+	if ((src_exponent -= SGL_BIAS) >= SGL_P - 1) {
+		*dstptr = src;
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		Sgl_clear_exponent_set_hidden(src);
+		result = src;
+		Sgl_rightshift(result,(SGL_P-1) - (src_exponent));
+		/* check for inexact */
+		if (Sgl_isinexact_to_fix(src,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     if (Sgl_iszero_sign(src)) Sgl_increment(result);
+			     break;
+			case ROUNDMINUS:
+			     if (Sgl_isone_sign(src)) Sgl_increment(result);
+			     break;
+			case ROUNDNEAREST:
+			     if (Sgl_isone_roundbit(src,src_exponent))
+			        if (Sgl_isone_stickybit(src,src_exponent) 
+				|| (Sgl_isone_lowmantissa(result))) 
+					Sgl_increment(result);
+			} 
+		}
+		Sgl_leftshift(result,(SGL_P-1) - (src_exponent));
+		if (Sgl_isone_hiddenoverflow(result)) 
+			Sgl_set_exponent(result,src_exponent + (SGL_BIAS+1));
+		else Sgl_set_exponent(result,src_exponent + SGL_BIAS);
+	}
+	else {
+		result = src;  		/* set sign */
+		Sgl_setzero_exponentmantissa(result);
+		/* check for inexact */
+		if (Sgl_isnotzero_exponentmantissa(src)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     if (Sgl_iszero_sign(src)) 
+				Sgl_set_exponent(result,SGL_BIAS);
+			     break;
+			case ROUNDMINUS:
+			     if (Sgl_isone_sign(src)) 
+				Sgl_set_exponent(result,SGL_BIAS);
+			     break;
+			case ROUNDNEAREST:
+			     if (src_exponent == -1)
+			        if (Sgl_isnotzero_mantissa(src))
+				   Sgl_set_exponent(result,SGL_BIAS);
+			} 
+		}
+	}
+	*dstptr = result;
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+} 
+
+/*
+ *  Double Floating-point Round to Integer
+ */
+
+/*ARGSUSED*/
+int
+dbl_frnd(
+	dbl_floating_point *srcptr,
+	unsigned int *nullptr,
+	dbl_floating_point *dstptr,
+	unsigned int *status)
+{
+	register unsigned int srcp1, srcp2, resultp1, resultp2;
+	register int src_exponent;
+	register boolean inexact = FALSE;
+
+	Dbl_copyfromptr(srcptr,srcp1,srcp2);
+        /*
+         * check source operand for NaN or infinity
+         */
+        if ((src_exponent = Dbl_exponent(srcp1)) == DBL_INFINITY_EXPONENT) {
+                /*
+                 * is signaling NaN?
+                 */
+                if (Dbl_isone_signaling(srcp1)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Dbl_set_quiet(srcp1);
+                }
+                /*
+                 * return quiet NaN or infinity
+                 */
+                Dbl_copytoptr(srcp1,srcp2,dstptr);
+                return(NOEXCEPTION);
+        }
+	/* 
+	 * Need to round?
+	 */
+	if ((src_exponent -= DBL_BIAS) >= DBL_P - 1) {
+		Dbl_copytoptr(srcp1,srcp2,dstptr);
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate result
+	 */
+	if (src_exponent >= 0) {
+		Dbl_clear_exponent_set_hidden(srcp1);
+		resultp1 = srcp1;
+		resultp2 = srcp2;
+		Dbl_rightshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
+		/* check for inexact */
+		if (Dbl_isinexact_to_fix(srcp1,srcp2,src_exponent)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     if (Dbl_iszero_sign(srcp1)) 
+				Dbl_increment(resultp1,resultp2);
+			     break;
+			case ROUNDMINUS:
+			     if (Dbl_isone_sign(srcp1)) 
+				Dbl_increment(resultp1,resultp2);
+			     break;
+			case ROUNDNEAREST:
+			     if (Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
+			      if (Dbl_isone_stickybit(srcp1,srcp2,src_exponent) 
+				  || (Dbl_isone_lowmantissap2(resultp2))) 
+					Dbl_increment(resultp1,resultp2);
+			} 
+		}
+		Dbl_leftshift(resultp1,resultp2,(DBL_P-1) - (src_exponent));
+		if (Dbl_isone_hiddenoverflow(resultp1))
+			Dbl_set_exponent(resultp1,src_exponent + (DBL_BIAS+1));
+		else Dbl_set_exponent(resultp1,src_exponent + DBL_BIAS);
+	}
+	else {
+		resultp1 = srcp1;  /* set sign */
+		Dbl_setzero_exponentmantissa(resultp1,resultp2);
+		/* check for inexact */
+		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
+			inexact = TRUE;
+			/*  round result  */
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+			     if (Dbl_iszero_sign(srcp1)) 
+				Dbl_set_exponent(resultp1,DBL_BIAS);
+			     break;
+			case ROUNDMINUS:
+			     if (Dbl_isone_sign(srcp1)) 
+				Dbl_set_exponent(resultp1,DBL_BIAS);
+			     break;
+			case ROUNDNEAREST:
+			     if (src_exponent == -1)
+			        if (Dbl_isnotzero_mantissa(srcp1,srcp2))
+				   Dbl_set_exponent(resultp1,DBL_BIAS);
+			} 
+		}
+	}
+	Dbl_copytoptr(resultp1,resultp2,dstptr);
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/hppa.h linux/arch/parisc/math-emu/hppa.h
--- linux.orig/arch/parisc/math-emu/hppa.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/hppa.h	2002-08-12 22:14:01.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+
+/* amount is assumed to be a constant between 0 and 32 (non-inclusive) */
+#define Shiftdouble(left,right,amount,dest)			\
+    /* int left, right, amount, dest; */			\
+    dest = ((left) << (32-(amount))) | ((unsigned int)(right) >> (amount))
+
+/* amount must be less than 32 */
+#define Variableshiftdouble(left,right,amount,dest)		\
+    /* unsigned int left, right;  int amount, dest; */		\
+    if (amount == 0) dest = right;				\
+    else dest = ((((unsigned) left)&0x7fffffff) << (32-(amount))) |	\
+          ((unsigned) right >> (amount))
+
+/* amount must be between 0 and 32 (non-inclusive) */
+#define Variable_shift_double(left,right,amount,dest)		\
+    /* unsigned int left, right;  int amount, dest; */		\
+    dest = (left << (32-(amount))) | ((unsigned) right >> (amount))
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/math-emu.h linux/arch/parisc/math-emu/math-emu.h
--- linux.orig/arch/parisc/math-emu/math-emu.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/math-emu.h	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,27 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef _PARISC_MATH_EMU_H
+#define _PARISC_MATH_EMU_H
+
+#include <asm/ptrace.h>
+extern int handle_fpe(struct pt_regs *regs);
+
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfadd.c linux/arch/parisc/math-emu/sfadd.c
--- linux.orig/arch/parisc/math-emu/sfadd.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfadd.c	2002-08-12 22:14:21.000000000 +0000
@@ -0,0 +1,518 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfadd.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single_add: add two single precision values.
+ *
+ *  External Interfaces:
+ *	sgl_fadd(leftptr, rightptr, dstptr, status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single_add: add two single precision values.
+ */
+int
+sgl_fadd(
+    sgl_floating_point *leftptr,
+    sgl_floating_point *rightptr,
+    sgl_floating_point *dstptr,
+    unsigned int *status)
+    {
+    register unsigned int left, right, result, extent;
+    register unsigned int signless_upper_left, signless_upper_right, save;
+    
+    
+    register int result_exponent, right_exponent, diff_exponent;
+    register int sign_save, jumpsize;
+    register boolean inexact = FALSE;
+    register boolean underflowtrap;
+        
+    /* Create local copies of the numbers */
+    left = *leftptr;
+    right = *rightptr;
+
+    /* A zero "save" helps discover equal operands (for later),  *
+     * and is used in swapping operands (if needed).             */
+    Sgl_xortointp1(left,right,/*to*/save);
+
+    /*
+     * check first operand for NaN's or infinity
+     */
+    if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
+	{
+	if (Sgl_iszero_mantissa(left)) 
+	    {
+	    if (Sgl_isnotnan(right)) 
+		{
+		if (Sgl_isinfinity(right) && save!=0) 
+		    {
+		    /* 
+		     * invalid since operands are opposite signed infinity's
+		     */
+		    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                    Set_invalidflag();
+                    Sgl_makequietnan(result);
+		    *dstptr = result;
+		    return(NOEXCEPTION);
+		    }
+		/*
+	 	 * return infinity
+	 	 */
+		*dstptr = left;
+		return(NOEXCEPTION);
+		}
+	    }
+	else 
+	    {
+            /*
+             * is NaN; signaling or quiet?
+             */
+            if (Sgl_isone_signaling(left)) 
+		{
+               	/* trap if INVALIDTRAP enabled */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+        	/* make NaN quiet */
+        	Set_invalidflag();
+        	Sgl_set_quiet(left);
+        	}
+	    /* 
+	     * is second operand a signaling NaN? 
+	     */
+	    else if (Sgl_is_signalingnan(right)) 
+		{
+        	/* trap if INVALIDTRAP enabled */
+               	if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+		/* make NaN quiet */
+		Set_invalidflag();
+		Sgl_set_quiet(right);
+		*dstptr = right;
+		return(NOEXCEPTION);
+		}
+	    /*
+ 	     * return quiet NaN
+ 	     */
+ 	    *dstptr = left;
+ 	    return(NOEXCEPTION);
+	    }
+	} /* End left NaN or Infinity processing */
+    /*
+     * check second operand for NaN's or infinity
+     */
+    if (Sgl_isinfinity_exponent(right)) 
+	{
+	if (Sgl_iszero_mantissa(right)) 
+	    {
+	    /* return infinity */
+	    *dstptr = right;
+	    return(NOEXCEPTION);
+	    }
+        /*
+         * is NaN; signaling or quiet?
+         */
+        if (Sgl_isone_signaling(right)) 
+	    {
+            /* trap if INVALIDTRAP enabled */
+	    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+	    /* make NaN quiet */
+	    Set_invalidflag();
+	    Sgl_set_quiet(right);
+	    }
+	/*
+	 * return quiet NaN
+ 	 */
+	*dstptr = right;
+	return(NOEXCEPTION);
+    	} /* End right NaN or Infinity processing */
+
+    /* Invariant: Must be dealing with finite numbers */
+
+    /* Compare operands by removing the sign */
+    Sgl_copytoint_exponentmantissa(left,signless_upper_left);
+    Sgl_copytoint_exponentmantissa(right,signless_upper_right);
+
+    /* sign difference selects add or sub operation. */
+    if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
+	{
+	/* Set the left operand to the larger one by XOR swap *
+	 *  First finish the first word using "save"          */
+	Sgl_xorfromintp1(save,right,/*to*/right);
+	Sgl_xorfromintp1(save,left,/*to*/left);
+	result_exponent = Sgl_exponent(left);
+	}
+    /* Invariant:  left is not smaller than right. */ 
+
+    if((right_exponent = Sgl_exponent(right)) == 0)
+        {
+	/* Denormalized operands.  First look for zeroes */
+	if(Sgl_iszero_mantissa(right)) 
+	    {
+	    /* right is zero */
+	    if(Sgl_iszero_exponentmantissa(left))
+		{
+		/* Both operands are zeros */
+		if(Is_rounding_mode(ROUNDMINUS))
+		    {
+		    Sgl_or_signs(left,/*with*/right);
+		    }
+		else
+		    {
+		    Sgl_and_signs(left,/*with*/right);
+		    }
+		}
+	    else 
+		{
+		/* Left is not a zero and must be the result.  Trapped
+		 * underflows are signaled if left is denormalized.  Result
+		 * is always exact. */
+		if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+		    {
+		    /* need to normalize results mantissa */
+	    	    sign_save = Sgl_signextendedsign(left);
+		    Sgl_leftshiftby1(left);
+		    Sgl_normalize(left,result_exponent);
+		    Sgl_set_sign(left,/*using*/sign_save);
+		    Sgl_setwrapped_exponent(left,result_exponent,unfl);
+		    *dstptr = left;
+		    return(UNDERFLOWEXCEPTION);
+		    }
+		}
+	    *dstptr = left;
+	    return(NOEXCEPTION);
+	    }
+
+	/* Neither are zeroes */
+	Sgl_clear_sign(right);	/* Exponent is already cleared */
+	if(result_exponent == 0 )
+	    {
+	    /* Both operands are denormalized.  The result must be exact
+	     * and is simply calculated.  A sum could become normalized and a
+	     * difference could cancel to a true zero. */
+	    if( (/*signed*/int) save < 0 )
+		{
+		Sgl_subtract(left,/*minus*/right,/*into*/result);
+		if(Sgl_iszero_mantissa(result))
+		    {
+		    if(Is_rounding_mode(ROUNDMINUS))
+			{
+			Sgl_setone_sign(result);
+			}
+		    else
+			{
+			Sgl_setzero_sign(result);
+			}
+		    *dstptr = result;
+		    return(NOEXCEPTION);
+		    }
+		}
+	    else
+		{
+		Sgl_addition(left,right,/*into*/result);
+		if(Sgl_isone_hidden(result))
+		    {
+		    *dstptr = result;
+		    return(NOEXCEPTION);
+		    }
+		}
+	    if(Is_underflowtrap_enabled())
+		{
+		/* need to normalize result */
+	    	sign_save = Sgl_signextendedsign(result);
+		Sgl_leftshiftby1(result);
+		Sgl_normalize(result,result_exponent);
+		Sgl_set_sign(result,/*using*/sign_save);
+                Sgl_setwrapped_exponent(result,result_exponent,unfl);
+		*dstptr = result;
+		return(UNDERFLOWEXCEPTION);
+		}
+	    *dstptr = result;
+	    return(NOEXCEPTION);
+	    }
+	right_exponent = 1;	/* Set exponent to reflect different bias
+				 * with denomalized numbers. */
+	}
+    else
+	{
+	Sgl_clear_signexponent_set_hidden(right);
+	}
+    Sgl_clear_exponent_set_hidden(left);
+    diff_exponent = result_exponent - right_exponent;
+
+    /* 
+     * Special case alignment of operands that would force alignment 
+     * beyond the extent of the extension.  A further optimization
+     * could special case this but only reduces the path length for this
+     * infrequent case.
+     */
+    if(diff_exponent > SGL_THRESHOLD)
+	{
+	diff_exponent = SGL_THRESHOLD;
+	}
+    
+    /* Align right operand by shifting to right */
+    Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
+     /*and lower to*/extent);
+
+    /* Treat sum and difference of the operands separately. */
+    if( (/*signed*/int) save < 0 )
+	{
+	/*
+	 * Difference of the two operands.  Their can be no overflow.  A
+	 * borrow can occur out of the hidden bit and force a post
+	 * normalization phase.
+	 */
+	Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
+	if(Sgl_iszero_hidden(result))
+	    {
+	    /* Handle normalization */
+	    /* A straight foward algorithm would now shift the result
+	     * and extension left until the hidden bit becomes one.  Not
+	     * all of the extension bits need participate in the shift.
+	     * Only the two most significant bits (round and guard) are
+	     * needed.  If only a single shift is needed then the guard
+	     * bit becomes a significant low order bit and the extension
+	     * must participate in the rounding.  If more than a single 
+	     * shift is needed, then all bits to the right of the guard 
+	     * bit are zeros, and the guard bit may or may not be zero. */
+	    sign_save = Sgl_signextendedsign(result);
+            Sgl_leftshiftby1_withextent(result,extent,result);
+
+            /* Need to check for a zero result.  The sign and exponent
+	     * fields have already been zeroed.  The more efficient test
+	     * of the full object can be used.
+	     */
+    	    if(Sgl_iszero(result))
+		/* Must have been "x-x" or "x+(-x)". */
+		{
+		if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
+		*dstptr = result;
+		return(NOEXCEPTION);
+		}
+	    result_exponent--;
+	    /* Look to see if normalization is finished. */
+	    if(Sgl_isone_hidden(result))
+		{
+		if(result_exponent==0)
+		    {
+		    /* Denormalized, exponent should be zero.  Left operand *
+ 		     * was normalized, so extent (guard, round) was zero    */
+		    goto underflow;
+		    }
+		else
+		    {
+		    /* No further normalization is needed. */
+		    Sgl_set_sign(result,/*using*/sign_save);
+	    	    Ext_leftshiftby1(extent);
+		    goto round;
+		    }
+		}
+
+	    /* Check for denormalized, exponent should be zero.  Left    * 
+	     * operand was normalized, so extent (guard, round) was zero */
+	    if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+	       result_exponent==0) goto underflow;
+
+	    /* Shift extension to complete one bit of normalization and
+	     * update exponent. */
+	    Ext_leftshiftby1(extent);
+
+	    /* Discover first one bit to determine shift amount.  Use a
+	     * modified binary search.  We have already shifted the result
+	     * one position right and still not found a one so the remainder
+	     * of the extension must be zero and simplifies rounding. */
+	    /* Scan bytes */
+	    while(Sgl_iszero_hiddenhigh7mantissa(result))
+		{
+		Sgl_leftshiftby8(result);
+		if((result_exponent -= 8) <= 0  && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Now narrow it down to the nibble */
+	    if(Sgl_iszero_hiddenhigh3mantissa(result))
+		{
+		/* The lower nibble contains the normalizing one */
+		Sgl_leftshiftby4(result);
+		if((result_exponent -= 4) <= 0 && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Select case were first bit is set (already normalized)
+	     * otherwise select the proper shift. */
+	    if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
+		{
+		/* Already normalized */
+		if(result_exponent <= 0) goto underflow;
+		Sgl_set_sign(result,/*using*/sign_save);
+		Sgl_set_exponent(result,/*using*/result_exponent);
+		*dstptr = result;
+		return(NOEXCEPTION);
+		}
+	    Sgl_sethigh4bits(result,/*using*/sign_save);
+	    switch(jumpsize) 
+		{
+		case 1:
+		    {
+		    Sgl_leftshiftby3(result);
+		    result_exponent -= 3;
+		    break;
+		    }
+		case 2:
+		case 3:
+		    {
+		    Sgl_leftshiftby2(result);
+		    result_exponent -= 2;
+		    break;
+		    }
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		    {
+		    Sgl_leftshiftby1(result);
+		    result_exponent -= 1;
+		    break;
+		    }
+		}
+	    if(result_exponent > 0) 
+		{
+		Sgl_set_exponent(result,/*using*/result_exponent);
+		*dstptr = result;
+		return(NOEXCEPTION); /* Sign bit is already set */
+		}
+	    /* Fixup potential underflows */
+	  underflow:
+	    if(Is_underflowtrap_enabled())
+		{
+		Sgl_set_sign(result,sign_save);
+                Sgl_setwrapped_exponent(result,result_exponent,unfl);
+		*dstptr = result;
+		/* inexact = FALSE; */
+		return(UNDERFLOWEXCEPTION);
+		}
+	    /* 
+	     * Since we cannot get an inexact denormalized result,
+	     * we can now return.
+	     */
+	    Sgl_right_align(result,/*by*/(1-result_exponent),extent);
+	    Sgl_clear_signexponent(result);
+	    Sgl_set_sign(result,sign_save);
+	    *dstptr = result;
+	    return(NOEXCEPTION);
+	    } /* end if(hidden...)... */
+	/* Fall through and round */
+	} /* end if(save < 0)... */
+    else 
+	{
+	/* Add magnitudes */
+	Sgl_addition(left,right,/*to*/result);
+	if(Sgl_isone_hiddenoverflow(result))
+	    {
+	    /* Prenormalization required. */
+	    Sgl_rightshiftby1_withextent(result,extent,extent);
+	    Sgl_arithrightshiftby1(result);
+	    result_exponent++;
+	    } /* end if hiddenoverflow... */
+	} /* end else ...add magnitudes... */
+    
+    /* Round the result.  If the extension is all zeros,then the result is
+     * exact.  Otherwise round in the correct direction.  No underflow is
+     * possible. If a postnormalization is necessary, then the mantissa is
+     * all zeros so no shift is needed. */
+  round:
+    if(Ext_isnotzero(extent))
+	{
+	inexact = TRUE;
+	switch(Rounding_mode())
+	    {
+	    case ROUNDNEAREST: /* The default. */
+	    if(Ext_isone_sign(extent))
+		{
+		/* at least 1/2 ulp */
+		if(Ext_isnotzero_lower(extent)  ||
+		  Sgl_isone_lowmantissa(result))
+		    {
+		    /* either exactly half way and odd or more than 1/2ulp */
+		    Sgl_increment(result);
+		    }
+		}
+	    break;
+
+	    case ROUNDPLUS:
+	    if(Sgl_iszero_sign(result))
+		{
+		/* Round up positive results */
+		Sgl_increment(result);
+		}
+	    break;
+	    
+	    case ROUNDMINUS:
+	    if(Sgl_isone_sign(result))
+		{
+		/* Round down negative results */
+		Sgl_increment(result);
+		}
+	    
+	    case ROUNDZERO:;
+	    /* truncate is simple */
+	    } /* end switch... */
+	if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
+	}
+    if(result_exponent == SGL_INFINITY_EXPONENT)
+        {
+        /* Overflow */
+        if(Is_overflowtrap_enabled())
+	    {
+	    Sgl_setwrapped_exponent(result,result_exponent,ovfl);
+	    *dstptr = result;
+	    if (inexact)
+		if (Is_inexacttrap_enabled())
+		    return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+		else Set_inexactflag();
+	    return(OVERFLOWEXCEPTION);
+	    }
+        else
+	    {
+	    Set_overflowflag();
+	    inexact = TRUE;
+	    Sgl_setoverflow(result);
+	    }
+	}
+    else Sgl_set_exponent(result,result_exponent);
+    *dstptr = result;
+    if(inexact) 
+	if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+	else Set_inexactflag();
+    return(NOEXCEPTION);
+    }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfcmp.c linux/arch/parisc/math-emu/sfcmp.c
--- linux.orig/arch/parisc/math-emu/sfcmp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfcmp.c	2002-08-12 22:14:17.000000000 +0000
@@ -0,0 +1,155 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfcmp.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	sgl_cmp: compare two values
+ *
+ *  External Interfaces:
+ *	sgl_fcmp(leftptr, rightptr, cond, status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+    
+/*
+ * sgl_cmp: compare two values
+ */
+int
+sgl_fcmp (sgl_floating_point * leftptr, sgl_floating_point * rightptr,
+	  unsigned int cond, unsigned int *status)
+                                           
+                       /* The predicate to be tested */
+                         
+    {
+    register unsigned int left, right;
+    register int xorresult;
+        
+    /* Create local copies of the numbers */
+    left = *leftptr;
+    right = *rightptr;
+
+    /*
+     * Test for NaN
+     */
+    if(    (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
+        || (Sgl_exponent(right) == SGL_INFINITY_EXPONENT) )
+	{
+	/* Check if a NaN is involved.  Signal an invalid exception when 
+	 * comparing a signaling NaN or when comparing quiet NaNs and the
+	 * low bit of the condition is set */
+        if( (  (Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
+	    && Sgl_isnotzero_mantissa(left) 
+	    && (Exception(cond) || Sgl_isone_signaling(left)))
+	   ||
+	    (  (Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
+	    && Sgl_isnotzero_mantissa(right) 
+	    && (Exception(cond) || Sgl_isone_signaling(right)) ) )
+	    {
+	    if( Is_invalidtrap_enabled() ) {
+	    	Set_status_cbit(Unordered(cond));
+		return(INVALIDEXCEPTION);
+	    }
+	    else Set_invalidflag();
+	    Set_status_cbit(Unordered(cond));
+	    return(NOEXCEPTION);
+	    }
+	/* All the exceptional conditions are handled, now special case
+	   NaN compares */
+        else if( ((Sgl_exponent(left) == SGL_INFINITY_EXPONENT)
+	    && Sgl_isnotzero_mantissa(left))
+	   ||
+	    ((Sgl_exponent(right) == SGL_INFINITY_EXPONENT)
+	    && Sgl_isnotzero_mantissa(right)) )
+	    {
+	    /* NaNs always compare unordered. */
+	    Set_status_cbit(Unordered(cond));
+	    return(NOEXCEPTION);
+	    }
+	/* infinities will drop down to the normal compare mechanisms */
+	}
+    /* First compare for unequal signs => less or greater or
+     * special equal case */
+    Sgl_xortointp1(left,right,xorresult);
+    if( xorresult < 0 )
+        {
+        /* left negative => less, left positive => greater.
+         * equal is possible if both operands are zeros. */
+        if( Sgl_iszero_exponentmantissa(left) 
+	  && Sgl_iszero_exponentmantissa(right) )
+            {
+	    Set_status_cbit(Equal(cond));
+	    }
+	else if( Sgl_isone_sign(left) )
+	    {
+	    Set_status_cbit(Lessthan(cond));
+	    }
+	else
+	    {
+	    Set_status_cbit(Greaterthan(cond));
+	    }
+        }
+    /* Signs are the same.  Treat negative numbers separately
+     * from the positives because of the reversed sense.  */
+    else if( Sgl_all(left) == Sgl_all(right) )
+        {
+        Set_status_cbit(Equal(cond));
+        }
+    else if( Sgl_iszero_sign(left) )
+        {
+        /* Positive compare */
+        if( Sgl_all(left) < Sgl_all(right) )
+	    {
+	    Set_status_cbit(Lessthan(cond));
+	    }
+	else
+	    {
+	    Set_status_cbit(Greaterthan(cond));
+	    }
+	}
+    else
+        {
+        /* Negative compare.  Signed or unsigned compares
+         * both work the same.  That distinction is only
+         * important when the sign bits differ. */
+        if( Sgl_all(left) > Sgl_all(right) )
+	    {
+	    Set_status_cbit(Lessthan(cond));
+	    }
+        else
+	    {
+	    Set_status_cbit(Greaterthan(cond));
+	    }
+        }
+	return(NOEXCEPTION);
+    }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfdiv.c linux/arch/parisc/math-emu/sfdiv.c
--- linux.orig/arch/parisc/math-emu/sfdiv.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfdiv.c	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,392 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfdiv.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Precision Floating-point Divide
+ *
+ *  External Interfaces:
+ *	sgl_fdiv(srcptr1,srcptr2,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ *  Single Precision Floating-point Divide
+ */
+
+int
+sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
+	  sgl_floating_point * dstptr, unsigned int *status)
+{
+	register unsigned int opnd1, opnd2, opnd3, result;
+	register int dest_exponent, count;
+	register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+	boolean is_tiny;
+
+	opnd1 = *srcptr1;
+	opnd2 = *srcptr2;
+	/* 
+	 * set sign bit of result 
+	 */
+	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);  
+	else Sgl_setzero(result);
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd1)) {
+		if (Sgl_iszero_mantissa(opnd1)) {
+			if (Sgl_isnotnan(opnd2)) {
+				if (Sgl_isinfinity(opnd2)) {
+					/* 
+					 * invalid since both operands 
+					 * are infinity 
+					 */
+					if (Is_invalidtrap_enabled()) 
+                                		return(INVALIDEXCEPTION);
+                                	Set_invalidflag();
+                                	Sgl_makequietnan(result);
+					*dstptr = result;
+					return(NOEXCEPTION);
+				}
+				/*
+			 	 * return infinity
+			 	 */
+				Sgl_setinfinity_exponentmantissa(result);
+				*dstptr = result;
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+                	/*
+                 	 * is NaN; signaling or quiet?
+                 	 */
+                	if (Sgl_isone_signaling(opnd1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Sgl_set_quiet(opnd1);
+                	}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd2)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled())
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Sgl_set_quiet(opnd2);
+                		*dstptr = opnd2;
+                		return(NOEXCEPTION);
+			}
+                	/*
+                 	 * return quiet NaN
+                 	 */
+                	*dstptr = opnd1;
+                	return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd2)) {
+		if (Sgl_iszero_mantissa(opnd2)) {
+			/*
+			 * return zero
+			 */
+			Sgl_setzero_exponentmantissa(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+                /*
+                 * is NaN; signaling or quiet?
+                 */
+                if (Sgl_isone_signaling(opnd2)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Sgl_set_quiet(opnd2);
+                }
+                /*
+                 * return quiet NaN
+                 */
+                *dstptr = opnd2;
+                return(NOEXCEPTION);
+	}
+	/*
+	 * check for division by zero
+	 */
+	if (Sgl_iszero_exponentmantissa(opnd2)) {
+		if (Sgl_iszero_exponentmantissa(opnd1)) {
+			/* invalid since both operands are zero */
+			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        Set_invalidflag();
+                        Sgl_makequietnan(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+		if (Is_divisionbyzerotrap_enabled())
+                        return(DIVISIONBYZEROEXCEPTION);
+                Set_divisionbyzeroflag();
+                Sgl_setinfinity_exponentmantissa(result);
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+	/*
+	 * Generate exponent 
+	 */
+	dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS;
+
+	/*
+	 * Generate mantissa
+	 */
+	if (Sgl_isnotzero_exponent(opnd1)) {
+		/* set hidden bit */
+		Sgl_clear_signexponent_set_hidden(opnd1);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd1)) {
+			Sgl_setzero_exponentmantissa(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+                /* is denormalized; want to normalize */
+                Sgl_clear_signexponent(opnd1);
+                Sgl_leftshiftby1(opnd1);
+		Sgl_normalize(opnd1,dest_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Sgl_isnotzero_exponent(opnd2)) {
+		Sgl_clear_signexponent_set_hidden(opnd2);
+	}
+	else {
+                /* is denormalized; want to normalize */
+                Sgl_clear_signexponent(opnd2);
+                Sgl_leftshiftby1(opnd2);
+		while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) {
+			Sgl_leftshiftby8(opnd2);
+			dest_exponent += 8;
+		}
+		if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) {
+			Sgl_leftshiftby4(opnd2);
+			dest_exponent += 4;
+		}
+		while(Sgl_iszero_hidden(opnd2)) {
+			Sgl_leftshiftby1(opnd2);
+			dest_exponent += 1;
+		}
+	}
+
+	/* Divide the source mantissas */
+
+	/*
+	 * A non_restoring divide algorithm is used.
+	 */
+	Sgl_subtract(opnd1,opnd2,opnd1);
+	Sgl_setzero(opnd3);
+	for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) {
+		Sgl_leftshiftby1(opnd1);
+		Sgl_leftshiftby1(opnd3);
+		if (Sgl_iszero_sign(opnd1)) {
+			Sgl_setone_lowmantissa(opnd3);
+			Sgl_subtract(opnd1,opnd2,opnd1);
+		}
+		else Sgl_addition(opnd1,opnd2,opnd1);
+	}
+	if (count <= SGL_P) {
+		Sgl_leftshiftby1(opnd3);
+		Sgl_setone_lowmantissa(opnd3);
+		Sgl_leftshift(opnd3,SGL_P-count);
+		if (Sgl_iszero_hidden(opnd3)) {
+			Sgl_leftshiftby1(opnd3);
+			dest_exponent--;
+		}
+	}
+	else {
+		if (Sgl_iszero_hidden(opnd3)) {
+			/* need to get one more bit of result */
+			Sgl_leftshiftby1(opnd1);
+			Sgl_leftshiftby1(opnd3);
+			if (Sgl_iszero_sign(opnd1)) {
+				Sgl_setone_lowmantissa(opnd3);
+				Sgl_subtract(opnd1,opnd2,opnd1);
+			}
+			else Sgl_addition(opnd1,opnd2,opnd1);
+			dest_exponent--;
+		}
+		if (Sgl_iszero_sign(opnd1)) guardbit = TRUE;
+		stickybit = Sgl_all(opnd1);
+	}
+	inexact = guardbit | stickybit;
+
+	/* 
+	 * round result 
+	 */
+	if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
+		Sgl_clear_signexponent(opnd3);
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) 
+					Sgl_increment_mantissa(opnd3);
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) 
+					Sgl_increment_mantissa(opnd3);
+				break;
+			case ROUNDNEAREST:
+				if (guardbit) {
+			   	if (stickybit || Sgl_isone_lowmantissa(opnd3))
+			      	    Sgl_increment_mantissa(opnd3);
+				}
+		}
+		if (Sgl_isone_hidden(opnd3)) dest_exponent++;
+	}
+	Sgl_set_mantissa(result,opnd3);
+
+        /* 
+         * Test for overflow
+         */
+	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
+                /* trap if OVERFLOWTRAP enabled */
+                if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
+                        *dstptr = result;
+                        if (inexact) 
+                            if (Is_inexacttrap_enabled())
+                                return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return(OVERFLOWEXCEPTION);
+                }
+		Set_overflowflag();
+                /* set result to infinity or largest number */
+		Sgl_setoverflow(result);
+		inexact = TRUE;
+	}
+        /* 
+         * Test for underflow
+         */
+	else if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+                        *dstptr = result;
+                        if (inexact) 
+                            if (Is_inexacttrap_enabled())
+                                return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+                            else Set_inexactflag();
+                        return(UNDERFLOWEXCEPTION);
+                }
+
+		/* Determine if should set underflow flag */
+		is_tiny = TRUE;
+		if (dest_exponent == 0 && inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) {
+					Sgl_increment(opnd3);
+					if (Sgl_isone_hiddenoverflow(opnd3))
+                			    is_tiny = FALSE;
+					Sgl_decrement(opnd3);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) {
+					Sgl_increment(opnd3);
+					if (Sgl_isone_hiddenoverflow(opnd3))
+                			    is_tiny = FALSE;
+					Sgl_decrement(opnd3);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Sgl_isone_lowmantissa(opnd3))) {
+				      	Sgl_increment(opnd3);
+					if (Sgl_isone_hiddenoverflow(opnd3))
+                			    is_tiny = FALSE;
+					Sgl_decrement(opnd3);
+				}
+				break;
+			}
+		}
+
+                /*
+                 * denormalize result or set to signed zero
+                 */
+		stickybit = inexact;
+		Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
+
+		/* return rounded number */ 
+		if (inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS:
+				if (Sgl_iszero_sign(result)) {
+					Sgl_increment(opnd3);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result))  {
+					Sgl_increment(opnd3);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Sgl_isone_lowmantissa(opnd3))) {
+			      		Sgl_increment(opnd3);
+				}
+				break;
+			}
+                	if (is_tiny) Set_underflowflag();
+                }
+		Sgl_set_exponentmantissa(result,opnd3);
+	}
+	else Sgl_set_exponent(result,dest_exponent);
+	*dstptr = result;
+	/* check for inexact */
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else  Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfmpy.c linux/arch/parisc/math-emu/sfmpy.c
--- linux.orig/arch/parisc/math-emu/sfmpy.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfmpy.c	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,380 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfmpy.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Precision Floating-point Multiply
+ *
+ *  External Interfaces:
+ *	sgl_fmpy(srcptr1,srcptr2,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ *  Single Precision Floating-point Multiply
+ */
+
+int
+sgl_fmpy(
+    sgl_floating_point *srcptr1,
+    sgl_floating_point *srcptr2,
+    sgl_floating_point *dstptr,
+    unsigned int *status)
+{
+	register unsigned int opnd1, opnd2, opnd3, result;
+	register int dest_exponent, count;
+	register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
+	boolean is_tiny;
+
+	opnd1 = *srcptr1;
+	opnd2 = *srcptr2;
+	/* 
+	 * set sign bit of result 
+	 */
+	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);  
+	else Sgl_setzero(result);
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd1)) {
+		if (Sgl_iszero_mantissa(opnd1)) {
+			if (Sgl_isnotnan(opnd2)) {
+				if (Sgl_iszero_exponentmantissa(opnd2)) {
+					/* 
+					 * invalid since operands are infinity 
+					 * and zero 
+					 */
+					if (Is_invalidtrap_enabled()) 
+                                		return(INVALIDEXCEPTION);
+                                	Set_invalidflag();
+                                	Sgl_makequietnan(result);
+					*dstptr = result;
+					return(NOEXCEPTION);
+				}
+				/*
+			 	 * return infinity
+			 	 */
+				Sgl_setinfinity_exponentmantissa(result);
+				*dstptr = result;
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+                	/*
+                 	 * is NaN; signaling or quiet?
+                 	 */
+                	if (Sgl_isone_signaling(opnd1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Sgl_set_quiet(opnd1);
+                	}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd2)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Sgl_set_quiet(opnd2);
+                		*dstptr = opnd2;
+                		return(NOEXCEPTION);
+			}
+                	/*
+                 	 * return quiet NaN
+                 	 */
+                	*dstptr = opnd1;
+                	return(NOEXCEPTION);
+		}
+	}
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if (Sgl_isinfinity_exponent(opnd2)) {
+		if (Sgl_iszero_mantissa(opnd2)) {
+			if (Sgl_iszero_exponentmantissa(opnd1)) {
+				/* invalid since operands are zero & infinity */
+				if (Is_invalidtrap_enabled()) 
+                                	return(INVALIDEXCEPTION);
+                                Set_invalidflag();
+                                Sgl_makequietnan(opnd2);
+				*dstptr = opnd2;
+				return(NOEXCEPTION);
+			}
+			/*
+			 * return infinity
+			 */
+			Sgl_setinfinity_exponentmantissa(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+                /*
+                 * is NaN; signaling or quiet?
+                 */
+                if (Sgl_isone_signaling(opnd2)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Sgl_set_quiet(opnd2);
+                }
+                /*
+                 * return quiet NaN
+                 */
+                *dstptr = opnd2;
+                return(NOEXCEPTION);
+	}
+	/*
+	 * Generate exponent 
+	 */
+	dest_exponent = Sgl_exponent(opnd1) + Sgl_exponent(opnd2) - SGL_BIAS;
+
+	/*
+	 * Generate mantissa
+	 */
+	if (Sgl_isnotzero_exponent(opnd1)) {
+		/* set hidden bit */
+		Sgl_clear_signexponent_set_hidden(opnd1);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd1)) {
+			Sgl_setzero_exponentmantissa(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+                /* is denormalized, adjust exponent */
+                Sgl_clear_signexponent(opnd1);
+		Sgl_leftshiftby1(opnd1);
+		Sgl_normalize(opnd1,dest_exponent);
+	}
+	/* opnd2 needs to have hidden bit set with msb in hidden bit */
+	if (Sgl_isnotzero_exponent(opnd2)) {
+		Sgl_clear_signexponent_set_hidden(opnd2);
+	}
+	else {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd2)) {
+			Sgl_setzero_exponentmantissa(result);
+			*dstptr = result;
+			return(NOEXCEPTION);
+		}
+                /* is denormalized; want to normalize */
+                Sgl_clear_signexponent(opnd2);
+                Sgl_leftshiftby1(opnd2);
+		Sgl_normalize(opnd2,dest_exponent);
+	}
+
+	/* Multiply two source mantissas together */
+
+	Sgl_leftshiftby4(opnd2);     /* make room for guard bits */
+	Sgl_setzero(opnd3);
+	/*
+	 * Four bits at a time are inspected in each loop, and a
+	 * simple shift and add multiply algorithm is used.
+	 */
+	for (count=1;count<SGL_P;count+=4) {
+		stickybit |= Slow4(opnd3);
+		Sgl_rightshiftby4(opnd3);
+		if (Sbit28(opnd1)) Sall(opnd3) += (Sall(opnd2) << 3);
+		if (Sbit29(opnd1)) Sall(opnd3) += (Sall(opnd2) << 2);
+		if (Sbit30(opnd1)) Sall(opnd3) += (Sall(opnd2) << 1);
+		if (Sbit31(opnd1)) Sall(opnd3) += Sall(opnd2);
+		Sgl_rightshiftby4(opnd1);
+	}
+	/* make sure result is left-justified */
+	if (Sgl_iszero_sign(opnd3)) {
+		Sgl_leftshiftby1(opnd3);
+	}
+	else {
+		/* result mantissa >= 2. */
+		dest_exponent++;
+	}
+	/* check for denormalized result */
+	while (Sgl_iszero_sign(opnd3)) {
+		Sgl_leftshiftby1(opnd3);
+		dest_exponent--;
+	}
+	/*
+	 * check for guard, sticky and inexact bits
+	 */
+	stickybit |= Sgl_all(opnd3) << (SGL_BITLENGTH - SGL_EXP_LENGTH + 1);
+	guardbit = Sbit24(opnd3);
+	inexact = guardbit | stickybit;
+
+	/* re-align mantissa */
+	Sgl_rightshiftby8(opnd3);
+
+	/* 
+	 * round result 
+	 */
+	if (inexact && (dest_exponent>0 || Is_underflowtrap_enabled())) {
+		Sgl_clear_signexponent(opnd3);
+		switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) 
+					Sgl_increment(opnd3);
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) 
+					Sgl_increment(opnd3);
+				break;
+			case ROUNDNEAREST:
+				if (guardbit) {
+			   	if (stickybit || Sgl_isone_lowmantissa(opnd3))
+			      	Sgl_increment(opnd3);
+				}
+		}
+		if (Sgl_isone_hidden(opnd3)) dest_exponent++;
+	}
+	Sgl_set_mantissa(result,opnd3);
+
+        /* 
+         * Test for overflow
+         */
+	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
+                /* trap if OVERFLOWTRAP enabled */
+                if (Is_overflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+			Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
+			*dstptr = result;
+			if (inexact) 
+			    if (Is_inexacttrap_enabled())
+				return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+			    else Set_inexactflag();
+			return(OVERFLOWEXCEPTION);
+                }
+		inexact = TRUE;
+		Set_overflowflag();
+                /* set result to infinity or largest number */
+		Sgl_setoverflow(result);
+	}
+        /* 
+         * Test for underflow
+         */
+	else if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+			Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+			*dstptr = result;
+			if (inexact) 
+			    if (Is_inexacttrap_enabled())
+				return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
+			    else Set_inexactflag();
+			return(UNDERFLOWEXCEPTION);
+                }
+
+		/* Determine if should set underflow flag */
+		is_tiny = TRUE;
+		if (dest_exponent == 0 && inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) {
+					Sgl_increment(opnd3);
+					if (Sgl_isone_hiddenoverflow(opnd3))
+                			    is_tiny = FALSE;
+					Sgl_decrement(opnd3);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) {
+					Sgl_increment(opnd3);
+					if (Sgl_isone_hiddenoverflow(opnd3))
+                			    is_tiny = FALSE;
+					Sgl_decrement(opnd3);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Sgl_isone_lowmantissa(opnd3))) {
+				      	Sgl_increment(opnd3);
+					if (Sgl_isone_hiddenoverflow(opnd3))
+                			    is_tiny = FALSE;
+					Sgl_decrement(opnd3);
+				}
+				break;
+			}
+		}
+
+                /*
+                 * denormalize result or set to signed zero
+                 */
+		stickybit = inexact;
+		Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
+
+		/* return zero or smallest number */
+		if (inexact) {
+			switch (Rounding_mode()) {
+			case ROUNDPLUS: 
+				if (Sgl_iszero_sign(result)) {
+					Sgl_increment(opnd3);
+				}
+				break;
+			case ROUNDMINUS: 
+				if (Sgl_isone_sign(result)) {
+					Sgl_increment(opnd3);
+				}
+				break;
+			case ROUNDNEAREST:
+				if (guardbit && (stickybit || 
+				    Sgl_isone_lowmantissa(opnd3))) {
+			      		Sgl_increment(opnd3);
+				}
+				break;
+			}
+                if (is_tiny) Set_underflowflag();
+		}
+		Sgl_set_exponentmantissa(result,opnd3);
+	}
+	else Sgl_set_exponent(result,dest_exponent);
+	*dstptr = result;
+
+	/* check for inexact */
+	if (inexact) {
+		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+		else Set_inexactflag();
+	}
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfrem.c linux/arch/parisc/math-emu/sfrem.c
--- linux.orig/arch/parisc/math-emu/sfrem.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfrem.c	2002-08-12 22:13:59.000000000 +0000
@@ -0,0 +1,290 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfrem.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Precision Floating-point Remainder
+ *
+ *  External Interfaces:
+ *	sgl_frem(srcptr1,srcptr2,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ *  Single Precision Floating-point Remainder
+ */
+
+int
+sgl_frem (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
+	  sgl_floating_point * dstptr, unsigned int *status)
+{
+	register unsigned int opnd1, opnd2, result;
+	register int opnd1_exponent, opnd2_exponent, dest_exponent, stepcount;
+	register boolean roundup = FALSE;
+
+	opnd1 = *srcptr1;
+	opnd2 = *srcptr2;
+	/*
+	 * check first operand for NaN's or infinity
+	 */
+	if ((opnd1_exponent = Sgl_exponent(opnd1)) == SGL_INFINITY_EXPONENT) {
+		if (Sgl_iszero_mantissa(opnd1)) {
+			if (Sgl_isnotnan(opnd2)) {
+				/* invalid since first operand is infinity */
+				if (Is_invalidtrap_enabled()) 
+                                	return(INVALIDEXCEPTION);
+                                Set_invalidflag();
+                                Sgl_makequietnan(result);
+				*dstptr = result;
+				return(NOEXCEPTION);
+			}
+		}
+		else {
+                	/*
+                 	 * is NaN; signaling or quiet?
+                 	 */
+                	if (Sgl_isone_signaling(opnd1)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Sgl_set_quiet(opnd1);
+                	}
+			/* 
+			 * is second operand a signaling NaN? 
+			 */
+			else if (Sgl_is_signalingnan(opnd2)) {
+                        	/* trap if INVALIDTRAP enabled */
+                        	if (Is_invalidtrap_enabled()) 
+                            		return(INVALIDEXCEPTION);
+                        	/* make NaN quiet */
+                        	Set_invalidflag();
+                        	Sgl_set_quiet(opnd2);
+                		*dstptr = opnd2;
+                		return(NOEXCEPTION);
+			}
+                	/*
+                 	 * return quiet NaN
+                 	 */
+                	*dstptr = opnd1;
+                	return(NOEXCEPTION);
+		}
+	} 
+	/*
+	 * check second operand for NaN's or infinity
+	 */
+	if ((opnd2_exponent = Sgl_exponent(opnd2)) == SGL_INFINITY_EXPONENT) {
+		if (Sgl_iszero_mantissa(opnd2)) {
+			/*
+			 * return first operand
+			 */
+                	*dstptr = opnd1;
+			return(NOEXCEPTION);
+		}
+                /*
+                 * is NaN; signaling or quiet?
+                 */
+                if (Sgl_isone_signaling(opnd2)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Sgl_set_quiet(opnd2);
+                }
+                /*
+                 * return quiet NaN
+                 */
+                *dstptr = opnd2;
+                return(NOEXCEPTION);
+	}
+	/*
+	 * check second operand for zero
+	 */
+	if (Sgl_iszero_exponentmantissa(opnd2)) {
+		/* invalid since second operand is zero */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                Set_invalidflag();
+                Sgl_makequietnan(result);
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+
+	/* 
+	 * get sign of result
+	 */
+	result = opnd1;  
+
+	/* 
+	 * check for denormalized operands
+	 */
+	if (opnd1_exponent == 0) {
+		/* check for zero */
+		if (Sgl_iszero_mantissa(opnd1)) {
+			*dstptr = opnd1;
+			return(NOEXCEPTION);
+		}
+		/* normalize, then continue */
+		opnd1_exponent = 1;
+		Sgl_normalize(opnd1,opnd1_exponent);
+	}
+	else {
+		Sgl_clear_signexponent_set_hidden(opnd1);
+	}
+	if (opnd2_exponent == 0) {
+		/* normalize, then continue */
+		opnd2_exponent = 1;
+		Sgl_normalize(opnd2,opnd2_exponent);
+	}
+	else {
+		Sgl_clear_signexponent_set_hidden(opnd2);
+	}
+
+	/* find result exponent and divide step loop count */
+	dest_exponent = opnd2_exponent - 1;
+	stepcount = opnd1_exponent - opnd2_exponent;
+
+	/*
+	 * check for opnd1/opnd2 < 1
+	 */
+	if (stepcount < 0) {
+		/*
+		 * check for opnd1/opnd2 > 1/2
+		 *
+		 * In this case n will round to 1, so 
+		 *    r = opnd1 - opnd2 
+		 */
+		if (stepcount == -1 && Sgl_isgreaterthan(opnd1,opnd2)) {
+			Sgl_all(result) = ~Sgl_all(result);   /* set sign */
+			/* align opnd2 with opnd1 */
+			Sgl_leftshiftby1(opnd2); 
+			Sgl_subtract(opnd2,opnd1,opnd2);
+			/* now normalize */
+                	while (Sgl_iszero_hidden(opnd2)) {
+                        	Sgl_leftshiftby1(opnd2);
+                        	dest_exponent--;
+			}
+			Sgl_set_exponentmantissa(result,opnd2);
+			goto testforunderflow;
+		}
+		/*
+		 * opnd1/opnd2 <= 1/2
+		 *
+		 * In this case n will round to zero, so 
+		 *    r = opnd1
+		 */
+		Sgl_set_exponentmantissa(result,opnd1);
+		dest_exponent = opnd1_exponent;
+		goto testforunderflow;
+	}
+
+	/*
+	 * Generate result
+	 *
+	 * Do iterative subtract until remainder is less than operand 2.
+	 */
+	while (stepcount-- > 0 && Sgl_all(opnd1)) {
+		if (Sgl_isnotlessthan(opnd1,opnd2))
+			Sgl_subtract(opnd1,opnd2,opnd1);
+		Sgl_leftshiftby1(opnd1);
+	}
+	/*
+	 * Do last subtract, then determine which way to round if remainder 
+	 * is exactly 1/2 of opnd2 
+	 */
+	if (Sgl_isnotlessthan(opnd1,opnd2)) {
+		Sgl_subtract(opnd1,opnd2,opnd1);
+		roundup = TRUE;
+	}
+	if (stepcount > 0 || Sgl_iszero(opnd1)) {
+		/* division is exact, remainder is zero */
+		Sgl_setzero_exponentmantissa(result);
+		*dstptr = result;
+		return(NOEXCEPTION);
+	}
+
+	/* 
+	 * Check for cases where opnd1/opnd2 < n 
+	 *
+	 * In this case the result's sign will be opposite that of
+	 * opnd1.  The mantissa also needs some correction.
+	 */
+	Sgl_leftshiftby1(opnd1);
+	if (Sgl_isgreaterthan(opnd1,opnd2)) {
+		Sgl_invert_sign(result);
+		Sgl_subtract((opnd2<<1),opnd1,opnd1);
+	}
+	/* check for remainder being exactly 1/2 of opnd2 */
+	else if (Sgl_isequal(opnd1,opnd2) && roundup) { 
+		Sgl_invert_sign(result);
+	}
+
+	/* normalize result's mantissa */
+        while (Sgl_iszero_hidden(opnd1)) {
+                dest_exponent--;
+                Sgl_leftshiftby1(opnd1);
+        }
+	Sgl_set_exponentmantissa(result,opnd1);
+
+        /* 
+         * Test for underflow
+         */
+    testforunderflow:
+	if (dest_exponent <= 0) {
+                /* trap if UNDERFLOWTRAP enabled */
+                if (Is_underflowtrap_enabled()) {
+                        /*
+                         * Adjust bias of result
+                         */
+                        Sgl_setwrapped_exponent(result,dest_exponent,unfl);
+			*dstptr = result;
+			/* frem is always exact */
+			return(UNDERFLOWEXCEPTION);
+                }
+                /*
+                 * denormalize result or set to signed zero
+                 */
+                if (dest_exponent >= (1 - SGL_P)) {
+			Sgl_rightshift_exponentmantissa(result,1-dest_exponent);
+                }
+                else {
+			Sgl_setzero_exponentmantissa(result);
+		}
+	}
+	else Sgl_set_exponent(result,dest_exponent);
+	*dstptr = result;
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfsqrt.c linux/arch/parisc/math-emu/sfsqrt.c
--- linux.orig/arch/parisc/math-emu/sfsqrt.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfsqrt.c	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,187 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfsqrt.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single Floating-point Square Root
+ *
+ *  External Interfaces:
+ *	sgl_fsqrt(srcptr,nullptr,dstptr,status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ *  Single Floating-point Square Root
+ */
+
+/*ARGSUSED*/
+unsigned int
+sgl_fsqrt(
+    sgl_floating_point *srcptr,
+    unsigned int *nullptr,
+    sgl_floating_point *dstptr,
+    unsigned int *status)
+{
+	register unsigned int src, result;
+	register int src_exponent;
+	register unsigned int newbit, sum;
+	register boolean guardbit = FALSE, even_exponent;
+
+	src = *srcptr;
+        /*
+         * check source operand for NaN or infinity
+         */
+        if ((src_exponent = Sgl_exponent(src)) == SGL_INFINITY_EXPONENT) {
+                /*
+                 * is signaling NaN?
+                 */
+                if (Sgl_isone_signaling(src)) {
+                        /* trap if INVALIDTRAP enabled */
+                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                        /* make NaN quiet */
+                        Set_invalidflag();
+                        Sgl_set_quiet(src);
+                }
+                /*
+                 * Return quiet NaN or positive infinity.
+		 *  Fall thru to negative test if negative infinity.
+                 */
+		if (Sgl_iszero_sign(src) || Sgl_isnotzero_mantissa(src)) {
+                	*dstptr = src;
+                	return(NOEXCEPTION);
+		}
+        }
+
+        /*
+         * check for zero source operand
+         */
+	if (Sgl_iszero_exponentmantissa(src)) {
+		*dstptr = src;
+		return(NOEXCEPTION);
+	}
+
+        /*
+         * check for negative source operand 
+         */
+	if (Sgl_isone_sign(src)) {
+		/* trap if INVALIDTRAP enabled */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+		/* make NaN quiet */
+		Set_invalidflag();
+		Sgl_makequietnan(src);
+		*dstptr = src;
+		return(NOEXCEPTION);
+	}
+
+	/*
+	 * Generate result
+	 */
+	if (src_exponent > 0) {
+		even_exponent = Sgl_hidden(src);
+		Sgl_clear_signexponent_set_hidden(src);
+	}
+	else {
+		/* normalize operand */
+		Sgl_clear_signexponent(src);
+		src_exponent++;
+		Sgl_normalize(src,src_exponent);
+		even_exponent = src_exponent & 1;
+	}
+	if (even_exponent) {
+		/* exponent is even */
+		/* Add comment here.  Explain why odd exponent needs correction */
+		Sgl_leftshiftby1(src);
+	}
+	/*
+	 * Add comment here.  Explain following algorithm.
+	 * 
+	 * Trust me, it works.
+	 *
+	 */
+	Sgl_setzero(result);
+	newbit = 1 << SGL_P;
+	while (newbit && Sgl_isnotzero(src)) {
+		Sgl_addition(result,newbit,sum);
+		if(sum <= Sgl_all(src)) {
+			/* update result */
+			Sgl_addition(result,(newbit<<1),result);
+			Sgl_subtract(src,sum,src);
+		}
+		Sgl_rightshiftby1(newbit);
+		Sgl_leftshiftby1(src);
+	}
+	/* correct exponent for pre-shift */
+	if (even_exponent) {
+		Sgl_rightshiftby1(result);
+	}
+
+	/* check for inexact */
+	if (Sgl_isnotzero(src)) {
+		if (!even_exponent && Sgl_islessthan(result,src)) 
+			Sgl_increment(result);
+		guardbit = Sgl_lowmantissa(result);
+		Sgl_rightshiftby1(result);
+
+		/*  now round result  */
+		switch (Rounding_mode()) {
+		case ROUNDPLUS:
+		     Sgl_increment(result);
+		     break;
+		case ROUNDNEAREST:
+		     /* stickybit is always true, so guardbit 
+		      * is enough to determine rounding */
+		     if (guardbit) {
+			Sgl_increment(result);
+		     }
+		     break;
+		}
+		/* increment result exponent by 1 if mantissa overflowed */
+		if (Sgl_isone_hiddenoverflow(result)) src_exponent+=2;
+
+		if (Is_inexacttrap_enabled()) {
+			Sgl_set_exponent(result,
+			 ((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
+			*dstptr = result;
+			return(INEXACTEXCEPTION);
+		}
+		else Set_inexactflag();
+	}
+	else {
+		Sgl_rightshiftby1(result);
+	}
+	Sgl_set_exponent(result,((src_exponent-SGL_BIAS)>>1)+SGL_BIAS);
+	*dstptr = result;
+	return(NOEXCEPTION);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sfsub.c linux/arch/parisc/math-emu/sfsub.c
--- linux.orig/arch/parisc/math-emu/sfsub.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sfsub.c	2002-08-12 22:14:18.000000000 +0000
@@ -0,0 +1,521 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/*
+ * BEGIN_DESC
+ *
+ *  File:
+ *	@(#)	pa/spmath/sfsub.c		$Revision: 1.1 $
+ *
+ *  Purpose:
+ *	Single_subtract: subtract two single precision values.
+ *
+ *  External Interfaces:
+ *	sgl_fsub(leftptr, rightptr, dstptr, status)
+ *
+ *  Internal Interfaces:
+ *
+ *  Theory:
+ *	<<please update with a overview of the operation of this file>>
+ *
+ * END_DESC
+*/
+
+
+#include "float.h"
+#include "sgl_float.h"
+
+/*
+ * Single_subtract: subtract two single precision values.
+ */
+int
+sgl_fsub(
+	    sgl_floating_point *leftptr,
+	    sgl_floating_point *rightptr,
+	    sgl_floating_point *dstptr,
+	    unsigned int *status)
+    {
+    register unsigned int left, right, result, extent;
+    register unsigned int signless_upper_left, signless_upper_right, save;
+    
+    register int result_exponent, right_exponent, diff_exponent;
+    register int sign_save, jumpsize;
+    register boolean inexact = FALSE, underflowtrap;
+        
+    /* Create local copies of the numbers */
+    left = *leftptr;
+    right = *rightptr;
+
+    /* A zero "save" helps discover equal operands (for later),  *
+     * and is used in swapping operands (if needed).             */
+    Sgl_xortointp1(left,right,/*to*/save);
+
+    /*
+     * check first operand for NaN's or infinity
+     */
+    if ((result_exponent = Sgl_exponent(left)) == SGL_INFINITY_EXPONENT)
+	{
+	if (Sgl_iszero_mantissa(left)) 
+	    {
+	    if (Sgl_isnotnan(right)) 
+		{
+		if (Sgl_isinfinity(right) && save==0) 
+		    {
+		    /* 
+		     * invalid since operands are same signed infinity's
+		     */
+		    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+                    Set_invalidflag();
+                    Sgl_makequietnan(result);
+		    *dstptr = result;
+		    return(NOEXCEPTION);
+		    }
+		/*
+	 	 * return infinity
+	 	 */
+		*dstptr = left;
+		return(NOEXCEPTION);
+		}
+	    }
+	else 
+	    {
+            /*
+             * is NaN; signaling or quiet?
+             */
+            if (Sgl_isone_signaling(left)) 
+		{
+               	/* trap if INVALIDTRAP enabled */
+		if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+        	/* make NaN quiet */
+        	Set_invalidflag();
+        	Sgl_set_quiet(left);
+        	}
+	    /* 
+	     * is second operand a signaling NaN? 
+	     */
+	    else if (Sgl_is_signalingnan(right)) 
+		{
+        	/* trap if INVALIDTRAP enabled */
+               	if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+		/* make NaN quiet */
+		Set_invalidflag();
+		Sgl_set_quiet(right);
+		*dstptr = right;
+		return(NOEXCEPTION);
+		}
+	    /*
+ 	     * return quiet NaN
+ 	     */
+ 	    *dstptr = left;
+ 	    return(NOEXCEPTION);
+	    }
+	} /* End left NaN or Infinity processing */
+    /*
+     * check second operand for NaN's or infinity
+     */
+    if (Sgl_isinfinity_exponent(right)) 
+	{
+	if (Sgl_iszero_mantissa(right)) 
+	    {
+	    /* return infinity */
+	    Sgl_invert_sign(right);
+	    *dstptr = right;
+	    return(NOEXCEPTION);
+	    }
+        /*
+         * is NaN; signaling or quiet?
+         */
+        if (Sgl_isone_signaling(right)) 
+	    {
+            /* trap if INVALIDTRAP enabled */
+	    if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
+	    /* make NaN quiet */
+	    Set_invalidflag();
+	    Sgl_set_quiet(right);
+	    }
+	/*
+	 * return quiet NaN
+ 	 */
+	*dstptr = right;
+	return(NOEXCEPTION);
+    	} /* End right NaN or Infinity processing */
+
+    /* Invariant: Must be dealing with finite numbers */
+
+    /* Compare operands by removing the sign */
+    Sgl_copytoint_exponentmantissa(left,signless_upper_left);
+    Sgl_copytoint_exponentmantissa(right,signless_upper_right);
+
+    /* sign difference selects sub or add operation. */
+    if(Sgl_ismagnitudeless(signless_upper_left,signless_upper_right))
+	{
+	/* Set the left operand to the larger one by XOR swap *
+	 *  First finish the first word using "save"          */
+	Sgl_xorfromintp1(save,right,/*to*/right);
+	Sgl_xorfromintp1(save,left,/*to*/left);
+	result_exponent = Sgl_exponent(left);
+	Sgl_invert_sign(left);
+	}
+    /* Invariant:  left is not smaller than right. */ 
+
+    if((right_exponent = Sgl_exponent(right)) == 0)
+        {
+	/* Denormalized operands.  First look for zeroes */
+	if(Sgl_iszero_mantissa(right)) 
+	    {
+	    /* right is zero */
+	    if(Sgl_iszero_exponentmantissa(left))
+		{
+		/* Both operands are zeros */
+		Sgl_invert_sign(right);
+		if(Is_rounding_mode(ROUNDMINUS))
+		    {
+		    Sgl_or_signs(left,/*with*/right);
+		    }
+		else
+		    {
+		    Sgl_and_signs(left,/*with*/right);
+		    }
+		}
+	    else 
+		{
+		/* Left is not a zero and must be the result.  Trapped
+		 * underflows are signaled if left is denormalized.  Result
+		 * is always exact. */
+		if( (result_exponent == 0) && Is_underflowtrap_enabled() )
+		    {
+		    /* need to normalize results mantissa */
+	    	    sign_save = Sgl_signextendedsign(left);
+		    Sgl_leftshiftby1(left);
+		    Sgl_normalize(left,result_exponent);
+		    Sgl_set_sign(left,/*using*/sign_save);
+                    Sgl_setwrapped_exponent(left,result_exponent,unfl);
+		    *dstptr = left;
+		    /* inexact = FALSE */
+		    return(UNDERFLOWEXCEPTION);
+		    }
+		}
+	    *dstptr = left;
+	    return(NOEXCEPTION);
+	    }
+
+	/* Neither are zeroes */
+	Sgl_clear_sign(right);	/* Exponent is already cleared */
+	if(result_exponent == 0 )
+	    {
+	    /* Both operands are denormalized.  The result must be exact
+	     * and is simply calculated.  A sum could become normalized and a
+	     * difference could cancel to a true zero. */
+	    if( (/*signed*/int) save >= 0 )
+		{
+		Sgl_subtract(left,/*minus*/right,/*into*/result);
+		if(Sgl_iszero_mantissa(result))
+		    {
+		    if(Is_rounding_mode(ROUNDMINUS))
+			{
+			Sgl_setone_sign(result);
+			}
+		    else
+			{
+			Sgl_setzero_sign(result);
+			}
+		    *dstptr = result;
+		    return(NOEXCEPTION);
+		    }
+		}
+	    else
+		{
+		Sgl_addition(left,right,/*into*/result);
+		if(Sgl_isone_hidden(result))
+		    {
+		    *dstptr = result;
+		    return(NOEXCEPTION);
+		    }
+		}
+	    if(Is_underflowtrap_enabled())
+		{
+		/* need to normalize result */
+	    	sign_save = Sgl_signextendedsign(result);
+		Sgl_leftshiftby1(result);
+		Sgl_normalize(result,result_exponent);
+		Sgl_set_sign(result,/*using*/sign_save);
+                Sgl_setwrapped_exponent(result,result_exponent,unfl);
+		*dstptr = result;
+		/* inexact = FALSE */
+		return(UNDERFLOWEXCEPTION);
+		}
+	    *dstptr = result;
+	    return(NOEXCEPTION);
+	    }
+	right_exponent = 1;	/* Set exponent to reflect different bias
+				 * with denomalized numbers. */
+	}
+    else
+	{
+	Sgl_clear_signexponent_set_hidden(right);
+	}
+    Sgl_clear_exponent_set_hidden(left);
+    diff_exponent = result_exponent - right_exponent;
+
+    /* 
+     * Special case alignment of operands that would force alignment 
+     * beyond the extent of the extension.  A further optimization
+     * could special case this but only reduces the path length for this
+     * infrequent case.
+     */
+    if(diff_exponent > SGL_THRESHOLD)
+	{
+	diff_exponent = SGL_THRESHOLD;
+	}
+    
+    /* Align right operand by shifting to right */
+    Sgl_right_align(/*operand*/right,/*shifted by*/diff_exponent,
+      /*and lower to*/extent);
+
+    /* Treat sum and difference of the operands separately. */
+    if( (/*signed*/int) save >= 0 )
+	{
+	/*
+	 * Difference of the two operands.  Their can be no overflow.  A
+	 * borrow can occur out of the hidden bit and force a post
+	 * normalization phase.
+	 */
+	Sgl_subtract_withextension(left,/*minus*/right,/*with*/extent,/*into*/result);
+	if(Sgl_iszero_hidden(result))
+	    {
+	    /* Handle normalization */
+	    /* A straight foward algorithm would now shift the result
+	     * and extension left until the hidden bit becomes one.  Not
+	     * all of the extension bits need participate in the shift.
+	     * Only the two most significant bits (round and guard) are
+	     * needed.  If only a single shift is needed then the guard
+	     * bit becomes a significant low order bit and the extension
+	     * must participate in the rounding.  If more than a single 
+	     * shift is needed, then all bits to the right of the guard 
+	     * bit are zeros, and the guard bit may or may not be zero. */
+	    sign_save = Sgl_signextendedsign(result);
+            Sgl_leftshiftby1_withextent(result,extent,result);
+
+            /* Need to check for a zero result.  The sign and exponent
+	     * fields have already been zeroed.  The more efficient test
+	     * of the full object can be used.
+	     */
+    	    if(Sgl_iszero(result))
+		/* Must have been "x-x" or "x+(-x)". */
+		{
+		if(Is_rounding_mode(ROUNDMINUS)) Sgl_setone_sign(result);
+		*dstptr = result;
+		return(NOEXCEPTION);
+		}
+	    result_exponent--;
+	    /* Look to see if normalization is finished. */
+	    if(Sgl_isone_hidden(result))
+		{
+		if(result_exponent==0)
+		    {
+		    /* Denormalized, exponent should be zero.  Left operand *
+ 		     * was normalized, so extent (guard, round) was zero    */
+		    goto underflow;
+		    }
+		else
+		    {
+		    /* No further normalization is needed. */
+		    Sgl_set_sign(result,/*using*/sign_save);
+	    	    Ext_leftshiftby1(extent);
+		    goto round;
+		    }
+		}
+
+	    /* Check for denormalized, exponent should be zero.  Left    *
+	     * operand was normalized, so extent (guard, round) was zero */
+	    if(!(underflowtrap = Is_underflowtrap_enabled()) &&
+	       result_exponent==0) goto underflow;
+
+	    /* Shift extension to complete one bit of normalization and
+	     * update exponent. */
+	    Ext_leftshiftby1(extent);
+
+	    /* Discover first one bit to determine shift amount.  Use a
+	     * modified binary search.  We have already shifted the result
+	     * one position right and still not found a one so the remainder
+	     * of the extension must be zero and simplifies rounding. */
+	    /* Scan bytes */
+	    while(Sgl_iszero_hiddenhigh7mantissa(result))
+		{
+		Sgl_leftshiftby8(result);
+		if((result_exponent -= 8) <= 0  && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Now narrow it down to the nibble */
+	    if(Sgl_iszero_hiddenhigh3mantissa(result))
+		{
+		/* The lower nibble contains the normalizing one */
+		Sgl_leftshiftby4(result);
+		if((result_exponent -= 4) <= 0 && !underflowtrap)
+		    goto underflow;
+		}
+	    /* Select case were first bit is set (already normalized)
+	     * otherwise select the proper shift. */
+	    if((jumpsize = Sgl_hiddenhigh3mantissa(result)) > 7)
+		{
+		/* Already normalized */
+		if(result_exponent <= 0) goto underflow;
+		Sgl_set_sign(result,/*using*/sign_save);
+		Sgl_set_exponent(result,/*using*/result_exponent);
+		*dstptr = result;
+		return(NOEXCEPTION);
+		}
+	    Sgl_sethigh4bits(result,/*using*/sign_save);
+	    switch(jumpsize) 
+		{
+		case 1:
+		    {
+		    Sgl_leftshiftby3(result);
+		    result_exponent -= 3;
+		    break;
+		    }
+		case 2:
+		case 3:
+		    {
+		    Sgl_leftshiftby2(result);
+		    result_exponent -= 2;
+		    break;
+		    }
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		    {
+		    Sgl_leftshiftby1(result);
+		    result_exponent -= 1;
+		    break;
+		    }
+		}
+	    if(result_exponent > 0) 
+		{
+		Sgl_set_exponent(result,/*using*/result_exponent);
+		*dstptr = result;	/* Sign bit is already set */
+		return(NOEXCEPTION);
+		}
+	    /* Fixup potential underflows */
+	  underflow:
+	    if(Is_underflowtrap_enabled())
+		{
+		Sgl_set_sign(result,sign_save);
+                Sgl_setwrapped_exponent(result,result_exponent,unfl);
+		*dstptr = result;
+		/* inexact = FALSE */
+		return(UNDERFLOWEXCEPTION);
+		}
+	    /*
+	     * Since we cannot get an inexact denormalized result,
+	     * we can now return.
+	     */
+	    Sgl_right_align(result,/*by*/(1-result_exponent),extent);
+	    Sgl_clear_signexponent(result);
+	    Sgl_set_sign(result,sign_save);
+	    *dstptr = result;
+	    return(NOEXCEPTION);
+	    } /* end if(hidden...)... */
+	/* Fall through and round */
+	} /* end if(save >= 0)... */
+    else 
+	{
+	/* Add magnitudes */
+	Sgl_addition(left,right,/*to*/result);
+	if(Sgl_isone_hiddenoverflow(result))
+	    {
+	    /* Prenormalization required. */
+	    Sgl_rightshiftby1_withextent(result,extent,extent);
+	    Sgl_arithrightshiftby1(result);
+	    result_exponent++;
+	    } /* end if hiddenoverflow... */
+	} /* end else ...sub magnitudes... */
+    
+    /* Round the result.  If the extension is all zeros,then the result is
+     * exact.  Otherwise round in the correct direction.  No underflow is
+     * possible. If a postnormalization is necessary, then the mantissa is
+     * all zeros so no shift is needed. */
+  round:
+    if(Ext_isnotzero(extent))
+	{
+	inexact = TRUE;
+	switch(Rounding_mode())
+	    {
+	    case ROUNDNEAREST: /* The default. */
+	    if(Ext_isone_sign(extent))
+		{
+		/* at least 1/2 ulp */
+		if(Ext_isnotzero_lower(extent)  ||
+		  Sgl_isone_lowmantissa(result))
+		    {
+		    /* either exactly half way and odd or more than 1/2ulp */
+		    Sgl_increment(result);
+		    }
+		}
+	    break;
+
+	    case ROUNDPLUS:
+	    if(Sgl_iszero_sign(result))
+		{
+		/* Round up positive results */
+		Sgl_increment(result);
+		}
+	    break;
+	    
+	    case ROUNDMINUS:
+	    if(Sgl_isone_sign(result))
+		{
+		/* Round down negative results */
+		Sgl_increment(result);
+		}
+	    
+	    case ROUNDZERO:;
+	    /* truncate is simple */
+	    } /* end switch... */
+	if(Sgl_isone_hiddenoverflow(result)) result_exponent++;
+	}
+    if(result_exponent == SGL_INFINITY_EXPONENT)
+        {
+        /* Overflow */
+        if(Is_overflowtrap_enabled())
+	    {
+	    Sgl_setwrapped_exponent(result,result_exponent,ovfl);
+	    *dstptr = result;
+	    if (inexact)
+		if (Is_inexacttrap_enabled())
+		    return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
+		else Set_inexactflag();
+	    return(OVERFLOWEXCEPTION);
+	    }
+        else
+	    {
+	    Set_overflowflag();
+	    inexact = TRUE;
+	    Sgl_setoverflow(result);
+	    }
+	}
+    else Sgl_set_exponent(result,result_exponent);
+    *dstptr = result;
+    if(inexact) 
+	if(Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
+	else Set_inexactflag();
+    return(NOEXCEPTION);
+    }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/sgl_float.h linux/arch/parisc/math-emu/sgl_float.h
--- linux.orig/arch/parisc/math-emu/sgl_float.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/sgl_float.h	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,486 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifdef __NO_PA_HDRS
+    PA header file -- do not include this header file for non-PA builds.
+#endif
+
+/* 32-bit word grabing functions */
+#define Sgl_firstword(value) Sall(value)
+#define Sgl_secondword(value) dummy_location
+#define Sgl_thirdword(value) dummy_location
+#define Sgl_fourthword(value) dummy_location
+
+#define Sgl_sign(object) Ssign(object)
+#define Sgl_exponent(object) Sexponent(object)
+#define Sgl_signexponent(object) Ssignexponent(object)
+#define Sgl_mantissa(object) Smantissa(object)
+#define Sgl_exponentmantissa(object) Sexponentmantissa(object)
+#define Sgl_all(object) Sall(object)
+
+/* sgl_and_signs ands the sign bits of each argument and puts the result
+ * into the first argument. sgl_or_signs ors those same sign bits */
+#define Sgl_and_signs( src1dst, src2)		\
+    Sall(src1dst) = (Sall(src2)|~((unsigned int)1<<31)) & Sall(src1dst)
+#define Sgl_or_signs( src1dst, src2)		\
+    Sall(src1dst) = (Sall(src2)&((unsigned int)1<<31)) | Sall(src1dst)
+
+/* The hidden bit is always the low bit of the exponent */
+#define Sgl_clear_exponent_set_hidden(srcdst) Deposit_sexponent(srcdst,1)
+#define Sgl_clear_signexponent_set_hidden(srcdst) \
+    Deposit_ssignexponent(srcdst,1)
+#define Sgl_clear_sign(srcdst) Sall(srcdst) &= ~((unsigned int)1<<31)
+#define Sgl_clear_signexponent(srcdst) Sall(srcdst) &= 0x007fffff
+
+/* varamount must be less than 32 for the next three functions */
+#define Sgl_rightshift(srcdst, varamount)	\
+    Sall(srcdst) >>= varamount
+#define Sgl_leftshift(srcdst, varamount)	\
+    Sall(srcdst) <<= varamount
+#define Sgl_rightshift_exponentmantissa(srcdst, varamount) \
+    Sall(srcdst) = \
+	(Sexponentmantissa(srcdst) >> varamount) | \
+	(Sall(srcdst) & ((unsigned int)1<<31))
+
+#define Sgl_leftshiftby1_withextent(left,right,result) \
+    Shiftdouble(Sall(left),Extall(right),31,Sall(result))
+    
+#define Sgl_rightshiftby1_withextent(left,right,dst)		\
+    Shiftdouble(Sall(left),Extall(right),1,Extall(right))
+#define Sgl_arithrightshiftby1(srcdst)	\
+    Sall(srcdst) = (int)Sall(srcdst) >> 1
+    
+/* Sign extend the sign bit with an integer destination */
+#define Sgl_signextendedsign(value) Ssignedsign(value)
+
+#define Sgl_isone_hidden(sgl_value) (Shidden(sgl_value))
+#define Sgl_increment(sgl_value) Sall(sgl_value) += 1
+#define Sgl_increment_mantissa(sgl_value) \
+    Deposit_smantissa(sgl_value,sgl_value+1)
+#define Sgl_decrement(sgl_value) Sall(sgl_value) -= 1
+
+#define Sgl_isone_sign(sgl_value) (Is_ssign(sgl_value)!=0)
+#define Sgl_isone_hiddenoverflow(sgl_value) \
+    (Is_shiddenoverflow(sgl_value)!=0)
+#define Sgl_isone_lowmantissa(sgl_value) (Is_slow(sgl_value)!=0)
+#define Sgl_isone_signaling(sgl_value) (Is_ssignaling(sgl_value)!=0)
+#define Sgl_is_signalingnan(sgl_value) (Ssignalingnan(sgl_value)==0x1ff)
+#define Sgl_isnotzero(sgl_value) (Sall(sgl_value)!=0)
+#define Sgl_isnotzero_hiddenhigh7mantissa(sgl_value) \
+    (Shiddenhigh7mantissa(sgl_value)!=0)
+#define Sgl_isnotzero_low4(sgl_value) (Slow4(sgl_value)!=0)
+#define Sgl_isnotzero_exponent(sgl_value) (Sexponent(sgl_value)!=0)
+#define Sgl_isnotzero_mantissa(sgl_value) (Smantissa(sgl_value)!=0)
+#define Sgl_isnotzero_exponentmantissa(sgl_value) \
+    (Sexponentmantissa(sgl_value)!=0)
+#define Sgl_iszero(sgl_value) (Sall(sgl_value)==0)
+#define Sgl_iszero_signaling(sgl_value) (Is_ssignaling(sgl_value)==0)
+#define Sgl_iszero_hidden(sgl_value) (Is_shidden(sgl_value)==0)
+#define Sgl_iszero_hiddenoverflow(sgl_value) \
+    (Is_shiddenoverflow(sgl_value)==0)
+#define Sgl_iszero_hiddenhigh3mantissa(sgl_value) \
+    (Shiddenhigh3mantissa(sgl_value)==0)
+#define Sgl_iszero_hiddenhigh7mantissa(sgl_value) \
+    (Shiddenhigh7mantissa(sgl_value)==0)
+#define Sgl_iszero_sign(sgl_value) (Is_ssign(sgl_value)==0)
+#define Sgl_iszero_exponent(sgl_value) (Sexponent(sgl_value)==0)
+#define Sgl_iszero_mantissa(sgl_value) (Smantissa(sgl_value)==0)
+#define Sgl_iszero_exponentmantissa(sgl_value) \
+    (Sexponentmantissa(sgl_value)==0)
+#define Sgl_isinfinity_exponent(sgl_value) 		\
+    (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT)
+#define Sgl_isnotinfinity_exponent(sgl_value) 		\
+    (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT)
+#define Sgl_isinfinity(sgl_value)			\
+    (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT &&	\
+    Sgl_mantissa(sgl_value)==0)
+#define Sgl_isnan(sgl_value)				\
+    (Sgl_exponent(sgl_value)==SGL_INFINITY_EXPONENT &&	\
+    Sgl_mantissa(sgl_value)!=0)
+#define Sgl_isnotnan(sgl_value)				\
+    (Sgl_exponent(sgl_value)!=SGL_INFINITY_EXPONENT ||	\
+    Sgl_mantissa(sgl_value)==0)
+#define Sgl_islessthan(sgl_op1,sgl_op2)			\
+    (Sall(sgl_op1) < Sall(sgl_op2))
+#define Sgl_isgreaterthan(sgl_op1,sgl_op2)		\
+    (Sall(sgl_op1) > Sall(sgl_op2))
+#define Sgl_isnotlessthan(sgl_op1,sgl_op2)		\
+    (Sall(sgl_op1) >= Sall(sgl_op2))
+#define Sgl_isequal(sgl_op1,sgl_op2)			\
+    (Sall(sgl_op1) == Sall(sgl_op2))
+
+#define Sgl_leftshiftby8(sgl_value) \
+    Sall(sgl_value) <<= 8
+#define Sgl_leftshiftby4(sgl_value) \
+    Sall(sgl_value) <<= 4
+#define Sgl_leftshiftby3(sgl_value) \
+    Sall(sgl_value) <<= 3
+#define Sgl_leftshiftby2(sgl_value) \
+    Sall(sgl_value) <<= 2
+#define Sgl_leftshiftby1(sgl_value) \
+    Sall(sgl_value) <<= 1
+#define Sgl_rightshiftby1(sgl_value) \
+    Sall(sgl_value) >>= 1
+#define Sgl_rightshiftby4(sgl_value) \
+    Sall(sgl_value) >>= 4
+#define Sgl_rightshiftby8(sgl_value) \
+    Sall(sgl_value) >>= 8
+    
+#define Sgl_ismagnitudeless(signlessleft,signlessright)			\
+/*  unsigned int signlessleft, signlessright; */			\
+      (signlessleft < signlessright)  
+    
+
+#define Sgl_copytoint_exponentmantissa(source,dest)     \
+    dest = Sexponentmantissa(source)
+
+/* A quiet NaN has the high mantissa bit clear and at least on other (in this
+ * case the adjacent bit) bit set. */
+#define Sgl_set_quiet(sgl_value) Deposit_shigh2mantissa(sgl_value,1)
+#define Sgl_set_exponent(sgl_value,exp) Deposit_sexponent(sgl_value,exp)
+
+#define Sgl_set_mantissa(dest,value) Deposit_smantissa(dest,value)
+#define Sgl_set_exponentmantissa(dest,value) \
+    Deposit_sexponentmantissa(dest,value)
+
+/*  An infinity is represented with the max exponent and a zero mantissa */
+#define Sgl_setinfinity_exponent(sgl_value) \
+    Deposit_sexponent(sgl_value,SGL_INFINITY_EXPONENT)
+#define Sgl_setinfinity_exponentmantissa(sgl_value)	\
+    Deposit_sexponentmantissa(sgl_value, \
+	(SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))))
+#define Sgl_setinfinitypositive(sgl_value)		\
+    Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH)))
+#define Sgl_setinfinitynegative(sgl_value)		\
+    Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) \
+    | ((unsigned int)1<<31)
+#define Sgl_setinfinity(sgl_value,sign)					\
+    Sall(sgl_value) = (SGL_INFINITY_EXPONENT << (32-(1+SGL_EXP_LENGTH))) | \
+     ((unsigned int)sign << 31)
+#define Sgl_sethigh4bits(sgl_value, extsign)  \
+    Deposit_shigh4(sgl_value,extsign)
+#define Sgl_set_sign(sgl_value,sign) Deposit_ssign(sgl_value,sign)
+#define Sgl_invert_sign(sgl_value)  \
+    Deposit_ssign(sgl_value,~Ssign(sgl_value))
+#define Sgl_setone_sign(sgl_value) Deposit_ssign(sgl_value,1)
+#define Sgl_setone_lowmantissa(sgl_value) Deposit_slow(sgl_value,1)
+#define Sgl_setzero_sign(sgl_value)  Sall(sgl_value) &= 0x7fffffff
+#define Sgl_setzero_exponent(sgl_value) Sall(sgl_value) &= 0x807fffff
+#define Sgl_setzero_mantissa(sgl_value) Sall(sgl_value) &= 0xff800000
+#define Sgl_setzero_exponentmantissa(sgl_value)  Sall(sgl_value) &= 0x80000000
+#define Sgl_setzero(sgl_value) Sall(sgl_value) = 0
+#define Sgl_setnegativezero(sgl_value) Sall(sgl_value) = (unsigned int)1 << 31
+
+/* Use following macro for both overflow & underflow conditions */
+#define ovfl -
+#define unfl +
+#define Sgl_setwrapped_exponent(sgl_value,exponent,op) \
+    Deposit_sexponent(sgl_value,(exponent op SGL_WRAP))
+
+#define Sgl_setlargestpositive(sgl_value) 				\
+    Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH)))	\
+                      | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 )
+#define Sgl_setlargestnegative(sgl_value)				\
+    Sall(sgl_value) = ((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH)))	\
+                      | ((1<<(32-(1+SGL_EXP_LENGTH))) - 1 )		\
+		      | ((unsigned int)1<<31)
+
+#define Sgl_setnegativeinfinity(sgl_value)	\
+    Sall(sgl_value) = 				\
+    ((1<<SGL_EXP_LENGTH) | SGL_INFINITY_EXPONENT) << (32-(1+SGL_EXP_LENGTH))
+#define Sgl_setlargest(sgl_value,sign) 					\
+    Sall(sgl_value) = (unsigned int)sign << 31 |			\
+        (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH)))		\
+	  | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
+#define Sgl_setlargest_exponentmantissa(sgl_value)			\
+    Sall(sgl_value) = Sall(sgl_value) & ((unsigned int)1<<31) |		\
+        (((SGL_EMAX+SGL_BIAS) << (32-(1+SGL_EXP_LENGTH)))		\
+	  | ((1 << (32-(1+SGL_EXP_LENGTH))) - 1 ))
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Sgl_right_align(srcdst,shift,extent)				\
+    /* sgl_floating_point srcdst; int shift; extension extent */	\
+    if (shift < 32) {							\
+	Extall(extent) = Sall(srcdst) << (32-(shift));			\
+    	Sall(srcdst) >>= shift;						\
+    }									\
+    else {								\
+	Extall(extent) = Sall(srcdst);					\
+	Sall(srcdst) = 0;						\
+    }
+#define Sgl_hiddenhigh3mantissa(sgl_value) Shiddenhigh3mantissa(sgl_value)
+#define Sgl_hidden(sgl_value) Shidden(sgl_value)
+#define Sgl_lowmantissa(sgl_value) Slow(sgl_value)
+
+/* The left argument is never smaller than the right argument */
+#define Sgl_subtract(sgl_left,sgl_right,sgl_result) \
+    Sall(sgl_result) = Sall(sgl_left) - Sall(sgl_right)
+
+/* Subtract right augmented with extension from left augmented with zeros and
+ * store into result and extension. */
+#define Sgl_subtract_withextension(left,right,extent,result)		\
+    /* sgl_floating_point left,right,result; extension extent */	\
+  Sgl_subtract(left,right,result);					\
+  if((Extall(extent) = 0-Extall(extent)))				\
+      Sall(result) = Sall(result)-1
+
+#define Sgl_addition(sgl_left,sgl_right,sgl_result) \
+    Sall(sgl_result) = Sall(sgl_left) + Sall(sgl_right)
+
+#define Sgl_xortointp1(left,right,result)			\
+    result = Sall(left) XOR Sall(right);
+
+#define Sgl_xorfromintp1(left,right,result)			\
+    Sall(result) = left XOR Sall(right)
+
+/* Need to Initialize */
+#define Sgl_makequietnan(dest)						\
+    Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH))	\
+                 | (1<<(32-(1+SGL_EXP_LENGTH+2)))
+#define Sgl_makesignalingnan(dest)					\
+    Sall(dest) = ((SGL_EMAX+SGL_BIAS)+1)<< (32-(1+SGL_EXP_LENGTH))	\
+                 | (1<<(32-(1+SGL_EXP_LENGTH+1)))
+
+#define Sgl_normalize(sgl_opnd,exponent)			\
+	while(Sgl_iszero_hiddenhigh7mantissa(sgl_opnd)) {	\
+		Sgl_leftshiftby8(sgl_opnd);			\
+		exponent -= 8;					\
+	}							\
+	if(Sgl_iszero_hiddenhigh3mantissa(sgl_opnd)) {		\
+		Sgl_leftshiftby4(sgl_opnd);			\
+		exponent -= 4;					\
+	}							\
+	while(Sgl_iszero_hidden(sgl_opnd)) {			\
+		Sgl_leftshiftby1(sgl_opnd);			\
+		exponent -= 1;					\
+	}
+
+#define Sgl_setoverflow(sgl_opnd)				\
+	/* set result to infinity or largest number */		\
+	switch (Rounding_mode()) {				\
+		case ROUNDPLUS:					\
+			if (Sgl_isone_sign(sgl_opnd)) {		\
+				Sgl_setlargestnegative(sgl_opnd); \
+			}					\
+			else {					\
+				Sgl_setinfinitypositive(sgl_opnd); \
+			}					\
+			break;					\
+		case ROUNDMINUS:				\
+			if (Sgl_iszero_sign(sgl_opnd)) {	\
+				Sgl_setlargestpositive(sgl_opnd); \
+			}					\
+			else {					\
+				Sgl_setinfinitynegative(sgl_opnd); \
+			}					\
+			break;					\
+		case ROUNDNEAREST:				\
+			Sgl_setinfinity_exponentmantissa(sgl_opnd); \
+			break;					\
+		case ROUNDZERO:					\
+			Sgl_setlargest_exponentmantissa(sgl_opnd); \
+	}
+
+#define Sgl_denormalize(opnd,exponent,guard,sticky,inexact)		\
+	Sgl_clear_signexponent_set_hidden(opnd);			\
+	if (exponent >= (1 - SGL_P)) {					\
+		guard = (Sall(opnd) >> -exponent) & 1;			\
+		if (exponent < 0) sticky |= Sall(opnd) << (32+exponent); \
+		inexact = guard | sticky;				\
+		Sall(opnd) >>= (1-exponent);				\
+	}								\
+	else {								\
+		guard = 0;						\
+		sticky |= Sall(opnd);					\
+		inexact = sticky;					\
+		Sgl_setzero(opnd);					\
+	}
+
+/* 
+ * The fused multiply add instructions requires a single extended format,
+ * with 48 bits of mantissa.
+ */
+#define SGLEXT_THRESHOLD 48
+
+#define Sglext_setzero(valA,valB)	\
+    Sextallp1(valA) = 0; Sextallp2(valB) = 0
+
+#define Sglext_isnotzero_mantissap2(valB) (Sextallp2(valB)!=0)
+#define Sglext_isone_lowp1(val) (Sextlowp1(val)!=0)
+#define Sglext_isone_highp2(val) (Sexthighp2(val)!=0)
+#define Sglext_isnotzero_low31p2(val) (Sextlow31p2(val)!=0)
+#define Sglext_iszero(valA,valB) (Sextallp1(valA)==0 && Sextallp2(valB)==0)
+
+#define Sgl_copytoptr(src,destptr) *destptr = src
+#define Sgl_copyfromptr(srcptr,dest) dest = *srcptr
+#define Sglext_copy(srca,srcb,desta,destb) \
+    Sextallp1(desta) = Sextallp1(srca);	\
+    Sextallp2(destb) = Sextallp2(srcb)
+#define Sgl_copyto_sglext(src1,dest1,dest2) \
+	Sextallp1(dest1) = Sall(src1); Sextallp2(dest2) = 0
+
+#define Sglext_swap_lower(leftp2,rightp2)  \
+    Sextallp2(leftp2)  = Sextallp2(leftp2) XOR Sextallp2(rightp2);  \
+    Sextallp2(rightp2) = Sextallp2(leftp2) XOR Sextallp2(rightp2);  \
+    Sextallp2(leftp2)  = Sextallp2(leftp2) XOR Sextallp2(rightp2)
+
+#define Sglext_setone_lowmantissap2(value) Deposit_dlowp2(value,1)
+
+/* The high bit is always zero so arithmetic or logical shifts will work. */
+#define Sglext_right_align(srcdstA,srcdstB,shift) \
+  {int shiftamt, sticky;						\
+    shiftamt = shift % 32;						\
+    sticky = 0;								\
+    switch (shift/32) {							\
+     case 0: if (shiftamt > 0) {					\
+	        sticky = Sextallp2(srcdstB) << 32 - (shiftamt);		\
+                Variable_shift_double(Sextallp1(srcdstA),		\
+		 Sextallp2(srcdstB),shiftamt,Sextallp2(srcdstB));	\
+	        Sextallp1(srcdstA) >>= shiftamt;			\
+	     }								\
+	     break;							\
+     case 1: if (shiftamt > 0) {					\
+	        sticky = (Sextallp1(srcdstA) << 32 - (shiftamt)) |	\
+			 Sextallp2(srcdstB);				\
+	     }								\
+	     else {							\
+		sticky = Sextallp2(srcdstB);				\
+	     }								\
+	     Sextallp2(srcdstB) = Sextallp1(srcdstA) >> shiftamt;	\
+	     Sextallp1(srcdstA) = 0;					\
+	     break;							\
+    }									\
+    if (sticky) Sglext_setone_lowmantissap2(srcdstB);			\
+  }
+
+/* The left argument is never smaller than the right argument */
+#define Sglext_subtract(lefta,leftb,righta,rightb,resulta,resultb) \
+    if( Sextallp2(rightb) > Sextallp2(leftb) ) Sextallp1(lefta)--; \
+    Sextallp2(resultb) = Sextallp2(leftb) - Sextallp2(rightb);	\
+    Sextallp1(resulta) = Sextallp1(lefta) - Sextallp1(righta)
+
+#define Sglext_addition(lefta,leftb,righta,rightb,resulta,resultb) \
+    /* If the sum of the low words is less than either source, then \
+     * an overflow into the next word occurred. */ \
+    if ((Sextallp2(resultb) = Sextallp2(leftb)+Sextallp2(rightb)) < \
+        Sextallp2(rightb)) \
+	    Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)+1; \
+    else Sextallp1(resulta) = Sextallp1(lefta)+Sextallp1(righta)
+
+
+#define Sglext_arithrightshiftby1(srcdstA,srcdstB)	\
+    Shiftdouble(Sextallp1(srcdstA),Sextallp2(srcdstB),1,Sextallp2(srcdstB)); \
+    Sextallp1(srcdstA) = (int)Sextallp1(srcdstA) >> 1
+   
+#define Sglext_leftshiftby8(valA,valB) \
+    Shiftdouble(Sextallp1(valA),Sextallp2(valB),24,Sextallp1(valA)); \
+    Sextallp2(valB) <<= 8
+#define Sglext_leftshiftby4(valA,valB) \
+    Shiftdouble(Sextallp1(valA),Sextallp2(valB),28,Sextallp1(valA)); \
+    Sextallp2(valB) <<= 4
+#define Sglext_leftshiftby3(valA,valB) \
+    Shiftdouble(Sextallp1(valA),Sextallp2(valB),29,Sextallp1(valA)); \
+    Sextallp2(valB) <<= 3
+#define Sglext_leftshiftby2(valA,valB) \
+    Shiftdouble(Sextallp1(valA),Sextallp2(valB),30,Sextallp1(valA)); \
+    Sextallp2(valB) <<= 2
+#define Sglext_leftshiftby1(valA,valB) \
+    Shiftdouble(Sextallp1(valA),Sextallp2(valB),31,Sextallp1(valA)); \
+    Sextallp2(valB) <<= 1
+
+#define Sglext_rightshiftby4(valueA,valueB) \
+    Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),4,Sextallp2(valueB)); \
+    Sextallp1(valueA) >>= 4
+#define Sglext_rightshiftby3(valueA,valueB) \
+    Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),3,Sextallp2(valueB)); \
+    Sextallp1(valueA) >>= 3
+#define Sglext_rightshiftby1(valueA,valueB) \
+    Shiftdouble(Sextallp1(valueA),Sextallp2(valueB),1,Sextallp2(valueB)); \
+    Sextallp1(valueA) >>= 1
+
+#define Sglext_xortointp1(left,right,result) Sgl_xortointp1(left,right,result)
+#define Sglext_xorfromintp1(left,right,result) \
+	Sgl_xorfromintp1(left,right,result)
+#define Sglext_copytoint_exponentmantissa(src,dest) \
+	Sgl_copytoint_exponentmantissa(src,dest)
+#define Sglext_ismagnitudeless(signlessleft,signlessright) \
+	Sgl_ismagnitudeless(signlessleft,signlessright)
+
+#define Sglext_set_sign(dbl_value,sign)  Sgl_set_sign(dbl_value,sign)  
+#define Sglext_clear_signexponent_set_hidden(srcdst) \
+	Sgl_clear_signexponent_set_hidden(srcdst) 
+#define Sglext_clear_signexponent(srcdst) Sgl_clear_signexponent(srcdst) 
+#define Sglext_clear_sign(srcdst) Sgl_clear_sign(srcdst) 
+#define Sglext_isone_hidden(dbl_value) Sgl_isone_hidden(dbl_value) 
+
+#define Sglext_denormalize(opndp1,opndp2,exponent,is_tiny)		\
+  {int sticky;								\
+    is_tiny = TRUE;							\
+    if (exponent == 0 && Sextallp2(opndp2)) {				\
+	switch (Rounding_mode()) {					\
+	case ROUNDPLUS:							\
+		if (Sgl_iszero_sign(opndp1))				\
+			if (Sgl_isone_hiddenoverflow(opndp1 + 1))	\
+				is_tiny = FALSE;			\
+		break;							\
+	case ROUNDMINUS:						\
+		if (Sgl_isone_sign(opndp1)) {				\
+			if (Sgl_isone_hiddenoverflow(opndp1 + 1))	\
+				is_tiny = FALSE;			\
+		}							\
+		break;							\
+	case ROUNDNEAREST:						\
+		if (Sglext_isone_highp2(opndp2) &&			\
+		    (Sglext_isone_lowp1(opndp1) || 			\
+		     Sglext_isnotzero_low31p2(opndp2)))			\
+			if (Sgl_isone_hiddenoverflow(opndp1 + 1))	\
+				is_tiny = FALSE;			\
+		break;							\
+	}								\
+    }									\
+    Sglext_clear_signexponent_set_hidden(opndp1);			\
+    if (exponent >= (1-DBL_P)) {					\
+	if (exponent >= -31) {						\
+	    if (exponent > -31) {					\
+		sticky = Sextallp2(opndp2) << 31+exponent;		\
+		Variable_shift_double(opndp1,opndp2,1-exponent,opndp2);	\
+		Sextallp1(opndp1) >>= 1-exponent;			\
+	    }								\
+	    else {							\
+		sticky = Sextallp2(opndp2);				\
+		Sextallp2(opndp2) = Sextallp1(opndp1);			\
+		Sextallp1(opndp1) = 0;					\
+	    }								\
+	}								\
+	else {								\
+	    sticky = (Sextallp1(opndp1) << 31+exponent) | 		\
+		     Sextallp2(opndp2);					\
+	    Sextallp2(opndp2) = Sextallp1(opndp1) >> -31-exponent;	\
+	    Sextallp1(opndp1) = 0;					\
+	}								\
+    }									\
+    else {								\
+	sticky = Sextallp1(opndp1) | Sextallp2(opndp2);			\
+	Sglext_setzero(opndp1,opndp2);					\
+    }									\
+    if (sticky) Sglext_setone_lowmantissap2(opndp2);			\
+    exponent = 0;							\
+  }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/math-emu/types.h linux/arch/parisc/math-emu/types.h
--- linux.orig/arch/parisc/math-emu/types.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/math-emu/types.h	2002-08-12 22:14:09.000000000 +0000
@@ -0,0 +1,25 @@
+/*
+ * Linux/PA-RISC Project (http://www.parisc-linux.org/)
+ *
+ * Floating-point emulation code
+ *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2, or (at your option)
+ *    any later version.
+ *
+ *    This program is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/kernel.h>
+#define BUG() do { \
+        printk(KERN_ERR "floating-pt emulation BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/Makefile linux/arch/parisc/mm/Makefile
--- linux.orig/arch/parisc/mm/Makefile	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/mm/Makefile	2002-08-12 22:14:13.000000000 +0000
@@ -8,6 +8,6 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS	 := init.o fault.o kmap.o extable.o
+obj-y	 := init.o fault.o extable.o ioremap.o
 
 include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/extable.c linux/arch/parisc/mm/extable.c
--- linux.orig/arch/parisc/mm/extable.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/mm/extable.c	2002-08-12 22:14:11.000000000 +0000
@@ -46,17 +46,17 @@
 const struct exception_table_entry *
 search_exception_table (unsigned long addr)
 {
-#ifndef CONFIG_MODULE
+#ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
 	return search_one_table(__start___ex_table, 
                                 __stop___ex_table - 1, 
                                 addr);
 #else
-	struct exception_table_entry *ret;
 	/* The kernel is the last "module" -- no need to treat it special. */
 	struct module *mp;
 
 	for (mp = module_list; mp ; mp = mp->next) {
+		const struct exception_table_entry *ret;
 		if (!mp->ex_table_start)
 			continue;
 		ret = search_one_table(mp->ex_table_start, mp->ex_table_end - 1,
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/fault.c linux/arch/parisc/mm/fault.c
--- linux.orig/arch/parisc/mm/fault.c	2001-03-19 20:37:16.000000000 +0000
+++ linux/arch/parisc/mm/fault.c	2002-08-12 22:14:25.000000000 +0000
@@ -17,6 +17,10 @@
 #include <linux/interrupt.h>
 
 #include <asm/uaccess.h>
+#include <asm/traps.h>
+
+#define PRINT_USER_FAULTS /* (turn this on if you want user faults to be */
+			 /*  dumped to the console via printk)          */
 
 
 /* Defines for parisc_acctyp()	*/
@@ -114,59 +118,31 @@
 #undef isGraphicsFlushRead
 #undef BITSSET
 
-/* This is similar to expand_stack(), except that it is for stacks
- * that grow upwards.
- */
-
-static inline int expand_stackup(struct vm_area_struct * vma, unsigned long address)
-{
-	unsigned long grow;
-
-	address += 4 + PAGE_SIZE - 1;
-	address &= PAGE_MASK;
-	grow = (address - vma->vm_end) >> PAGE_SHIFT;
-	if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
-	    ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->rlim[RLIMIT_AS].rlim_cur)
-		return -ENOMEM;
-	vma->vm_end = address;
-	vma->vm_mm->total_vm += grow;
-	if (vma->vm_flags & VM_LOCKED)
-		vma->vm_mm->locked_vm += grow;
-	return 0;
-}
-
-
-/* This is similar to find_vma(), except that it understands that stacks
- * grow up rather than down.
- * XXX Optimise by making use of cache and avl tree as per find_vma().
- */
 
-struct vm_area_struct * pa_find_vma(struct mm_struct * mm, unsigned long addr)
-{
-	struct vm_area_struct *vma = NULL;
-
-	if (mm) {
-		vma = mm->mmap;
-		if (!vma || addr < vma->vm_start)
-			return NULL;
-		while (vma->vm_next && addr >= vma->vm_next->vm_start)
-			vma = vma->vm_next;
-	}
-	return vma;
-}
-
-
-/*
- * This routine handles page faults.  It determines the address,
- * and the problem, and then passes it off to one of the appropriate
- * routines.
- */
-extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);
+#if 0
+/* This is the treewalk to find a vma which is the highest that has
+ * a start < addr.  We're using find_vma_prev instead right now, but
+ * we might want to use this at some point in the future.  Probably
+ * not, but I want it committed to CVS so I don't lose it :-)
+ */
+			while (tree != vm_avl_empty) {
+				if (tree->vm_start > addr) {
+					tree = tree->vm_avl_left;
+				} else {
+					prev = tree;
+					if (prev->vm_next == NULL)
+						break;
+					if (prev->vm_next->vm_start > addr)
+						break;
+					tree = tree->vm_avl_right;
+				}
+			}
+#endif
 
 void do_page_fault(struct pt_regs *regs, unsigned long code,
 			      unsigned long address)
 {
-	struct vm_area_struct * vma;
+	struct vm_area_struct *vma, *prev_vma;
 	struct task_struct *tsk = current;
 	struct mm_struct *mm = tsk->mm;
 	const struct exception_table_entry *fix;
@@ -176,13 +152,9 @@
 		goto no_context;
 
 	down_read(&mm->mmap_sem);
-	vma = pa_find_vma(mm, address);
-	if (!vma)
-		goto bad_area;
-	if (address < vma->vm_end)
-		goto good_area;
-	if (!(vma->vm_flags & VM_GROWSUP) || expand_stackup(vma, address))
-		goto bad_area;
+	vma = find_vma_prev(mm, address, &prev_vma);
+	if (!vma || address < vma->vm_start)
+		goto check_expansion;
 /*
  * Ok, we have a good vm_area for this memory access. We still need to
  * check the access permissions.
@@ -221,6 +193,11 @@
 	up_read(&mm->mmap_sem);
 	return;
 
+check_expansion:
+	vma = prev_vma;
+	if (vma && (expand_stack(vma, address) == 0))
+		goto good_area;
+
 /*
  * Something tried to access memory that isn't in our memory map..
  */
@@ -230,9 +207,16 @@
 	if (user_mode(regs)) {
 		struct siginfo si;
 
-		printk("\ndo_page_fault() pid=%d command='%s'\n",
-		    tsk->pid, tsk->comm);
+#ifdef PRINT_USER_FAULTS
+		printk(KERN_DEBUG "\n");
+		printk(KERN_DEBUG "do_page_fault() pid=%d command='%s' type=%lu address=0x%08lx\n",
+		    tsk->pid, tsk->comm, code, address);
+		if (vma) {
+			printk(KERN_DEBUG "vm_start = 0x%08lx, vm_end = 0x%08lx\n",
+					vma->vm_start, vma->vm_end);
+		}
 		show_regs(regs);
+#endif
 		/* FIXME: actually we need to get the signo and code correct */
 		si.si_signo = SIGSEGV;
 		si.si_errno = 0;
@@ -272,11 +256,11 @@
 		}
 	}
 
-	parisc_terminate("Bad Address (null pointer deref?)",regs,code,address);
+	parisc_terminate("Bad Address (null pointer deref?)", regs, code, address);
 
   out_of_memory:
 	up_read(&mm->mmap_sem);
-	printk("VM: killing process %s\n", current->comm);
+	printk(KERN_CRIT "VM: killing process %s\n", current->comm);
 	if (user_mode(regs))
 		do_exit(SIGKILL);
 	goto no_context;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/init.c linux/arch/parisc/mm/init.c
--- linux.orig/arch/parisc/mm/init.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/mm/init.c	2002-08-12 22:14:19.000000000 +0000
@@ -15,15 +15,400 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/pci.h>		/* for hppa_dma_ops and pcxl_dma_ops */
+#include <linux/blk.h>          /* for initrd_start and initrd_end */
 #include <linux/swap.h>
 #include <linux/unistd.h>
 
 #include <asm/pgalloc.h>
+#include <asm/tlb.h>
 
-static unsigned long totalram_pages;
-extern unsigned long max_pfn, mem_max;
+mmu_gather_t mmu_gathers[NR_CPUS];
 
-void free_initmem(void)  {
+extern char _text;	/* start of kernel code, defined by linker */
+extern int  data_start;
+extern char _end;	/* end of BSS, defined by linker */
+extern char __init_begin, __init_end;
+
+#ifdef CONFIG_DISCONTIGMEM
+struct node_map_data node_data[MAX_PHYSMEM_RANGES];
+bootmem_data_t bmem_data[MAX_PHYSMEM_RANGES];
+unsigned char *chunkmap;
+unsigned int maxchunkmap;
+#endif
+
+static struct resource data_resource = {
+	name:	"Kernel data",
+	flags:	IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource code_resource = {
+	name:	"Kernel code",
+	flags:	IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource pdcdata_resource = {
+	name:	"PDC data (Page Zero)",
+	start:	0,
+	end:	0x9ff,
+	flags:	IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource sysram_resources[MAX_PHYSMEM_RANGES];
+
+static unsigned long max_pfn;
+
+/* The following array is initialized from the firmware specific
+ * information retrieved in kernel/inventory.c.
+ */
+
+physmem_range_t pmem_ranges[MAX_PHYSMEM_RANGES];
+int npmem_ranges;
+
+#ifdef __LP64__
+#define MAX_MEM         (~0UL)
+#else /* !__LP64__ */
+#define MAX_MEM         (3584U*1024U*1024U)
+#endif /* !__LP64__ */
+
+static unsigned long mem_limit = MAX_MEM;
+
+static void __init mem_limit_func(void)
+{
+	char *cp, *end;
+	unsigned long limit;
+	extern char saved_command_line[];
+
+	/* We need this before __setup() functions are called */
+
+	limit = MAX_MEM;
+	for (cp = saved_command_line; *cp; ) {
+		if (memcmp(cp, "mem=", 4) == 0) {
+			cp += 4;
+			limit = memparse(cp, &end);
+			if (end != cp)
+				break;
+			cp = end;
+		} else {
+			while (*cp != ' ' && *cp)
+				++cp;
+			while (*cp == ' ')
+				++cp;
+		}
+	}
+
+	if (limit < mem_limit)
+		mem_limit = limit;
+}
+
+#define MAX_GAP (0x40000000UL >> PAGE_SHIFT)
+
+static void __init setup_bootmem(void)
+{
+	unsigned long bootmap_size;
+	unsigned long mem_max;
+	unsigned long bootmap_pages;
+	unsigned long bootmap_start_pfn;
+	unsigned long bootmap_pfn;
+#ifndef CONFIG_DISCONTIGMEM
+	physmem_range_t pmem_holes[MAX_PHYSMEM_RANGES - 1];
+	int npmem_holes;
+#endif
+	int i, sysram_resource_count;
+
+	disable_sr_hashing(); /* Turn off space register hashing */
+
+#ifdef CONFIG_DISCONTIGMEM
+	/*
+	 * The below is still true as of 2.4.2. If this is ever fixed,
+	 * we can remove this warning!
+	 */
+
+	printk(KERN_WARNING "\n\n");
+	printk(KERN_WARNING "CONFIG_DISCONTIGMEM is enabled, which is probably a mistake. This\n");
+	printk(KERN_WARNING "option can lead to heavy swapping, even when there are gigabytes\n");
+	printk(KERN_WARNING "of free memory.\n\n");
+#endif
+
+#ifdef __LP64__
+
+#ifndef CONFIG_DISCONTIGMEM
+	/*
+	 * Sort the ranges. Since the number of ranges is typically
+	 * small, and performance is not an issue here, just do
+	 * a simple insertion sort.
+	 */
+
+	for (i = 1; i < npmem_ranges; i++) {
+		int j;
+
+		for (j = i; j > 0; j--) {
+			unsigned long tmp;
+
+			if (pmem_ranges[j-1].start_pfn <
+			    pmem_ranges[j].start_pfn) {
+
+				break;
+			}
+			tmp = pmem_ranges[j-1].start_pfn;
+			pmem_ranges[j-1].start_pfn = pmem_ranges[j].start_pfn;
+			pmem_ranges[j].start_pfn = tmp;
+			tmp = pmem_ranges[j-1].pages;
+			pmem_ranges[j-1].pages = pmem_ranges[j].pages;
+			pmem_ranges[j].pages = tmp;
+		}
+	}
+
+	/*
+	 * Throw out ranges that are too far apart (controlled by
+	 * MAX_GAP). If CONFIG_DISCONTIGMEM wasn't implemented so
+	 * poorly, we would recommend enabling that option, but,
+	 * until it is fixed, this is the best way to go.
+	 */
+
+	for (i = 1; i < npmem_ranges; i++) {
+		if (pmem_ranges[i].start_pfn -
+			(pmem_ranges[i-1].start_pfn +
+			 pmem_ranges[i-1].pages) > MAX_GAP) {
+			npmem_ranges = i;
+			break;
+		}
+	}
+#endif
+
+	if (npmem_ranges > 1) {
+
+		/* Print the memory ranges */
+
+		printk(KERN_INFO "Memory Ranges:\n");
+
+		for (i = 0; i < npmem_ranges; i++) {
+			unsigned long start;
+			unsigned long size;
+
+			size = (pmem_ranges[i].pages << PAGE_SHIFT);
+			start = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
+			printk(KERN_INFO "%2d) Start 0x%016lx End 0x%016lx Size %6ld Mb\n",
+				i,start, start + (size - 1), size >> 20);
+		}
+	}
+
+#endif /* __LP64__ */
+
+#if 1
+	/* KLUGE! this really belongs in kernel/resource.c! */
+	iomem_resource.end = ~0UL;
+#endif
+
+	sysram_resource_count = npmem_ranges;
+	for (i = 0; i < sysram_resource_count; i++) {
+		struct resource *res = &sysram_resources[i];
+		res->name = "System RAM";
+		res->start = pmem_ranges[i].start_pfn << PAGE_SHIFT;
+		res->end = res->start + (pmem_ranges[i].pages << PAGE_SHIFT)-1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+		request_resource(&iomem_resource, res);
+	}
+
+	/*
+	 * For 32 bit kernels we limit the amount of memory we can
+	 * support, in order to preserve enough kernel address space
+	 * for other purposes. For 64 bit kernels we don't normally
+	 * limit the memory, but this mechanism can be used to
+	 * artificially limit the amount of memory (and it is written
+	 * to work with multiple memory ranges).
+	 */
+
+	mem_limit_func();       /* check for "mem=" argument */
+
+	mem_max = 0;
+	for (i = 0; i < npmem_ranges; i++) {
+		unsigned long rsize;
+
+		rsize = pmem_ranges[i].pages << PAGE_SHIFT;
+		if ((mem_max + rsize) > mem_limit) {
+			printk(KERN_WARNING "Memory truncated to %ld Mb\n", mem_limit >> 20);
+			if (mem_max == mem_limit)
+				npmem_ranges = i;
+			else {
+				pmem_ranges[i].pages =   (mem_limit >> PAGE_SHIFT)
+						       - (mem_max >> PAGE_SHIFT);
+				npmem_ranges = i + 1;
+				mem_max = mem_limit;
+			}
+			break;
+		}
+		mem_max += rsize;
+	}
+
+	printk(KERN_INFO "Total Memory: %ld Mb\n",mem_max >> 20);
+
+#ifndef CONFIG_DISCONTIGMEM
+
+	/* Merge the ranges, keeping track of the holes */
+
+	{
+		unsigned long end_pfn;
+		unsigned long hole_pages;
+
+		npmem_holes = 0;
+		end_pfn = pmem_ranges[0].start_pfn + pmem_ranges[0].pages;
+		for (i = 1; i < npmem_ranges; i++) {
+
+			hole_pages = pmem_ranges[i].start_pfn - end_pfn;
+			if (hole_pages) {
+				pmem_holes[npmem_holes].start_pfn = end_pfn;
+				pmem_holes[npmem_holes++].pages = hole_pages;
+				end_pfn += hole_pages;
+			}
+			end_pfn += pmem_ranges[i].pages;
+		}
+
+		pmem_ranges[0].pages = end_pfn - pmem_ranges[0].start_pfn;
+		npmem_ranges = 1;
+	}
+#endif
+
+	bootmap_pages = 0;
+	for (i = 0; i < npmem_ranges; i++)
+		bootmap_pages += bootmem_bootmap_pages(pmem_ranges[i].pages);
+
+	bootmap_start_pfn = PAGE_ALIGN(__pa((unsigned long) &_end)) >> PAGE_SHIFT;
+
+#ifdef CONFIG_DISCONTIGMEM
+	for (i = 0; i < npmem_ranges; i++)
+		node_data[i].pg_data.bdata = &bmem_data[i];
+#endif
+	/*
+	 * Initialize and free the full range of memory in each range.
+	 * Note that the only writing these routines do are to the bootmap,
+	 * and we've made sure to locate the bootmap properly so that they
+	 * won't be writing over anything important.
+	 */
+
+	bootmap_pfn = bootmap_start_pfn;
+	max_pfn = 0;
+	for (i = 0; i < npmem_ranges; i++) {
+		unsigned long start_pfn;
+		unsigned long npages;
+
+		start_pfn = pmem_ranges[i].start_pfn;
+		npages = pmem_ranges[i].pages;
+
+		bootmap_size = init_bootmem_node(NODE_DATA(i),
+						bootmap_pfn,
+						start_pfn,
+						(start_pfn + npages) );
+		free_bootmem_node(NODE_DATA(i),
+				  (start_pfn << PAGE_SHIFT),
+				  (npages << PAGE_SHIFT) );
+		bootmap_pfn += (bootmap_size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		if ((start_pfn + npages) > max_pfn)
+			max_pfn = start_pfn + npages;
+	}
+
+	if ((bootmap_pfn - bootmap_start_pfn) != bootmap_pages) {
+		printk(KERN_WARNING "WARNING! bootmap sizing is messed up!\n");
+		BUG();
+	}
+
+	/* reserve PAGE0 pdc memory, kernel text/data/bss & bootmap */
+
+#define PDC_CONSOLE_IO_IODC_SIZE 32768
+
+	reserve_bootmem_node(NODE_DATA(0), 0UL,
+			(unsigned long)(PAGE0->mem_free + PDC_CONSOLE_IO_IODC_SIZE));
+	reserve_bootmem_node(NODE_DATA(0),__pa((unsigned long)&_text),
+			(unsigned long)(&_end - &_text));
+	reserve_bootmem_node(NODE_DATA(0), (bootmap_start_pfn << PAGE_SHIFT),
+			((bootmap_pfn - bootmap_start_pfn) << PAGE_SHIFT));
+
+#ifndef CONFIG_DISCONTIGMEM
+
+	/* reserve the holes */
+
+	for (i = 0; i < npmem_holes; i++) {
+		reserve_bootmem_node(NODE_DATA(0),
+				(pmem_holes[i].start_pfn << PAGE_SHIFT),
+				(pmem_holes[i].pages << PAGE_SHIFT));
+	}
+#endif
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start) {
+		printk(KERN_INFO "initrd: %08lx-%08lx\n", initrd_start, initrd_end);
+		if (__pa(initrd_start) < mem_max) {
+			unsigned long initrd_reserve;
+
+			if (__pa(initrd_end) > mem_max) {
+				initrd_reserve = mem_max - __pa(initrd_start);
+			} else {
+				initrd_reserve = initrd_end - initrd_start;
+			}
+			initrd_below_start_ok = 1;
+			printk(KERN_INFO "initrd: reserving %08lx-%08lx (mem_max %08lx)\n", __pa(initrd_start), __pa(initrd_start) + initrd_reserve, mem_max);
+
+			reserve_bootmem_node(NODE_DATA(0),__pa(initrd_start), initrd_reserve);
+		}
+	}
+#endif
+
+	data_resource.start =  virt_to_phys(&data_start);
+	data_resource.end = virt_to_phys(&_end)-1;
+	code_resource.start = virt_to_phys(&_text);
+	code_resource.end = virt_to_phys(&data_start)-1;
+
+	/* We don't know which region the kernel will be in, so try
+	 * all of them.
+	 */
+	for (i = 0; i < sysram_resource_count; i++) {
+		struct resource *res = &sysram_resources[i];
+		request_resource(res, &code_resource);
+		request_resource(res, &data_resource);
+	}
+	request_resource(&sysram_resources[0], &pdcdata_resource);
+}
+
+void free_initmem(void)
+{
+	/* FIXME: */
+#if 0
+	printk(KERN_INFO "NOT FREEING INITMEM (%dk)\n",
+			(&__init_end - &__init_begin) >> 10);
+	return;
+#endif
+	unsigned long addr;
+	
+	printk(KERN_INFO "Freeing unused kernel memory: ");
+
+#if 1
+	/* Attempt to catch anyone trying to execute code here
+	 * by filling the page with BRK insns.
+	 * 
+	 * If we disable interrupts for all CPUs, then IPI stops working.
+	 * Kinda breaks the global cache flushing.
+	 */
+	local_irq_disable();
+
+	memset(&__init_begin, 0x00, 
+		(unsigned long)&__init_end - (unsigned long)&__init_begin);
+
+	flush_data_cache();
+	asm volatile("sync" : : );
+	flush_icache_range((unsigned long)&__init_begin, (unsigned long)&__init_end);
+	asm volatile("sync" : : );
+
+	local_irq_enable();
+#endif
+	
+	addr = (unsigned long)(&__init_begin);
+	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		set_page_count(virt_to_page(addr), 1);
+		free_page(addr);
+		num_physpages++;
+	}
+
+	printk("%luk freed\n", (unsigned long)(&__init_end - &__init_begin) >> 10);
 }
 
 /*
@@ -37,67 +422,42 @@
  * a hole of 4kB between each vmalloced area for the same reason.
  */
 
+#define MAP_START 0x4000 /* Leave room for gateway page expansion */
 #define VM_MAP_OFFSET  (32*1024)
 #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \
 				     & ~(VM_MAP_OFFSET-1)))
 
 void *vmalloc_start;
+#ifdef CONFIG_PA11
 unsigned long pcxl_dma_start;
+#endif
 
 void __init mem_init(void)
 {
-	max_mapnr = num_physpages = max_low_pfn;
-	high_memory = __va(max_low_pfn * PAGE_SIZE);
+	int i;
+
+	high_memory = __va((max_pfn << PAGE_SHIFT));
+	max_mapnr = (virt_to_page(high_memory - 1) - mem_map) + 1;
+
+	num_physpages = 0;
+	for (i = 0; i < npmem_ranges; i++)
+		num_physpages += free_all_bootmem_node(NODE_DATA(i));
 
-	totalram_pages += free_all_bootmem();
-	printk("Memory: %luk available\n", totalram_pages << (PAGE_SHIFT-10));
+	printk(KERN_INFO "Memory: %luk available\n", num_physpages << (PAGE_SHIFT-10));
 
+#ifdef CONFIG_PA11
 	if (hppa_dma_ops == &pcxl_dma_ops) {
-	    pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(high_memory);
+	    pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START);
 	    vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE);
 	}
 	else {
 	    pcxl_dma_start = 0;
-	    vmalloc_start = SET_MAP_OFFSET(high_memory);
-	}
-}
-
-void __bad_pgd(pgd_t *pgd)
-{
-	printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
-	pgd_val(*pgd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
-}
-
-void __bad_pmd(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
-}
-
-pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
-{
-	pte_t *pte;
-
-	pte = (pte_t *) __get_free_page(GFP_KERNEL);
-
-	if (pmd_none(*pmd)) {
-		if (pte) {
-			clear_page(pte);
-			pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)pte);
-			return pte + offset;
-		}
-		pmd_val(*pmd) = _PAGE_TABLE + __pa(BAD_PAGETABLE);
-		return NULL;
-	}
-
-	free_page((unsigned long)pte);
-
-	if (pmd_bad(*pmd)) {
-		__bad_pmd(pmd);
-		return NULL;
+	    vmalloc_start = SET_MAP_OFFSET(MAP_START);
 	}
+#else
+	vmalloc_start = SET_MAP_OFFSET(MAP_START);
+#endif
 
-	return (pte_t *) pmd_page(*pmd) + offset;
 }
 
 int do_check_pgt_cache(int low, int high)
@@ -105,40 +465,16 @@
 	return 0;
 }
 
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving an inode
- * unused etc..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-pte_t * __bad_pagetable(void)
-{
-	return (pte_t *) NULL;
-}
-
 unsigned long *empty_zero_page;
-unsigned long *empty_bad_page;
-
-pte_t __bad_page(void)
-{
-	return *(pte_t *)NULL;
-}
 
 void show_mem(void)
 {
 	int i,free = 0,total = 0,reserved = 0;
 	int shared = 0, cached = 0;
 
-	printk("Mem-info:\n");
+	printk(KERN_INFO "Mem-info:\n");
 	show_free_areas();
-	printk("Free swap:	 %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+	printk(KERN_INFO "Free swap:	 %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
 	i = max_mapnr;
 	while (i-- > 0) {
 		total++;
@@ -151,54 +487,50 @@
 		else
 			shared += atomic_read(&mem_map[i].count) - 1;
 	}
-	printk("%d pages of RAM\n",total);
-	printk("%d reserved pages\n",reserved);
-	printk("%d pages shared\n",shared);
-	printk("%d pages swap cached\n",cached);
+	printk(KERN_INFO "%d pages of RAM\n", total);
+	printk(KERN_INFO "%d reserved pages\n", reserved);
+	printk(KERN_INFO "%d pages shared\n", shared);
+	printk(KERN_INFO "%d pages swap cached\n", cached);
 	show_buffers();
 }
 
-void set_pte_phys (unsigned long vaddr, unsigned long phys)
-{
-}
-
 
-/*
- * pagetable_init() sets up the page tables
- *
- * Note that gateway_init() places the Linux gateway page at page 0.
- * Since gateway pages cannot be dereferenced this has the desirable
- * side effect of trapping those pesky NULL-reference errors in the
- * kernel.
- */
-static void __init pagetable_init(void)
+static void __init map_pages(unsigned long start_vaddr, unsigned long start_paddr, unsigned long size, pgprot_t pgprot)
 {
 	pgd_t *pg_dir;
 	pmd_t *pmd;
 	pte_t *pg_table;
+	unsigned long end_paddr;
+	unsigned long start_pmd;
+	unsigned long start_pte;
 	unsigned long tmp1;
 	unsigned long tmp2;
 	unsigned long address;
 	unsigned long ro_start;
 	unsigned long ro_end;
 	unsigned long fv_addr;
-	extern  const int stext;
-	extern  int data_start;
-	extern  const unsigned long fault_vector_20;
+	unsigned long gw_addr;
+	extern const unsigned long fault_vector_20;
+	extern void * const linux_gateway_page;
 
-	ro_start = __pa((unsigned long)&stext);
+	ro_start = __pa((unsigned long)&_text);
 	ro_end   = __pa((unsigned long)&data_start);
 	fv_addr  = __pa((unsigned long)&fault_vector_20) & PAGE_MASK;
+	gw_addr  = __pa((unsigned long)&linux_gateway_page) & PAGE_MASK;
 
-	printk("pagetable_init\n");
+	end_paddr = start_paddr + size;
 
-	/* Map whole memory from PAGE_OFFSET */
-	pg_dir = (pgd_t *)swapper_pg_dir + USER_PGD_PTRS;
+	pg_dir = pgd_offset_k(start_vaddr);
 
-	address = 0;
-	while (address < mem_max) {
-		/* XXX: BTLB should be done here */
+#if PTRS_PER_PMD == 1
+	start_pmd = 0;
+#else
+	start_pmd = ((start_vaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+#endif
+	start_pte = ((start_vaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
 
+	address = start_paddr;
+	while (address < end_paddr) {
 #if PTRS_PER_PMD == 1
 		pmd = (pmd_t *)__pa(pg_dir);
 #else
@@ -209,7 +541,7 @@
 		 */
 
 		if (!pmd) {
-			pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+			pmd = (pmd_t *) alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
 			pmd = (pmd_t *) __pa(pmd);
 		}
 
@@ -219,8 +551,8 @@
 
 		/* now change pmd to kernel virtual addresses */
 
-		pmd = (pmd_t *) __va(pmd);
-		for (tmp1 = 0 ; tmp1 < PTRS_PER_PMD ; tmp1++,pmd++) {
+		pmd = (pmd_t *)__va(pmd) + start_pmd;
+		for (tmp1 = start_pmd; tmp1 < PTRS_PER_PMD; tmp1++,pmd++) {
 
 			/*
 			 * pg_table is physical at this point
@@ -229,7 +561,7 @@
 			pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
 			if (!pg_table) {
 				pg_table = (pte_t *)
-					alloc_bootmem_low_pages(PAGE_SIZE);
+					alloc_bootmem_low_pages_node(NODE_DATA(0),PAGE_SIZE);
 				pg_table = (pte_t *) __pa(pg_table);
 			}
 
@@ -238,8 +570,8 @@
 
 			/* now change pg_table to kernel virtual addresses */
 
-			pg_table = (pte_t *) __va(pg_table);
-			for (tmp2=0; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
+			pg_table = (pte_t *) __va(pg_table) + start_pte;
+			for (tmp2 = start_pte; tmp2 < PTRS_PER_PTE; tmp2++,pg_table++) {
 				pte_t pte;
 
 #if !defined(CONFIG_KWDB) && !defined(CONFIG_STI_CONSOLE)
@@ -249,53 +581,84 @@
 ** The right thing to do seems like KWDB modify only the pte which
 ** has a break point on it...otherwise we might mask worse bugs.
 */
+				/*
+				 * Map the fault vector writable so we can
+				 * write the HPMC checksum.
+				 */
 				if (address >= ro_start && address < ro_end
-							&& address != fv_addr)
+							&& address != fv_addr
+							&& address != gw_addr)
 				    pte = __mk_pte(address, PAGE_KERNEL_RO);
 				else
 #endif
-				    pte = __mk_pte(address, PAGE_KERNEL);
+				    pte = __mk_pte(address, pgprot);
 
-				if (address >= mem_max)
+				if (address >= end_paddr)
 					pte_val(pte) = 0;
 
 				set_pte(pg_table, pte);
 
 				address += PAGE_SIZE;
 			}
+			start_pte = 0;
 
-			if (address >= mem_max)
+			if (address >= end_paddr)
 			    break;
 		}
+		start_pmd = 0;
 	}
+}
+
+/*
+ * pagetable_init() sets up the page tables
+ *
+ * Note that gateway_init() places the Linux gateway page at page 0.
+ * Since gateway pages cannot be dereferenced this has the desirable
+ * side effect of trapping those pesky NULL-reference errors in the
+ * kernel.
+ */
+static void __init pagetable_init(void)
+{
+	int range;
+
+	printk("pagetable_init\n");
+
+	/* Map each physical memory range to its kernel vaddr */
+
+	for (range = 0; range < npmem_ranges; range++) {
+		unsigned long start_paddr;
+		unsigned long end_paddr;
+		unsigned long size;
+
+		start_paddr = pmem_ranges[range].start_pfn << PAGE_SHIFT;
+		end_paddr = start_paddr + (pmem_ranges[range].pages << PAGE_SHIFT);
+		size = pmem_ranges[range].pages << PAGE_SHIFT;
+
+		map_pages((unsigned long)__va(start_paddr), start_paddr,
+			size, PAGE_KERNEL);
+	}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_end && initrd_end > mem_limit) {
+		printk("initrd: mapping %08lx-%08lx\n", initrd_start, initrd_end);
+		map_pages(initrd_start, __pa(initrd_start),
+			initrd_end - initrd_start, PAGE_KERNEL);
+	}
+#endif
 
 	empty_zero_page = alloc_bootmem_pages(PAGE_SIZE);
 	memset(empty_zero_page, 0, PAGE_SIZE);
 }
 
-unsigned long gateway_pgd_offset;
-unsigned long gateway_pgd_entry;
-
 static void __init gateway_init(void)
 {
-	unsigned long hpux_gateway_page_addr;
 	unsigned long linux_gateway_page_addr;
-	pgd_t *pg_dir;
-	pmd_t *pmd_base;
-	pmd_t *pmd;
-	pte_t *pg_table_base;
-	pte_t *pg_table;
-	/* FIXME: These are 'const' in order to trick the compiler
-           into not treating them as DP-relative data. */
-	extern void * const hpux_gateway_page;
+	/* FIXME: This is 'const' in order to trick the compiler
+	   into not treating it as DP-relative data. */
 	extern void * const linux_gateway_page;
-	pte_t pte;
 
-	hpux_gateway_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
 	linux_gateway_page_addr = LINUX_GATEWAY_ADDR & PAGE_MASK;
 
-	gateway_pgd_offset = hpux_gateway_page_addr >> PGDIR_SHIFT;
-
 	/*
 	 * Setup Linux Gateway page.
 	 *
@@ -303,177 +666,356 @@
 	 * page 0), so it doesn't need to be aliased into user space.
 	 */
 
-	pg_dir = (pgd_t *)swapper_pg_dir;
-
-#if PTRS_PER_PMD == 1
-	pmd_base = (pmd_t *)pg_dir;
-	pmd = pmd_base +
-		((linux_gateway_page_addr) >> PGDIR_SHIFT);
-
-#else
-	pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
-	pgd_val(*(pg_dir + (linux_gateway_page_addr >> PGDIR_SHIFT))) =
-		_PAGE_TABLE | __pa(pmd_base);
+	map_pages(linux_gateway_page_addr, __pa(&linux_gateway_page),
+		PAGE_SIZE, PAGE_GATEWAY);
+}
 
-	pmd = pmd_base +
-		((linux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
-								PMD_SHIFT);
-#endif
+void
+map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm)
+{
+	pgd_t *pg_dir;
+	pmd_t *pmd;
+	pte_t *pg_table;
+	unsigned long start_pmd;
+	unsigned long start_pte;
+	unsigned long address;
+	unsigned long hpux_gw_page_addr;
+	/* FIXME: This is 'const' in order to trick the compiler
+	   into not treating it as DP-relative data. */
+	extern void * const hpux_gateway_page;
 
-	pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
+	hpux_gw_page_addr = HPUX_GATEWAY_ADDR & PAGE_MASK;
 
-	pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
+	/*
+	 * Setup HP-UX Gateway page.
+	 *
+	 * The HP-UX gateway page resides in the user address space,
+	 * so it needs to be aliased into each process.
+	 */
 
-	pte = __mk_pte(__pa(&linux_gateway_page), PAGE_GATEWAY);
+	pg_dir = pgd_offset(mm,hpux_gw_page_addr);
 
-	pg_table = pg_table_base +
-		((linux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
-								PAGE_SHIFT);
+#if PTRS_PER_PMD == 1
+	start_pmd = 0;
+#else
+	start_pmd = ((hpux_gw_page_addr >> PMD_SHIFT) & (PTRS_PER_PMD - 1));
+#endif
+	start_pte = ((hpux_gw_page_addr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
 
-	set_pte(pg_table,pte);
+	address = __pa(&hpux_gateway_page);
+#if PTRS_PER_PMD == 1
+	pmd = (pmd_t *)__pa(pg_dir);
+#else
+	pmd = (pmd_t *) (PAGE_MASK & pgd_val(*pg_dir));
 
 	/*
-	 * Setup HP-UX gateway page.
-	 * This page will be aliased into each user address space.
+	 * pmd is physical at this point
 	 */
 
-	pg_table_base = (pte_t *) alloc_bootmem_pages(PAGE_SIZE);
-
-	pte = __mk_pte(__pa(&hpux_gateway_page), PAGE_GATEWAY);
-	pg_table = pg_table_base +
-		((hpux_gateway_page_addr & (PAGE_MASK) & (PMD_SIZE - 1)) >>
-								PAGE_SHIFT);
-
-	set_pte(pg_table,pte);
-
+	if (!pmd) {
+		pmd = (pmd_t *) get_zeroed_page(GFP_KERNEL);
+		pmd = (pmd_t *) __pa(pmd);
+	}
 
-#if PTRS_PER_PMD == 1
-	pmd_base = (pmd_t *)pg_table_base;
-#else
-	pmd_base = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE);
-	pmd = pmd_base +
-		((hpux_gateway_page_addr & (PMD_MASK) & (PGDIR_SIZE - 1)) >>
-								PMD_SHIFT);
-	pmd_val(*pmd) = _PAGE_TABLE | __pa(pg_table_base);
+	pgd_val(*pg_dir) = _PAGE_TABLE | (unsigned long) pmd;
 #endif
+	/* now change pmd to kernel virtual addresses */
 
-	gateway_pgd_entry = _PAGE_TABLE | __pa(pmd_base);
+	pmd = (pmd_t *)__va(pmd) + start_pmd;
 
 	/*
-	 * We will be aliasing the HP-UX gateway page into all HP-UX
-	 * user spaces at the same address (not counting the space register
-	 * value) that will be equivalently mapped as long as space register
-	 * hashing is disabled. It will be a problem if anyone touches
-	 * the gateway pages at its "kernel" address, since that is
-	 * NOT equivalently mapped. We'll flush the caches at this
-	 * point, just in case some code has touched those addresses
-	 * previous to this, but all bets are off if they get touched
-	 * after this point.
+	 * pg_table is physical at this point
 	 */
 
-	flush_all_caches();
+	pg_table = (pte_t *) (PAGE_MASK & pmd_val(*pmd));
+	if (!pg_table)
+		pg_table = (pte_t *) __pa(get_zeroed_page(GFP_KERNEL));
 
-	return;
+	pmd_val(*pmd) = _PAGE_TABLE | (unsigned long) pg_table;
+
+	/* now change pg_table to kernel virtual addresses */
+
+	pg_table = (pte_t *) __va(pg_table) + start_pte;
+	set_pte(pg_table, __mk_pte(address, PAGE_GATEWAY));
 }
 
+extern void flush_tlb_all_local(void);
+
 void __init paging_init(void)
 {
+	int i;
+
+	setup_bootmem();
 	pagetable_init();
 	gateway_init();
+	flush_cache_all_local(); /* start with known state */
+	flush_tlb_all_local();
 
-	{
-		unsigned long zones_size[MAX_NR_ZONES] = { max_pfn/2, max_pfn/2, };
+	for (i = 0; i < npmem_ranges; i++) {
+		unsigned long zones_size[MAX_NR_ZONES] = { 0, 0, 0, };
 
-		free_area_init(zones_size);
+		zones_size[ZONE_DMA] = pmem_ranges[i].pages;
+		free_area_init_node(i,NODE_DATA(i),NULL,zones_size,
+				(pmem_ranges[i].start_pfn << PAGE_SHIFT),0);
 	}
+
+#ifdef CONFIG_DISCONTIGMEM
+	/*
+	 * Initialize support for virt_to_page() macro.
+	 *
+	 * Note that MAX_ADDRESS is the largest virtual address that
+	 * we can map. However, since we map all physical memory into
+	 * the kernel address space, it also has an effect on the maximum
+	 * physical address we can map (MAX_ADDRESS - PAGE_OFFSET).
+	 */
+
+	maxchunkmap = MAX_ADDRESS >> CHUNKSHIFT;
+	chunkmap = (unsigned char *)alloc_bootmem(maxchunkmap);
+
+	for (i = 0; i < maxchunkmap; i++)
+	    chunkmap[i] = BADCHUNK;
+
+	for (i = 0; i < npmem_ranges; i++) {
+
+		ADJ_NODE_MEM_MAP(i) = NODE_MEM_MAP(i) - pmem_ranges[i].start_pfn;
+		{
+			unsigned long chunk_paddr;
+			unsigned long end_paddr;
+			int chunknum;
+
+			chunk_paddr = (pmem_ranges[i].start_pfn << PAGE_SHIFT);
+			end_paddr = chunk_paddr + (pmem_ranges[i].pages << PAGE_SHIFT);
+			chunk_paddr &= CHUNKMASK;
+
+			chunknum = (int)CHUNKNUM(chunk_paddr);
+			while (chunk_paddr < end_paddr) {
+				if (chunknum >= maxchunkmap)
+					goto badchunkmap1;
+				if (chunkmap[chunknum] != BADCHUNK)
+					goto badchunkmap2;
+				chunkmap[chunknum] = (unsigned char)i;
+				chunk_paddr += CHUNKSZ;
+				chunknum++;
+			}
+		}
+	}
+
+	return;
+
+badchunkmap1:
+	panic("paging_init: Physical address exceeds maximum address space!\n");
+badchunkmap2:
+	panic("paging_init: Collision in chunk map array. CHUNKSZ needs to be smaller\n");
+#endif
 }
 
-#define NR_SPACE_IDS	8192
+#ifdef CONFIG_PA20
 
-static unsigned long space_id[NR_SPACE_IDS / (8 * sizeof(long))];
-static unsigned long space_id_index;
-static unsigned long free_space_ids = NR_SPACE_IDS;
+/*
+ * Currently, all PA20 chips have 18 bit protection id's, which is the
+ * limiting factor (space ids are 32 bits).
+ */
+
+#define NR_SPACE_IDS 262144
+
+#else
 
 /*
- * XXX: We should probably unfold the set_bit / test_bit / clear_bit
- * locking out of these two functions and have a single spinlock on the
- * space_id data structures.
- *
- * Don't bother. This is all going to be significantly changed in the
- * very near future.
+ * Currently we have a one-to-one relationship between space id's and
+ * protection id's. Older parisc chips (PCXS, PCXT, PCXL, PCXL2) only
+ * support 15 bit protection id's, so that is the limiting factor.
+ * PCXT' has 18 bit protection id's, but only 16 bit spaceids, so it's
+ * probably not worth the effort for a special case here.
  */
 
-#define SPACEID_SHIFT (PAGE_SHIFT + (PT_NLEVELS)*(PAGE_SHIFT - PT_NLEVELS) - 32)
+#define NR_SPACE_IDS 32768
+
+#endif  /* !CONFIG_PA20 */
+
+#define RECYCLE_THRESHOLD (NR_SPACE_IDS / 2)
+#define SID_ARRAY_SIZE  (NR_SPACE_IDS / (8 * sizeof(long)))
+
+static unsigned long space_id[SID_ARRAY_SIZE] = { 1 }; /* disallow space 0 */
+static unsigned long dirty_space_id[SID_ARRAY_SIZE];
+static unsigned long space_id_index;
+static unsigned long free_space_ids = NR_SPACE_IDS - 1;
+static unsigned long dirty_space_ids = 0;
+
+static spinlock_t sid_lock = SPIN_LOCK_UNLOCKED;
 
 unsigned long alloc_sid(void)
 {
 	unsigned long index;
 
-	if (free_space_ids == 0)
-		BUG();
+	spin_lock(&sid_lock);
 
-	free_space_ids--;
+	if (free_space_ids == 0) {
+		if (dirty_space_ids != 0) {
+			spin_unlock(&sid_lock);
+			flush_tlb_all(); /* flush_tlb_all() calls recycle_sids() */
+			spin_lock(&sid_lock);
+		}
+		if (free_space_ids == 0)
+			BUG();
+	}
 
-	do {
-		index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
-	} while(test_and_set_bit(index, space_id));
+	free_space_ids--;
 
+	index = find_next_zero_bit(space_id, NR_SPACE_IDS, space_id_index);
+	space_id[index >> SHIFT_PER_LONG] |= (1L << (index & (BITS_PER_LONG - 1)));
 	space_id_index = index;
 
+	spin_unlock(&sid_lock);
+
 	return index << SPACEID_SHIFT;
 }
 
 void free_sid(unsigned long spaceid)
 {
 	unsigned long index = spaceid >> SPACEID_SHIFT;
-	if (index < 0)
-		BUG();
+	unsigned long *dirty_space_offset;
+
+	dirty_space_offset = dirty_space_id + (index >> SHIFT_PER_LONG);
+	index &= (BITS_PER_LONG - 1);
+
+	spin_lock(&sid_lock);
+
+	if (*dirty_space_offset & (1L << index))
+	    BUG(); /* attempt to free space id twice */
+
+	*dirty_space_offset |= (1L << index);
+	dirty_space_ids++;
+
+	spin_unlock(&sid_lock);
+}
+
+
+#ifdef CONFIG_SMP
+static void get_dirty_sids(unsigned long *ndirtyptr,unsigned long *dirty_array)
+{
+	int i;
+
+	/* NOTE: sid_lock must be held upon entry */
+
+	*ndirtyptr = dirty_space_ids;
+	if (dirty_space_ids != 0) {
+	    for (i = 0; i < SID_ARRAY_SIZE; i++) {
+		dirty_array[i] = dirty_space_id[i];
+		dirty_space_id[i] = 0;
+	    }
+	    dirty_space_ids = 0;
+	}
 
-	clear_bit(index, space_id);
+	return;
+}
+
+static void recycle_sids(unsigned long ndirty,unsigned long *dirty_array)
+{
+	int i;
+
+	/* NOTE: sid_lock must be held upon entry */
+
+	if (ndirty != 0) {
+		for (i = 0; i < SID_ARRAY_SIZE; i++) {
+			space_id[i] ^= dirty_array[i];
+		}
+
+		free_space_ids += ndirty;
+		space_id_index = 0;
+	}
+}
+
+#else /* CONFIG_SMP */
+
+static void recycle_sids(void)
+{
+	int i;
+
+	/* NOTE: sid_lock must be held upon entry */
+
+	if (dirty_space_ids != 0) {
+		for (i = 0; i < SID_ARRAY_SIZE; i++) {
+			space_id[i] ^= dirty_space_id[i];
+			dirty_space_id[i] = 0;
+		}
+
+		free_space_ids += dirty_space_ids;
+		dirty_space_ids = 0;
+		space_id_index = 0;
+	}
+}
+#endif
+
+/*
+ * flush_tlb_all() calls recycle_sids(), since whenever the entire tlb is
+ * purged, we can safely reuse the space ids that were released but
+ * not flushed from the tlb.
+ */
+
+#ifdef CONFIG_SMP
 
-	if (space_id_index > index) {
-		space_id_index = index;
+static unsigned long recycle_ndirty;
+static unsigned long recycle_dirty_array[SID_ARRAY_SIZE];
+static unsigned int recycle_inuse = 0;
+
+void flush_tlb_all(void)
+{
+	int do_recycle;
+
+	do_recycle = 0;
+	spin_lock(&sid_lock);
+	if (dirty_space_ids > RECYCLE_THRESHOLD) {
+	    if (recycle_inuse) {
+		BUG();  /* FIXME: Use a semaphore/wait queue here */
+	    }
+	    get_dirty_sids(&recycle_ndirty,recycle_dirty_array);
+	    recycle_inuse++;
+	    do_recycle++;
+	}
+	spin_unlock(&sid_lock);
+	smp_call_function((void (*)(void *))flush_tlb_all_local, NULL, 1, 1);
+	flush_tlb_all_local();
+	if (do_recycle) {
+	    spin_lock(&sid_lock);
+	    recycle_sids(recycle_ndirty,recycle_dirty_array);
+	    recycle_inuse = 0;
+	    spin_unlock(&sid_lock);
 	}
-	free_space_ids++;
 }
+#else
+void flush_tlb_all(void)
+{
+	spin_lock(&sid_lock);
+	flush_tlb_all_local();
+	recycle_sids();
+	spin_unlock(&sid_lock);
+}
+#endif
 
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
 #if 0
+	if (start < end)
+		printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(mem_map + MAP_NR(start));
-		set_page_count(mem_map+MAP_NR(start), 1);
+		ClearPageReserved(virt_to_page(start));
+		set_page_count(virt_to_page(start), 1);
 		free_page(start);
-		totalram_pages++;
+		num_physpages++;
 	}
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 #endif
 }
 #endif
 
 void si_meminfo(struct sysinfo *val)
 {
-	int i;
-
-	i = max_mapnr;
-	val->totalram = totalram_pages;
+	val->totalram = num_physpages;
 	val->sharedram = 0;
 	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
-#if 0
-	while (i-- > 0)  {
-		if (PageReserved(mem_map+i))
-			continue;
-		val->totalram++;
-		if (!atomic_read(&mem_map[i].count))
-			continue;
-		val->sharedram += atomic_read(&mem_map[i].count) - 1;
-	}
-	val->totalram <<= PAGE_SHIFT;
-	val->sharedram <<= PAGE_SHIFT;
-#endif
 	val->totalhigh = 0;
 	val->freehigh = 0;
+	val->mem_unit = PAGE_SIZE;
 	return;
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/ioremap.c linux/arch/parisc/mm/ioremap.c
--- linux.orig/arch/parisc/mm/ioremap.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/mm/ioremap.c	2002-08-12 22:14:11.000000000 +0000
@@ -0,0 +1,177 @@
+/*
+ * arch/parisc/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ * (C) Copyright 2001 Helge Deller <deller@gmx.de>
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+	unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PMD_MASK;
+	end = address + size;
+	if (end > PMD_SIZE)
+		end = PMD_SIZE;
+	if (address >= end)
+		BUG();
+	do {
+		if (!pte_none(*pte)) {
+			printk(KERN_ERR "remap_area_pte: page already exists\n");
+			BUG();
+		}
+		set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT | _PAGE_RW | 
+					_PAGE_DIRTY | _PAGE_ACCESSED | flags)));
+		address += PAGE_SIZE;
+		phys_addr += PAGE_SIZE;
+		pte++;
+	} while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+	unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	if (address >= end)
+		BUG();
+	do {
+		pte_t * pte = pte_alloc(NULL, pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+#if (USE_HPPA_IOREMAP)
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+				 unsigned long size, unsigned long flags)
+{
+	int error;
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	if (address >= end)
+		BUG();
+	spin_lock(&init_mm.page_table_lock);
+	do {
+		pmd_t *pmd;
+		pmd = pmd_alloc(dir, address);
+		error = -ENOMEM;
+		if (!pmd)
+			break;
+		if (remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			break;
+		error = 0;
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (address && (address < end));
+	spin_unlock(&init_mm.page_table_lock);
+	flush_tlb_all();
+	return error;
+}
+#endif /* USE_HPPA_IOREMAP */
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+#if !(USE_HPPA_IOREMAP)
+
+	unsigned long end = phys_addr + size - 1;
+	/* Support EISA addresses */
+	if ((phys_addr >= 0x00080000 && end < 0x000fffff)
+			|| (phys_addr >= 0x00500000 && end < 0x03bfffff)) {
+		phys_addr |= 0xfc000000;
+	}
+
+	return (void *)phys_addr;
+
+#else
+	void * addr;
+	struct vm_struct * area;
+	unsigned long offset, last_addr;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	/*
+	 * Don't allow anybody to remap normal RAM that we're using..
+	 */
+	if (phys_addr < virt_to_phys(high_memory)) {
+		char *t_addr, *t_end;
+		struct page *page;
+
+		t_addr = __va(phys_addr);
+		t_end = t_addr + (size - 1);
+	   
+		for(page = virt_to_page(t_addr); page <= virt_to_page(t_end); page++)
+			if(!PageReserved(page))
+				return NULL;
+	}
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr) - phys_addr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+	addr = area->addr;
+	if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+		vfree(addr);
+		return NULL;
+	}
+	return (void *) (offset + (char *)addr);
+#endif
+}
+
+void iounmap(void *addr)
+{
+#if !(USE_HPPA_IOREMAP)
+	return;
+#else
+	if (addr > high_memory)
+		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
+#endif
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/kmap.c linux/arch/parisc/mm/kmap.c
--- linux.orig/arch/parisc/mm/kmap.c	2001-02-09 19:29:44.000000000 +0000
+++ linux/arch/parisc/mm/kmap.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,143 +0,0 @@
-/*
-** Stolen mostly from arch/parisc/kernel/pci-dma.c
-*/
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/string.h>
-#include <linux/pci.h>
-
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgalloc.h>
-
-#include <asm/io.h>
-#include <asm/page.h>		/* get_order */
-
-#undef flush_cache_all
-#define flush_cache_all flush_all_caches
-
-typedef void (*pte_iterator_t) (pte_t * pte, unsigned long arg);
-
-#if 0
-/* XXX This routine could be used with iterate_page() to replace
- * unmap_uncached_page() and save a little code space but I didn't
- * do that since I'm not certain whether this is the right path. -PB
- */
-static void unmap_cached_pte(pte_t * pte, unsigned long arg)
-{
-	pte_t page = *pte;
-	pte_clear(pte);
-	if (!pte_none(page)) {
-		if (pte_present(page)) {
-			unsigned long map_nr = pte_pagenr(page);
-			if (map_nr < max_mapnr)
-				__free_page(mem_map + map_nr);
-		} else {
-			printk(KERN_CRIT
-			       "Whee.. Swapped out page in kernel page table\n");
-		}
-	}
-}
-#endif
-
-/* These two routines should probably check a few things... */
-static void set_uncached(pte_t * pte, unsigned long arg)
-{
-	pte_val(*pte) |= _PAGE_NO_CACHE;
-}
-
-static void set_cached(pte_t * pte, unsigned long arg)
-{
-	pte_val(*pte) &= ~_PAGE_NO_CACHE;
-}
-
-static inline void iterate_pte(pmd_t * pmd, unsigned long address,
-			       unsigned long size, pte_iterator_t op,
-			       unsigned long arg)
-{
-	pte_t *pte;
-	unsigned long end;
-
-	if (pmd_none(*pmd))
-		return;
-	if (pmd_bad(*pmd)) {
-		pmd_ERROR(*pmd);
-		pmd_clear(pmd);
-		return;
-	}
-	pte = pte_offset(pmd, address);
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		op(pte, arg);
-		address += PAGE_SIZE;
-		pte++;
-	} while (address < end);
-}
-
-static inline void iterate_pmd(pgd_t * dir, unsigned long address,
-			       unsigned long size, pte_iterator_t op,
-			       unsigned long arg)
-{
-	pmd_t *pmd;
-	unsigned long end;
-
-	if (pgd_none(*dir))
-		return;
-	if (pgd_bad(*dir)) {
-		pgd_ERROR(*dir);
-		pgd_clear(dir);
-		return;
-	}
-	pmd = pmd_offset(dir, address);
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	do {
-		iterate_pte(pmd, address, end - address, op, arg);
-		address = (address + PMD_SIZE) & PMD_MASK;
-		pmd++;
-	} while (address < end);
-}
-
-static void iterate_pages(unsigned long address, unsigned long size,
-			  pte_iterator_t op, unsigned long arg)
-{
-	pgd_t *dir;
-	unsigned long end = address + size;
-
-	dir = pgd_offset_k(address);
-	flush_cache_all();
-	do {
-		iterate_pmd(dir, address, end - address, op, arg);
-		address = (address + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	} while (address && (address < end));
-	flush_tlb_all();
-}
-
-void
-kernel_set_cachemode(unsigned long vaddr, unsigned long size, int what)
-{
-	switch (what) {
-	case IOMAP_FULL_CACHING:
-		iterate_pages(vaddr, size, set_cached, 0);
-		flush_tlb_range(&init_mm, vaddr, size);
-		break;
-	case IOMAP_NOCACHE_SER:
-		iterate_pages(vaddr, size, set_uncached, 0);
-		flush_tlb_range(&init_mm, vaddr, size);
-		break;
-	default:
-		printk(KERN_CRIT
-		       "kernel_set_cachemode mode %d not understood\n",
-		       what);
-		break;
-	}
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/pa11.c linux/arch/parisc/mm/pa11.c
--- linux.orig/arch/parisc/mm/pa11.c	2001-09-30 19:26:08.000000000 +0000
+++ linux/arch/parisc/mm/pa11.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,171 +0,0 @@
-/* $Id: pa11.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $
- *
- * pa11.c: PA 1.1 specific mmu/cache code.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/sgialib.h>
-#include <asm/mmu_context.h>
-
-extern unsigned long mips_tlb_entries;
-
-/* page functions */
-void pa11_clear_page(unsigned long page)
-{
-}
-
-static void pa11_copy_page(unsigned long to, unsigned long from)
-{
-}
-
-/* Cache operations. */
-static inline void pa11_flush_cache_all(void) { }
-static void pa11_flush_cache_mm(struct mm_struct *mm) { }
-static void pa11_flush_cache_range(struct mm_struct *mm,
-				    unsigned long start,
-				    unsigned long end)
-{
-}
-
-static void pa11_flush_cache_page(struct vm_area_struct *vma,
-				   unsigned long page)
-{
-}
-
-static void pa11_flush_page_to_ram(unsigned long page)
-{
-}
-
-static void pa11_flush_cache_sigtramp(unsigned long page)
-{
-}
-
-/* TLB operations. */
-static inline void pa11_flush_tlb_all(void)
-{
-	unsigned long flags;
-	int entry;
-
-	save_and_cli(flags);
-/* Here we will need to flush all the TLBs */
-	restore_flags(flags);
-}
-
-static void pa11_flush_tlb_mm(struct mm_struct *mm)
-{
-/* This is what the MIPS does..  Is it the right thing for PA-RISC? */
-	if(mm == current->mm)
-		pa11_flush_tlb_all();
-}
-
-static void pa11_flush_tlb_range(struct mm_struct *mm, unsigned long start,
-				  unsigned long end)
-{
-	if(mm == current->mm)
-		pa11_flush_tlb_all();
-}
-
-static void pa11_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-	if(vma->vm_mm == current->mm)
-		pa11_flush_tlb_all();
-}
-
-static void pa11_load_pgd(unsigned long pg_dir)
-{
-	unsigned long flags;
-    /* We need to do the right thing here */
-}
-
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-static void pa11_pgd_init(unsigned long page)
-{
-	unsigned long dummy1, dummy2;
-
-}
-
-static void pa11_update_mmu_cache(struct vm_area_struct * vma,
-				   unsigned long address, pte_t pte)
-{
-	pa11_flush_tlb_page(vma, address);
-}
-
-static void pa11_show_regs(struct pt_regs * regs)
-{
-	/*
-	 * Saved main processor registers
-	 */
-	printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
-	       (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
-	       (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
-	       (unsigned long) regs->regs[7]);
-	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
-	       (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
-               (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
-	       (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
-	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
-	       (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
-               (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
-	       (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
-	printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
-	       (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
-	       (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
-               (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
-
-	/*
-	 * Saved cp0 registers
-	 */
-	printk("epc  : %08lx    %s\nStatus: %08x\nCause : %08x\n",
-	       (unsigned long) regs->cp0_epc, print_tainted(),
-	       (unsigned int) regs->cp0_status,
-	       (unsigned int) regs->cp0_cause);
-}
-
-static int pa11_user_mode(struct pt_regs *regs)
-{
-       /* Return user mode stuff?? */
-}
-
-__initfunc(void ld_mmu_pa11(void))
-{
-
-    /* Taken directly from the MIPS arch..  Lots of bad things here */
-	clear_page = pa11_clear_page;
-	copy_page = pa11_copy_page;
-
-	flush_cache_all = pa11_flush_cache_all;
-	flush_cache_mm = pa11_flush_cache_mm;
-	flush_cache_range = pa11_flush_cache_range;
-	flush_cache_page = pa11_flush_cache_page;
-	flush_cache_sigtramp = pa11_flush_cache_sigtramp;
-	flush_page_to_ram = pa11_flush_page_to_ram;
-
-	flush_tlb_all = pa11_flush_tlb_all;
-	flush_tlb_mm = pa11_flush_tlb_mm;
-	flush_tlb_range = pa11_flush_tlb_range;
-	flush_tlb_page = pa11_flush_tlb_page;
-	pa11_asid_setup();
-
-	load_pgd = pa11_load_pgd;
-	pgd_init = pa11_pgd_init;
-	update_mmu_cache = pa11_update_mmu_cache;
-
-	show_regs = pa11_show_regs;
-    
-        add_wired_entry = pa11_add_wired_entry;
-
-	user_mode = pa11_user_mode;
-	flush_tlb_all();
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/mm/pa20.c linux/arch/parisc/mm/pa20.c
--- linux.orig/arch/parisc/mm/pa20.c	2001-09-30 19:26:08.000000000 +0000
+++ linux/arch/parisc/mm/pa20.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,171 +0,0 @@
-/* $Id: pa20.c,v 1.1 1999/03/17 01:05:41 pjlahaie Exp $
- *
- * pa20.c: PA 2.0 specific mmu/cache code.
- *
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/sgialib.h>
-#include <asm/mmu_context.h>
-
-extern unsigned long mips_tlb_entries;
-
-/* page functions */
-void pa20_clear_page(unsigned long page)
-{
-}
-
-static void pa20_copy_page(unsigned long to, unsigned long from)
-{
-}
-
-/* Cache operations. */
-static inline void pa20_flush_cache_all(void) { }
-static void pa20_flush_cache_mm(struct mm_struct *mm) { }
-static void pa20_flush_cache_range(struct mm_struct *mm,
-				    unsigned long start,
-				    unsigned long end)
-{
-}
-
-static void pa20_flush_cache_page(struct vm_area_struct *vma,
-				   unsigned long page)
-{
-}
-
-static void pa20_flush_page_to_ram(unsigned long page)
-{
-}
-
-static void pa20_flush_cache_sigtramp(unsigned long page)
-{
-}
-
-/* TLB operations. */
-static inline void pa20_flush_tlb_all(void)
-{
-	unsigned long flags;
-	int entry;
-
-	save_and_cli(flags);
-/* Here we will need to flush all the TLBs */
-	restore_flags(flags);
-}
-
-static void pa20_flush_tlb_mm(struct mm_struct *mm)
-{
-/* This is what the MIPS does..  Is it the right thing for PA-RISC? */
-	if(mm == current->mm)
-		pa20_flush_tlb_all();
-}
-
-static void pa20_flush_tlb_range(struct mm_struct *mm, unsigned long start,
-				  unsigned long end)
-{
-	if(mm == current->mm)
-		pa20_flush_tlb_all();
-}
-
-static void pa20_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
-	if(vma->vm_mm == current->mm)
-		pa20_flush_tlb_all();
-}
-
-static void pa20_load_pgd(unsigned long pg_dir)
-{
-	unsigned long flags;
-    /* We need to do the right thing here */
-}
-
-/*
- * Initialize new page directory with pointers to invalid ptes
- */
-static void pa20_pgd_init(unsigned long page)
-{
-	unsigned long dummy1, dummy2;
-
-}
-
-static void pa20_update_mmu_cache(struct vm_area_struct * vma,
-				   unsigned long address, pte_t pte)
-{
-	pa20_flush_tlb_page(vma, address);
-}
-
-static void pa20_show_regs(struct pt_regs * regs)
-{
-	/*
-	 * Saved main processor registers
-	 */
-	printk("$0 : %08x %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       0, (unsigned long) regs->regs[1], (unsigned long) regs->regs[2],
-	       (unsigned long) regs->regs[3], (unsigned long) regs->regs[4],
-	       (unsigned long) regs->regs[5], (unsigned long) regs->regs[6],
-	       (unsigned long) regs->regs[7]);
-	printk("$8 : %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       (unsigned long) regs->regs[8], (unsigned long) regs->regs[9],
-	       (unsigned long) regs->regs[10], (unsigned long) regs->regs[11],
-               (unsigned long) regs->regs[12], (unsigned long) regs->regs[13],
-	       (unsigned long) regs->regs[14], (unsigned long) regs->regs[15]);
-	printk("$16: %08lx %08lx %08lx %08lx %08lx %08lx %08lx %08lx\n",
-	       (unsigned long) regs->regs[16], (unsigned long) regs->regs[17],
-	       (unsigned long) regs->regs[18], (unsigned long) regs->regs[19],
-               (unsigned long) regs->regs[20], (unsigned long) regs->regs[21],
-	       (unsigned long) regs->regs[22], (unsigned long) regs->regs[23]);
-	printk("$24: %08lx %08lx                   %08lx %08lx %08lx %08lx\n",
-	       (unsigned long) regs->regs[24], (unsigned long) regs->regs[25],
-	       (unsigned long) regs->regs[28], (unsigned long) regs->regs[29],
-               (unsigned long) regs->regs[30], (unsigned long) regs->regs[31]);
-
-	/*
-	 * Saved cp0 registers
-	 */
-	printk("epc  : %08lx    %s\nStatus: %08x\nCause : %08x\n",
-	       (unsigned long) regs->cp0_epc, print_tainted(),
-	       (unsigned int) regs->cp0_status,
-	       (unsigned int) regs->cp0_cause);
-}
-
-static int pa20_user_mode(struct pt_regs *regs)
-{
-       /* Return user mode stuff?? */
-}
-
-__initfunc(void ld_mmu_pa20(void))
-{
-
-    /* Taken directly from the MIPS arch..  Lots of bad things here */
-	clear_page = pa20_clear_page;
-	copy_page = pa20_copy_page;
-
-	flush_cache_all = pa20_flush_cache_all;
-	flush_cache_mm = pa20_flush_cache_mm;
-	flush_cache_range = pa20_flush_cache_range;
-	flush_cache_page = pa20_flush_cache_page;
-	flush_cache_sigtramp = pa20_flush_cache_sigtramp;
-	flush_page_to_ram = pa20_flush_page_to_ram;
-
-	flush_tlb_all = pa20_flush_tlb_all;
-	flush_tlb_mm = pa20_flush_tlb_mm;
-	flush_tlb_range = pa20_flush_tlb_range;
-	flush_tlb_page = pa20_flush_tlb_page;
-	pa20_asid_setup();
-
-	load_pgd = pa20_load_pgd;
-	pgd_init = pa20_pgd_init;
-	update_mmu_cache = pa20_update_mmu_cache;
-
-	show_regs = pa20_show_regs;
-    
-        add_wired_entry = pa20_add_wired_entry;
-
-	user_mode = pa20_user_mode;
-	flush_tlb_all();
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/tools/Makefile linux/arch/parisc/tools/Makefile
--- linux.orig/arch/parisc/tools/Makefile	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/tools/Makefile	2002-08-12 22:14:26.000000000 +0000
@@ -22,7 +22,4 @@
 
 offset.s: offset.c
 
-clean:
-	rm -f offset.[hs] $(TARGET).new
-
 include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/tools/offset.c linux/arch/parisc/tools/offset.c
--- linux.orig/arch/parisc/tools/offset.c	2000-12-05 20:29:39.000000000 +0000
+++ linux/arch/parisc/tools/offset.c	2002-08-12 22:14:00.000000000 +0000
@@ -13,6 +13,13 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/hardirq.h>
+#include <asm/pdc.h>
+
+#ifdef __LP64__
+#define FRAME_SIZE	128
+#else
+#define FRAME_SIZE	64
+#endif
 
 #define text(t) __asm__("\n@@@" t)
 #define _offset(type, member) (&(((type *)NULL)->member))
@@ -21,7 +28,7 @@
 	__asm__("\n@@@" string "%0" : : "i" (_offset(ptr, member)))
 #define size(string, size) \
 	__asm__("\n@@@" string "%0" : : "i" (sizeof(size)))
-#define align(x,y) (((x)+(2*(y))-1)-(((x)+(y)-1)%(y)))
+#define align(x,y) (((x)+FRAME_SIZE+(y)-1)-(((x)+(y)-1)%(y)))
 #define size_align(string, size, algn) \
 	__asm__("\n@@@" string "%0" : : "i" \
 		align(sizeof(size),algn))
@@ -32,6 +39,15 @@
 text("#ifndef _PARISC_OFFSET_H");
 text("#define _PARISC_OFFSET_H");
 linefeed;
+#ifdef __LP64__
+text("#ifndef __LP64__");
+text("#error offset.h was generated for 64-bit build; did you do 'make dep'?");
+#else
+text("#ifdef __LP64__");
+text("#error offset.h was generated for 32-bit build; did you do 'make dep'?");
+#endif
+text("#endif");
+linefeed;
 
 void output_task_ptreg_defines(void)
 {
@@ -113,23 +129,14 @@
 	offset("#define TASK_PT_IASQ1   ", struct task_struct, thread.regs.iasq[1]);
 	offset("#define TASK_PT_IAOQ0   ", struct task_struct, thread.regs.iaoq[0]);
 	offset("#define TASK_PT_IAOQ1   ", struct task_struct, thread.regs.iaoq[1]);
-	offset("#define TASK_PT_CR24    ", struct task_struct, thread.regs.cr24);
-	offset("#define TASK_PT_CR25    ", struct task_struct, thread.regs.cr25);
-	offset("#define TASK_PT_CR26    ", struct task_struct, thread.regs.cr26);
 	offset("#define TASK_PT_CR27    ", struct task_struct, thread.regs.cr27);
-	offset("#define TASK_PT_CR30    ", struct task_struct, thread.regs.cr30);
 	offset("#define TASK_PT_ORIG_R28 ", struct task_struct, thread.regs.orig_r28);
 	offset("#define TASK_PT_KSP     ", struct task_struct, thread.regs.ksp);
 	offset("#define TASK_PT_KPC     ", struct task_struct, thread.regs.kpc);
 	offset("#define TASK_PT_SAR     ", struct task_struct, thread.regs.sar);
-	offset("#define TASK_PT_CR11    ", struct task_struct, thread.regs.sar);
 	offset("#define TASK_PT_IIR     ", struct task_struct, thread.regs.iir);
 	offset("#define TASK_PT_ISR     ", struct task_struct, thread.regs.isr);
 	offset("#define TASK_PT_IOR     ", struct task_struct, thread.regs.ior);
-	offset("#define TASK_PT_CR_PID0 ", struct task_struct, thread.regs.cr_pid[0]);
-	offset("#define TASK_PT_CR_PID1 ", struct task_struct, thread.regs.cr_pid[1]);
-	offset("#define TASK_PT_CR_PID2 ", struct task_struct, thread.regs.cr_pid[2]);
-	offset("#define TASK_PT_CR_PID3 ", struct task_struct, thread.regs.cr_pid[3]);
 	size("#define TASK_SZ      ", struct task_struct);
 	size_align("#define TASK_SZ_ALGN  ", struct task_struct, 64);
 	linefeed;
@@ -214,23 +221,14 @@
 	offset("#define PT_IASQ1   ", struct pt_regs, iasq[1]);
 	offset("#define PT_IAOQ0   ", struct pt_regs, iaoq[0]);
 	offset("#define PT_IAOQ1   ", struct pt_regs, iaoq[1]);
-	offset("#define PT_CR24    ", struct pt_regs, cr24);
-	offset("#define PT_CR25    ", struct pt_regs, cr25);
-	offset("#define PT_CR26    ", struct pt_regs, cr26);
 	offset("#define PT_CR27    ", struct pt_regs, cr27);
-	offset("#define PT_CR30    ", struct pt_regs, cr30);
 	offset("#define PT_ORIG_R28 ", struct pt_regs, orig_r28);
 	offset("#define PT_KSP     ", struct pt_regs, ksp);
 	offset("#define PT_KPC     ", struct pt_regs, kpc);
 	offset("#define PT_SAR     ", struct pt_regs, sar);
-	offset("#define PT_CR11    ", struct pt_regs, sar);
 	offset("#define PT_IIR     ", struct pt_regs, iir);
 	offset("#define PT_ISR     ", struct pt_regs, isr);
 	offset("#define PT_IOR     ", struct pt_regs, ior);
-	offset("#define PT_CR_PID0 ", struct pt_regs, cr_pid[0]);
-	offset("#define PT_CR_PID1 ", struct pt_regs, cr_pid[1]);
-	offset("#define PT_CR_PID2 ", struct pt_regs, cr_pid[2]);
-	offset("#define PT_CR_PID3 ", struct pt_regs, cr_pid[3]);
 	size("#define PT_SIZE    ", struct pt_regs);
 	size_align("#define PT_SZ_ALGN  ", struct pt_regs, 64);
 	linefeed;
@@ -249,6 +247,7 @@
 	offset("#define TASK_NICE          ", struct task_struct, nice);
 	offset("#define TASK_MM            ", struct task_struct, mm);
 	offset("#define TASK_PROCESSOR     ", struct task_struct, processor);
+	offset("#define TASK_PERSONALITY   ", struct task_struct, personality);
 	size  ("#define TASK_SZ          ", struct task_struct);
 	size_align("#define TASK_SZ_ALGN       ", struct task_struct, 64);
 	linefeed;
@@ -257,12 +256,39 @@
 void output_irq_stat_defines(void)
 {
 	text("/* PARISC irq_cpustat_t offsets. */");
-	offset("#define IRQSTAT_SI_ACTIVE  ", irq_cpustat_t, __softirq_active);
-	offset("#define IRQSTAT_SI_MASK    ", irq_cpustat_t, __softirq_mask);
+	offset("#define IRQSTAT_SIRQ_PEND  ", irq_cpustat_t, __softirq_pending);
 	size  ("#define IRQSTAT_SZ         ", irq_cpustat_t);
 	linefeed;
 }
 
+void output_cache_info_defines(void)
+{
+	text("/* PARISC pdc_cache_info offsets. */");
+	offset("#define ICACHE_BASE      ", struct pdc_cache_info, ic_base);
+	offset("#define ICACHE_STRIDE    ", struct pdc_cache_info, ic_stride);
+	offset("#define ICACHE_COUNT     ", struct pdc_cache_info, ic_count);
+	offset("#define ICACHE_LOOP      ", struct pdc_cache_info, ic_loop);
+	offset("#define DCACHE_BASE      ", struct pdc_cache_info, dc_base);
+	offset("#define DCACHE_STRIDE    ", struct pdc_cache_info, dc_stride);
+	offset("#define DCACHE_COUNT     ", struct pdc_cache_info, dc_count);
+	offset("#define DCACHE_LOOP      ", struct pdc_cache_info, dc_loop);
+	offset("#define ITLB_SID_BASE    ", struct pdc_cache_info, it_sp_base);
+	offset("#define ITLB_SID_STRIDE  ", struct pdc_cache_info, it_sp_stride);
+	offset("#define ITLB_SID_COUNT   ", struct pdc_cache_info, it_sp_count);
+	offset("#define ITLB_OFF_BASE    ", struct pdc_cache_info, it_off_base);
+	offset("#define ITLB_OFF_STRIDE  ", struct pdc_cache_info, it_off_stride);
+	offset("#define ITLB_OFF_COUNT   ", struct pdc_cache_info, it_off_count);
+	offset("#define ITLB_LOOP        ", struct pdc_cache_info, it_loop);
+	offset("#define DTLB_SID_BASE    ", struct pdc_cache_info, dt_sp_base);
+	offset("#define DTLB_SID_STRIDE  ", struct pdc_cache_info, dt_sp_stride);
+	offset("#define DTLB_SID_COUNT   ", struct pdc_cache_info, dt_sp_count);
+	offset("#define DTLB_OFF_BASE    ", struct pdc_cache_info, dt_off_base);
+	offset("#define DTLB_OFF_STRIDE  ", struct pdc_cache_info, dt_off_stride);
+	offset("#define DTLB_OFF_COUNT   ", struct pdc_cache_info, dt_off_count);
+	offset("#define DTLB_LOOP        ", struct pdc_cache_info, dt_loop);
+	linefeed;
+}
+
 #ifdef PRUMPF_HAD_MORE_TIME
 void output_thread_defines(void)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/vmlinux.lds linux/arch/parisc/vmlinux.lds
--- linux.orig/arch/parisc/vmlinux.lds	2001-07-02 21:40:58.000000000 +0000
+++ linux/arch/parisc/vmlinux.lds	2002-08-12 22:14:08.000000000 +0000
@@ -1,21 +1,14 @@
 /* ld script to make hppa Linux kernel */
-OUTPUT_FORMAT("elf32-hppa")
 OUTPUT_ARCH(hppa)
 ENTRY(_stext)
 SECTIONS
 {
 
-/* right now use 0x10000/0x11000, later when we don't use Console and
- * Boot-Device IODC, we will change this to 0x8000 !!!
- */
-
-  . = 0xc0100000;   
-/*	. = 0x10000;  */
+  . = 0x10100000;
 
   _text = .;			/* Text and read-only data */
   .text BLOCK(16) : {
 	*(.text*)
-	*(.PARISC.unwind)
 	*(.fixup)
 	*(.lock.text)		/* out-of-line lock text */
 	*(.gnu.warning)
@@ -57,12 +50,14 @@
 
 
   init_task BLOCK(16384) : { *(init_task) }  /* The initial task and kernel stack */
+  init_istack BLOCK(32768) : { *(init_istack) }  /* The initial interrupt stack */
 
   _edata = .;			/* End of data section */
 
 
   .bss : { *(.bss) *(COMMON) }		/* BSS */
 
+  .PARISC.unwind : { *(.PARISC.unwind) }
 
   _end = . ;
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/parisc/vmlinux64.lds linux/arch/parisc/vmlinux64.lds
--- linux.orig/arch/parisc/vmlinux64.lds	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/parisc/vmlinux64.lds	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,76 @@
+/* ld script to make hppa Linux kernel */
+OUTPUT_ARCH(hppa:hppa2.0w)
+ENTRY(_stext)
+SECTIONS
+{
+
+  . = 0x10100000;
+
+  _text = .;			/* Text and read-only data */
+  .text BLOCK(16) : {
+	*(.text*)
+	*(.PARISC.unwind)
+	*(.fixup)
+	*(.lock.text)		/* out-of-line lock text */
+	*(.gnu.warning)
+	} = 0
+
+  . = ALIGN(16);
+  .rodata : { *(.rodata) }
+  .kstrtab : { *(.kstrtab) }
+
+  _etext = .;			/* End of text section */
+  
+  .data BLOCK(8192) : {			/* Data without special */
+	data_start = .;
+	*(.data)
+	}
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  . = ALIGN(16);		/* Linkage tables */
+  .opd : { *(.opd) } PROVIDE (__gp = .); .plt : { *(.plt) } .dlt : { *(.dlt) }
+
+  . = ALIGN(16384);
+  __init_begin = .;
+  .init.text : { *(.init.text) }
+  .init.data : { *(.init.data) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) } 
+  __initcall_end = .;
+  __init_end = .;
+
+
+  init_task BLOCK(16384) : { *(init_task) }  /* The initial task and kernel stack */
+  init_istack BLOCK(32768) : { *(init_task) }  /* The initial interrupt stack */
+
+  _edata = .;			/* End of data section */
+
+
+  .bss : { *(.bss) *(COMMON) }		/* BSS */
+
+
+  _end = . ;
+
+  /* Stabs debugging sections.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  .stab.excl 0 : { *(.stab.excl) }
+  .stab.exclstr 0 : { *(.stab.exclstr) }
+  .stab.index 0 : { *(.stab.index) }
+  .stab.indexstr 0 : { *(.stab.indexstr) }
+  .comment 0 : { *(.comment) }
+  .note 0 : { *(.note) }	
+	
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/Makefile linux/arch/ppc/Makefile
--- linux.orig/arch/ppc/Makefile	2001-10-11 16:04:57.000000000 +0000
+++ linux/arch/ppc/Makefile	2002-08-12 22:14:02.000000000 +0000
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.23 09/18/01 11:19:05 paulus
+# BK Id: %F% %I% %G% %U% %#%
 #
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
@@ -21,16 +21,17 @@
 CHECKS		= checks
 endif
 
-ASFLAGS		=
 LINKFLAGS	= -T arch/ppc/vmlinux.lds -Ttext $(KERNELLOAD) -Bstatic
-CPPFLAGS	:= $(CPPFLAGS) -D__powerpc__
-CFLAGS		:= $(CFLAGS) -D__powerpc__ -fsigned-char \
+CPPFLAGS	:= $(CPPFLAGS) -I$(TOPDIR)/arch/$(ARCH)
+AFLAGS		:= $(AFLAGS) -I$(TOPDIR)/arch/$(ARCH)
+CFLAGS		:= $(CFLAGS) -I$(TOPDIR)/arch/$(ARCH) -fsigned-char \
 		-msoft-float -pipe -ffixed-r2 -Wno-uninitialized \
 		-mmultiple -mstring
+HOSTCFLAGS	+= -I$(TOPDIR)/arch/$(ARCH)
 CPP		= $(CC) -E $(CFLAGS)
 
 ifdef CONFIG_4xx
-CFLAGS := $(CFLAGS) -mcpu=403
+CFLAGS := $(CFLAGS) -Wa,-m405
 endif
 
 ifdef CONFIG_8xx
@@ -51,9 +52,10 @@
   endif
 endif
 
-ARCH_SUBDIRS = arch/ppc/kernel arch/ppc/mm arch/ppc/lib
+ARCH_SUBDIRS = arch/ppc/kernel arch/ppc/platforms arch/ppc/mm arch/ppc/lib
 SUBDIRS := $(SUBDIRS) $(ARCH_SUBDIRS)
-CORE_FILES := arch/ppc/kernel/kernel.o arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(CORE_FILES)
+CORE_FILES := arch/ppc/kernel/kernel.o arch/ppc/platforms/platform.o \
+	arch/ppc/mm/mm.o arch/ppc/lib/lib.o $(CORE_FILES)
 
 ifdef CONFIG_MATH_EMULATION
 SUBDIRS += arch/ppc/math-emu
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/boot/common/crt0.S linux/arch/ppc/boot/common/crt0.S
--- linux.orig/arch/ppc/boot/common/crt0.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/boot/common/crt0.S	2002-08-12 22:14:24.000000000 +0000
@@ -22,7 +22,7 @@
  */
 
 #include <linux/config.h>
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 
 	.text
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/boot/common/relocate.S linux/arch/ppc/boot/common/relocate.S
--- linux.orig/arch/ppc/boot/common/relocate.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/boot/common/relocate.S	2002-08-12 22:14:24.000000000 +0000
@@ -20,7 +20,7 @@
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 
 #define GETSYM(reg, sym)	\
 	lis	reg, sym@h; ori	reg, reg, sym@l	
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/boot/common/util.S linux/arch/ppc/boot/common/util.S
--- linux.orig/arch/ppc/boot/common/util.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/boot/common/util.S	2002-08-12 22:14:05.000000000 +0000
@@ -24,7 +24,7 @@
 
 #include <asm/processor.h>
 #include <asm/cache.h>
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 
 
 	.text
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/boot/prep/head.S linux/arch/ppc/boot/prep/head.S
--- linux.orig/arch/ppc/boot/prep/head.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/boot/prep/head.S	2002-08-12 22:14:06.000000000 +0000
@@ -2,7 +2,7 @@
  * BK Id: SCCS/s.head.S 1.13 01/11/02 10:46:07 trini
  */
 
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/boot/simple/head.S linux/arch/ppc/boot/simple/head.S
--- linux.orig/arch/ppc/boot/simple/head.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/boot/simple/head.S	2002-08-12 22:14:13.000000000 +0000
@@ -18,7 +18,7 @@
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 
 	.text
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/boot/simple/legacy.S linux/arch/ppc/boot/simple/legacy.S
--- linux.orig/arch/ppc/boot/simple/legacy.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/boot/simple/legacy.S	2002-08-12 22:14:09.000000000 +0000
@@ -6,7 +6,7 @@
  * This will go and setup ISA_io to 0x8000000 and return.
  */
 
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 
 	.text
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/config.in linux/arch/ppc/config.in
--- linux.orig/arch/ppc/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/config.in	2002-08-12 22:13:59.000000000 +0000
@@ -395,6 +395,8 @@
 
 source net/bluetooth/Config.in
 
+source lib/Config.in
+
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- linux.orig/arch/ppc/kernel/Makefile	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/Makefile	2002-08-12 22:14:14.000000000 +0000
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.41 04/16/02 20:08:22 paulus
+# BK Id: %F% %I% %G% %U% %#%
 #
 #
 # Makefile for the linux kernel.
@@ -14,9 +14,9 @@
 ifdef CONFIG_PPC64BRIDGE
 EXTRA_AFLAGS		:= -Wa,-mppc64bridge
 endif
-
-# Extra CFLAGS so we don't have to do relative includes
-CFLAGS_pmac_setup.o	+= -I$(TOPDIR)/arch/$(ARCH)/mm -I$(TOPDIR)/drivers/scsi
+ifdef CONFIG_4xx
+EXTRA_AFLAGS		:= -Wa,-m405
+endif
 
 # Code in these files is used before the kernel is moved to its final position
 CFLAGS_prom_init.o	+= -mrelocatable-lib
@@ -31,7 +31,7 @@
 
 O_TARGET := kernel.o
 
-export-objs			:= ppc_ksyms.o prep_setup.o time.o
+export-objs			:= ppc_ksyms.o time.o
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
 					process.o signal.o ptrace.o align.o \
@@ -39,17 +39,12 @@
 					cputable.o ppc_htab.o
 obj-$(CONFIG_6xx)		+= l2cr.o
 obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
-obj-$(CONFIG_POWER4)		+= xics.o
-obj-$(CONFIG_PCI)		+= pci.o pci-dma.o
+obj-$(CONFIG_PCI)		+= pci.o 
+obj-$(CONFIG_PCI)		+= pci-dma.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_4xx)		+= ppc4xx_pic.o
-obj-$(CONFIG_OAK)		+= oak_setup.o
-obj-$(CONFIG_WALNUT)		+= walnut_setup.o
 obj-$(CONFIG_TAU)		+= temp.o
-ifeq ($(CONFIG_WALNUT),y)
-obj-$(CONFIG_PCI)		+= galaxy_pci.o
-endif
+obj-$(CONFIG_4xx)		+= ppc4xx_pic.o
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
 ifeq ($(CONFIG_8xx),y)
 obj-$(CONFIG_PCI)		+= qspan_pci.o
@@ -58,30 +53,12 @@
 endif
 endif
 obj-$(CONFIG_MBX)		+= i8259.o
-obj-$(CONFIG_APUS)		+= apus_setup.o
-ifeq ($(CONFIG_APUS),y)
-obj-$(CONFIG_PCI)		+= apus_pci.o
-endif
-obj-$(CONFIG_ALL_PPC)		+= pmac_pic.o pmac_setup.o pmac_time.o prom.o \
-					prom_init.o pmac_feature.o pmac_pci.o \
-					chrp_setup.o chrp_time.o chrp_pci.o \
-					open_pic.o indirect_pci.o i8259.o \
-					prep_pci.o prep_time.o prep_nvram.o \
-					prep_setup.o
-obj-$(CONFIG_NVRAM)		+= pmac_nvram.o
-obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
-obj-$(CONFIG_PMAC_PBOOK)	+= sleep.o
-obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
-obj-$(CONFIG_PPC_RTAS)		+= error_log.o proc_rtas.o
-obj-$(CONFIG_GEMINI)		+= gemini_prom.o gemini_pci.o gemini_setup.o \
-					open_pic.o
+obj-$(CONFIG_ALL_PPC)		+= prom_init.o prom.o open_pic.o \
+					indirect_pci.o i8259.o prep_nvram.o
+obj-$(CONFIG_GEMINI)		+= open_pic.o
 obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
 obj-$(CONFIG_BOOTX_TEXT)	+= btext.o
 
-ifeq ($(CONFIG_SMP),y)
-obj-$(CONFIG_ALL_PPC)		+= pmac_smp.o chrp_smp.o
-endif
-
 include $(TOPDIR)/Rules.make
 
 entry.o: entry.S ppc_defs.h
@@ -90,7 +67,6 @@
 head.o: head.S ppc_defs.h
 head_4xx.o: head_4xx.S ppc_defs.h
 head_8xx.o: head_8xx.S ppc_defs.h
-gemini_prom.o: gemini_prom.S ppc_defs.h
 
 ppc_defs.h: mk_defs.c ppc_defs.head \
 		$(TOPDIR)/include/asm/mmu.h \
@@ -110,4 +86,3 @@
 checks: checks.c
 	$(HOSTCC) -I$(HPATH) $(HOSTCFLAGS) -D__KERNEL__ -fno-builtin -o checks checks.c
 	./checks
-
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/apus_pci.c linux/arch/ppc/kernel/apus_pci.c
--- linux.orig/arch/ppc/kernel/apus_pci.c	2001-09-08 19:38:41.000000000 +0000
+++ linux/arch/ppc/kernel/apus_pci.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,187 +0,0 @@
-/*
- * BK Id: SCCS/s.apus_pci.c 1.5 09/08/01 15:47:42 paulus
- */
-/*
- * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
- *
- * APUS PCI routines.
- *
- * Currently, only B/CVisionPPC cards (Permedia2) are supported.
- *
- * Thanks to Geert Uytterhoeven for the idea:
- * Read values from given config space(s) for the first devices, -1 otherwise
- *
- */
-
-#include <linux/config.h>
-#ifdef CONFIG_AMIGA
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-
-#include "apus_pci.h"
-
-
-/* These definitions are mostly adapted from pm2fb.c */
-
-#undef APUS_PCI_MASTER_DEBUG
-#ifdef APUS_PCI_MASTER_DEBUG
-#define DPRINTK(a,b...)	printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b)
-#else
-#define DPRINTK(a,b...)
-#endif 
-
-/*
- * The _DEFINITIVE_ memory mapping/unmapping functions.
- * This is due to the fact that they're changing soooo often...
- */
-#define DEFW()		wmb()
-#define DEFR()		rmb()
-#define DEFRW()		mb()
-
-#define DEVNO(d)	((d)>>3)
-#define FNNO(d)		((d)&7)
-
-
-extern unsigned long powerup_PCI_present;
-
-static struct pci_controller *apus_hose;
-
-
-void *pci_io_base(unsigned int bus)
-{
-	return 0;
-}
-
-
-#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op)	op((val), (type *)(addr)); DEFW()
-#define cfg_read_bad	*val = ~0;
-#define cfg_write_bad	;
-#define cfg_read_val(val)	*val
-#define cfg_write_val(val)	val
-
-#define APUS_PCI_OP(rw, size, type, op, mask)					\
-int									\
-apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
-{										\
-	int fnno = FNNO(dev->devfn);						\
-	int devno = DEVNO(dev->devfn);						\
-										\
-	if (dev->bus->number > 0 || devno != 1) {				\
-		cfg_##rw##_bad;							\
-		return PCIBIOS_DEVICE_NOT_FOUND;				\
-	}									\
-	/* base address + function offset + offset ^ endianness conversion */	\
-	cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask),	\
-		 type, op);							\
-										\
-	DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n",		\
-		dev->bus->number, dev->devfn>>3, dev->devfn&7,			\
-		offset, cfg_##rw##_val(val));					\
-	return PCIBIOS_SUCCESSFUL;						\
-}
-
-APUS_PCI_OP(read, byte, u8 *, readb, 3)
-APUS_PCI_OP(read, word, u16 *, readw, 2)
-APUS_PCI_OP(read, dword, u32 *, readl, 0)
-APUS_PCI_OP(write, byte, u8, writeb, 3)
-APUS_PCI_OP(write, word, u16, writew, 2)
-APUS_PCI_OP(write, dword, u32, writel, 0)
-
-
-static struct pci_ops apus_pci_ops = {
-	apus_pcibios_read_config_byte,
-	apus_pcibios_read_config_word,
-	apus_pcibios_read_config_dword,
-	apus_pcibios_write_config_byte,
-	apus_pcibios_write_config_word,
-	apus_pcibios_write_config_dword
-};
-
-static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
-
-void __init
-apus_pcibios_fixup(void)
-{
-/*	struct pci_dev *dev = pci_find_slot(0, 1<<3);
-	unsigned int reg, val, offset;*/
-
-	/* FIXME: interrupt? */
-	/*dev->interrupt = xxx;*/
-
-        request_resource(&iomem_resource, &pci_mem);
-    	printk("%s: PCI mem resource requested\n", __FUNCTION__);
-}
-
-static void __init apus_pcibios_fixup_bus(struct pci_bus *bus)
-{
-        bus->resource[1] = &pci_mem;
-}
-
-
-/* 
- * This is from pm2fb.c again
- * 
- * Check if PCI (B/CVisionPPC) is available, initialize it and set up
- * the pcibios_* pointers
- */
-
-
-void __init
-apus_setup_pci_ptrs(void)
-{
-	if (!powerup_PCI_present) {
-		DPRINTK("no PCI bridge detected\n");
-		return;
-	}
-	DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n");
-
-	apus_hose = pcibios_alloc_controller();
-	if (!apus_hose) {
-		printk("apus_pci: Can't allocate PCI controller structure\n");
-		return;
-	}
-
-	if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) {
-		printk("apus_pci: unable to map PCI config region\n");
-		return;
-	}
-
-	if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) {
-		printk("apus_pci: unable to map PCI bridge\n");
-		return;
-	}
-
-	writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN);
-	DEFW();
-
-	writel(CVPPC_REGS_REGION,  apus_hose->cfg_data+ PCI_BASE_ADDRESS_0);
-	DEFW();
-	writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1);
-	DEFW();
-	writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2);
-	DEFW();
-	writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS);
-	DEFW();
-
-	writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
-		PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND);
-	DEFW();
-
-	apus_hose->first_busno = 0;
-	apus_hose->last_busno = 0;
-	apus_hose->ops = &apus_pci_ops;
-	ppc_md.pcibios_fixup = apus_pcibios_fixup;
-	ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus;
-
-	return;
-}
-
-#endif /* CONFIG_AMIGA */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/apus_pci.h linux/arch/ppc/kernel/apus_pci.h
--- linux.orig/arch/ppc/kernel/apus_pci.h	2001-05-22 00:04:46.000000000 +0000
+++ linux/arch/ppc/kernel/apus_pci.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,40 +0,0 @@
-/*
- * BK Id: SCCS/s.apus_pci.h 1.4 05/17/01 18:14:21 cort
- */
-/*
- * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
- * driver.
- *
- * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
- * --------------------------------------------------------------------------
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- */
-
-#ifndef APUS_PCI_H
-#define APUS_PCI_H
-
-
-#include "pci.h"
-
-
-#define CSPPC_PCI_BRIDGE		0xfffe0000
-#define CSPPC_BRIDGE_ENDIAN		0x0000
-#define CSPPC_BRIDGE_INT		0x0010
-
-#define	CVPPC_PCI_CONFIG		0xfffc0000
-#define CVPPC_ROM_ADDRESS		0xe2000001
-#define CVPPC_REGS_REGION		0xef000000
-#define CVPPC_FB_APERTURE_ONE		0xe0000000
-#define CVPPC_FB_APERTURE_TWO		0xe1000000
-#define CVPPC_FB_SIZE			0x00800000
-
-/* CVPPC_BRIDGE_ENDIAN */
-#define CSPPCF_BRIDGE_BIG_ENDIAN	0x02
-
-/* CVPPC_BRIDGE_INT */
-#define CSPPCF_BRIDGE_ACTIVE_INT2	0x01
-
-
-#endif	/* APUS_PCI_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- linux.orig/arch/ppc/kernel/apus_setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/apus_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,1113 +0,0 @@
-/*
- * BK Id: SCCS/s.apus_setup.c 1.24 11/13/01 21:26:07 paulus
- */
-/*
- *  linux/arch/ppc/kernel/apus_setup.c
- *
- *  Copyright (C) 1998, 1999  Jesper Skov
- *
- *  Basically what is needed to replace functionality found in
- *  arch/m68k allowing Amiga drivers to work under APUS.
- *  Bits of code and/or ideas from arch/m68k and arch/ppc files.
- *
- * TODO:
- *  This file needs a *really* good cleanup. Restructure and optimize.
- *  Make sure it can be compiled for non-APUS configs. Begin to move
- *  Amiga specific stuff into mach/amiga.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/kd.h>
-#include <linux/init.h>
-#include <linux/hdreg.h>
-#include <linux/blk.h>
-#include <linux/pci.h>
-#include <linux/seq_file.h>
-
-#ifdef CONFIG_APUS
-#include <asm/logging.h>
-#endif
-
-/* Needs INITSERIAL call in head.S! */
-#undef APUS_DEBUG
-
-
-#include <linux/ide.h>
-#define T_CHAR          (0x0000)        /* char:  don't touch  */
-#define T_SHORT         (0x4000)        /* short: 12 -> 21     */
-#define T_INT           (0x8000)        /* int:   1234 -> 4321 */
-#define T_TEXT          (0xc000)        /* text:  12 -> 21     */
-
-#define T_MASK_TYPE     (0xc000)
-#define T_MASK_COUNT    (0x3fff)
-
-#define D_CHAR(cnt)     (T_CHAR  | (cnt))
-#define D_SHORT(cnt)    (T_SHORT | (cnt))
-#define D_INT(cnt)      (T_INT   | (cnt))
-#define D_TEXT(cnt)     (T_TEXT  | (cnt))
-
-static u_short driveid_types[] = {
-        D_SHORT(10),    /* config - vendor2 */
-        D_TEXT(20),     /* serial_no */
-        D_SHORT(3),     /* buf_type, buf_size - ecc_bytes */
-        D_TEXT(48),     /* fw_rev - model */
-        D_CHAR(2),      /* max_multsect - vendor3 */
-        D_SHORT(1),     /* dword_io */
-        D_CHAR(2),      /* vendor4 - capability */
-        D_SHORT(1),     /* reserved50 */
-        D_CHAR(4),      /* vendor5 - tDMA */
-        D_SHORT(4),     /* field_valid - cur_sectors */
-        D_INT(1),       /* cur_capacity */
-        D_CHAR(2),      /* multsect - multsect_valid */
-        D_INT(1),       /* lba_capacity */
-        D_SHORT(194)    /* dma_1word - reservedyy */
-};
-
-#define num_driveid_types       (sizeof(driveid_types)/sizeof(*driveid_types))
-
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-#include <asm/amigappc.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-
-#include "local_irq.h"
-
-unsigned long m68k_machtype;
-char debug_device[6] = "";
-
-extern void amiga_init_IRQ(void);
-
-void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
-/* machine dependent keyboard functions */
-int (*mach_keyb_init) (void) __initdata = NULL;
-int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
-void (*mach_kbd_leds) (unsigned int) = NULL;
-/* machine dependent irq functions */
-void (*mach_init_IRQ) (void) __initdata = NULL;
-void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
-void (*mach_get_model) (char *model) = NULL;
-int (*mach_get_hardware_list) (char *buffer) = NULL;
-int (*mach_get_irq_list) (char *) = NULL;
-void (*mach_process_int) (int, struct pt_regs *) = NULL;
-/* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
-void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
-int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
-int (*mach_set_clock_mmss) (unsigned long) = NULL;
-void (*mach_reset)( void );
-long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#if defined(CONFIG_AMIGA_FLOPPY)
-void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
-#endif
-#ifdef CONFIG_HEARTBEAT
-void (*mach_heartbeat) (int) = NULL;
-extern void apus_heartbeat (void);
-#endif
-
-extern unsigned long amiga_model;
-extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
-extern unsigned count_period_num; /* 1 decrementer count equals */
-extern unsigned count_period_den; /* count_period_num / count_period_den us */
-
-int num_memory = 0;
-struct mem_info memory[NUM_MEMINFO];/* memory description */
-/* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
-int m68k_realnum_memory = 0;
-struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
-
-struct mem_info ramdisk;
-
-extern void amiga_floppy_setup(char *, int *);
-extern void config_amiga(void);
-
-static int __60nsram = 0;
-
-/* for cpuinfo */
-static int __bus_speed = 0;
-static int __speed_test_failed = 0;
-
-/********************************************** COMPILE PROTECTION */
-/* Provide some stubs that links to Amiga specific functions. 
- * This allows CONFIG_APUS to be removed from generic PPC files while
- * preventing link errors for other PPC targets.
- */
-unsigned long apus_get_rtc_time(void)
-{
-#ifdef CONFIG_APUS
-	extern unsigned long m68k_get_rtc_time(void);
-	
-	return m68k_get_rtc_time ();
-#else
-	return 0;
-#endif
-}
-
-int apus_set_rtc_time(unsigned long nowtime)
-{
-#ifdef CONFIG_APUS
-	extern int m68k_set_rtc_time(unsigned long nowtime);
-
-	return m68k_set_rtc_time (nowtime);
-#else
-	return 0;
-#endif
-}
-
-
-
-/* Here some functions we don't support, but which the other ports reference */
-int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-	return 0; 
-}
-int pckbd_getkeycode(unsigned int scancode) 
-{ 
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-	return 0; 
-}
-int pckbd_translate(unsigned char scancode, unsigned char *keycode,
-		    char raw_mode) 
-{
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-	return 0; 
-}
-char pckbd_unexpected_up(unsigned char keycode)
-{
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-	return 0;
-}
-void pckbd_leds(unsigned char leds)
-{
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-}
-void pckbd_init_hw(void)
-{
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-}
-unsigned char pckbd_sysrq_xlate[128];
-
-struct pci_bus * __init pci_scan_peer_bridge(int bus)
-{
-	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
-	return NULL;
-}
-
-/*********************************************************** SETUP */
-/* From arch/m68k/kernel/setup.c. */
-void __init apus_setup_arch(void)
-{
-#ifdef CONFIG_APUS
-	extern char cmd_line[];
-	int i;
-	char *p, *q;
-
-	/* Let m68k-shared code know it should do the Amiga thing. */
-	m68k_machtype = MACH_AMIGA;
-
-	/* Parse the command line for arch-specific options.
-	 * For the m68k, this is currently only "debug=xxx" to enable printing
-	 * certain kernel messages to some machine-specific device.  */
-	for( p = cmd_line; p && *p; ) {
-	    i = 0;
-	    if (!strncmp( p, "debug=", 6 )) {
-		    strncpy( debug_device, p+6, sizeof(debug_device)-1 );
-		    debug_device[sizeof(debug_device)-1] = 0;
-		    if ((q = strchr( debug_device, ' ' ))) *q = 0;
-		    i = 1;
-	    } else if (!strncmp( p, "60nsram", 7 )) {
-		    APUS_WRITE (APUS_REG_WAITSTATE, 
-				REGWAITSTATE_SETRESET
-				|REGWAITSTATE_PPCR
-				|REGWAITSTATE_PPCW);
-		    __60nsram = 1;
-		    i = 1;
-	    }
-
-	    if (i) {
-		/* option processed, delete it */
-		if ((q = strchr( p, ' ' )))
-		    strcpy( p, q+1 );
-		else
-		    *p = 0;
-	    } else {
-		if ((p = strchr( p, ' ' ))) ++p;
-	    }
-	}
-
-	config_amiga();
-
-#if 0 /* Enable for logging - also include logging.o in Makefile rule */
-	{
-#define LOG_SIZE 4096
-		void* base;
-
-		/* Throw away some memory - the P5 firmare stomps on top
-		 * of CHIP memory during bootup.
-		 */
-		amiga_chip_alloc(0x1000);
-
-		base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
-		LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
-	}
-#endif
-#endif
-}
-
-int
-apus_show_cpuinfo(struct seq_file *m)
-{
-	extern int __map_without_bats;
-	extern unsigned long powerup_PCI_present;
-
-	seq_printf(m, "machine\t\t: Amiga\n");
-	seq_printf(m, "bus speed\t: %d%s", __bus_speed,
-		   (__speed_test_failed) ? " [failed]\n" : "\n");
-	seq_printf(m, "using BATs\t: %s\n",
-		   (__map_without_bats) ? "No" : "Yes");
-	seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70);
-	seq_printf(m, "PCI bridge\t: %s\n",
-		   (powerup_PCI_present) ? "Yes" : "No");
-	return 0;
-}
-
-static void get_current_tb(unsigned long long *time)
-{
-	__asm __volatile ("1:mftbu 4      \n\t"
-			  "  mftb  5      \n\t"
-			  "  mftbu 6      \n\t"
-			  "  cmpw  4,6    \n\t"
-			  "  bne   1b     \n\t"
-			  "  stw   4,0(%0)\n\t"
-			  "  stw   5,4(%0)\n\t"
-			  : 
-			  : "r" (time)
-			  : "r4", "r5", "r6");
-}
-
-
-void apus_calibrate_decr(void)
-{
-#ifdef CONFIG_APUS
-	unsigned long freq;
-
-	/* This algorithm for determining the bus speed was
-           contributed by Ralph Schmidt. */
-	unsigned long long start, stop;
-	int bus_speed;
-	int speed_test_failed = 0;
-
-	{
-		unsigned long loop = amiga_eclock / 10;
-
-		get_current_tb (&start);
-		while (loop--) {
-			unsigned char tmp;
-
-			tmp = ciaa.pra;
-		}
-		get_current_tb (&stop);
-	}
-
-	bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
-	if (AMI_1200 == amiga_model)
-		bus_speed /= 2;
-
-	if ((bus_speed >= 47) && (bus_speed < 53)) {
-		bus_speed = 50;
-		freq = 12500000;
-	} else if ((bus_speed >= 57) && (bus_speed < 63)) {
-		bus_speed = 60;
-		freq = 15000000;
-	} else if ((bus_speed >= 63) && (bus_speed < 69)) {
-		bus_speed = 67;
-		freq = 16666667;
-	} else {
-		printk ("APUS: Unable to determine bus speed (%d). "
-			"Defaulting to 50MHz", bus_speed);
-		bus_speed = 50;
-		freq = 12500000;
-		speed_test_failed = 1;
-	}
-
-	/* Ease diagnostics... */
-	{
-		extern int __map_without_bats;
-		extern unsigned long powerup_PCI_present;
-
-		printk ("APUS: BATs=%d, BUS=%dMHz",
-			(__map_without_bats) ? 0 : 1,
-			bus_speed);
-		if (speed_test_failed)
-			printk ("[FAILED - please report]");
-
-		printk (", RAM=%dns, PCI bridge=%d\n",
-			(__60nsram) ? 60 : 70,
-			(powerup_PCI_present) ? 1 : 0);
-
-		/* print a bit more if asked politely... */
-		if (!(ciaa.pra & 0x40)){
-			extern unsigned int bat_addrs[4][3];
-			int b;
-			for (b = 0; b < 4; ++b) {
-				printk ("APUS: BAT%d ", b);
-				printk ("%08x-%08x -> %08x\n",
-					bat_addrs[b][0],
-					bat_addrs[b][1],
-					bat_addrs[b][2]);
-			}
-		}
-
-	}
-
-        printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-	       freq/1000000, freq%1000000);
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-
-	__bus_speed = bus_speed;
-	__speed_test_failed = speed_test_failed;
-#endif
-}
-
-void arch_gettod(int *year, int *mon, int *day, int *hour,
-		 int *min, int *sec)
-{
-#ifdef CONFIG_APUS
-	if (mach_gettod)
-		mach_gettod(year, mon, day, hour, min, sec);
-	else
-		*year = *mon = *day = *hour = *min = *sec = 0;
-#endif
-}
-
-/* for "kbd-reset" cmdline param */
-__init
-void kbd_reset_setup(char *str, int *ints)
-{
-}
-
-/*********************************************************** FLOPPY */
-#if defined(CONFIG_AMIGA_FLOPPY)
-__init 
-void floppy_setup(char *str, int *ints)
-{
-	if (mach_floppy_setup)
-		mach_floppy_setup (str, ints);
-}
-#endif
-
-/*********************************************************** MEMORY */
-#define KMAP_MAX 32
-unsigned long kmap_chunks[KMAP_MAX*3];
-int kmap_chunk_count = 0;
-
-/* From pgtable.h */
-static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
-{
-	pgd_t *dir = 0;
-	pmd_t *pmd = 0;
-	pte_t *pte = 0;
-
-	va &= PAGE_MASK;
-	
-	dir = pgd_offset( mm, va );
-	if (dir)
-	{
-		pmd = pmd_offset(dir, va & PAGE_MASK);
-		if (pmd && pmd_present(*pmd))
-		{
-			pte = pte_offset(pmd, va);
-		}
-	}
-	return pte;
-}
-
-
-/* Again simulating an m68k/mm/kmap.c function. */
-void kernel_set_cachemode( unsigned long address, unsigned long size,
-			   unsigned int cmode )
-{
-	unsigned long mask, flags;
-
-	switch (cmode)
-	{
-	case IOMAP_FULL_CACHING:
-		mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
-		flags = 0;
-		break;
-	case IOMAP_NOCACHE_SER:
-		mask = ~0;
-		flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
-		break;
-	default:
-		panic ("kernel_set_cachemode() doesn't support mode %d\n", 
-		       cmode);
-		break;
-	}
-	
-	size /= PAGE_SIZE;
-	address &= PAGE_MASK;
-	while (size--)
-	{
-		pte_t *pte;
-
-		pte = my_find_pte(&init_mm, address);
-		if ( !pte )
-		{
-			printk("pte NULL in kernel_set_cachemode()\n");
-			return;
-		}
-
-                pte_val (*pte) &= mask;
-                pte_val (*pte) |= flags;
-                flush_tlb_page(find_vma(&init_mm,address),address);
-
-		address += PAGE_SIZE;
-	}
-}
-
-unsigned long mm_ptov (unsigned long paddr)
-{
-	unsigned long ret;
-	if (paddr < 16*1024*1024)
-		ret = ZTWO_VADDR(paddr);
-	else {
-		int i;
-
-		for (i = 0; i < kmap_chunk_count;){
-			unsigned long phys = kmap_chunks[i++];
-			unsigned long size = kmap_chunks[i++];
-			unsigned long virt = kmap_chunks[i++];
-			if (paddr >= phys
-			    && paddr < (phys + size)){
-				ret = virt + paddr - phys;
-				goto exit;
-			}
-		}
-		
-		ret = (unsigned long) __va(paddr);
-	}
-exit:
-#ifdef DEBUGPV
-	printk ("PTOV(%lx)=%lx\n", paddr, ret);
-#endif
-	return ret;
-}
-
-int mm_end_of_chunk (unsigned long addr, int len)
-{
-	if (memory[0].addr + memory[0].size == addr + len)
-		return 1;
-	return 0;
-}
-
-/*********************************************************** CACHE */
-
-#define L1_CACHE_BYTES 32
-#define MAX_CACHE_SIZE 8192
-void cache_push(__u32 addr, int length)
-{
-	addr = mm_ptov(addr);
-
-	if (MAX_CACHE_SIZE < length)
-		length = MAX_CACHE_SIZE;
-
-	while(length > 0){
-		__asm ("dcbf 0,%0\n\t"
-		       : : "r" (addr));
-		addr += L1_CACHE_BYTES;
-		length -= L1_CACHE_BYTES;
-	}
-	/* Also flush trailing block */
-	__asm ("dcbf 0,%0\n\t"
-	       "sync \n\t"
-	       : : "r" (addr));
-}
-
-void cache_clear(__u32 addr, int length)
-{
-	if (MAX_CACHE_SIZE < length)
-		length = MAX_CACHE_SIZE;
-
-	addr = mm_ptov(addr);
-
-	__asm ("dcbf 0,%0\n\t"
-	       "sync \n\t"
-	       "icbi 0,%0 \n\t"
-	       "isync \n\t"
-	       : : "r" (addr));
-	
-	addr += L1_CACHE_BYTES;
-	length -= L1_CACHE_BYTES;
-
-	while(length > 0){
-		__asm ("dcbf 0,%0\n\t"
-		       "sync \n\t"
-		       "icbi 0,%0 \n\t"
-		       "isync \n\t"
-		       : : "r" (addr));
-		addr += L1_CACHE_BYTES;
-		length -= L1_CACHE_BYTES;
-	}
-
-	__asm ("dcbf 0,%0\n\t"
-	       "sync \n\t"
-	       "icbi 0,%0 \n\t"
-	       "isync \n\t"
-	       : : "r" (addr));
-}
-
-/****************************************************** from setup.c */
-void
-apus_restart(char *cmd)
-{
-	cli();
-
-	APUS_WRITE(APUS_REG_LOCK, 
-		   REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
-	APUS_WRITE(APUS_REG_LOCK, 
-		   REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
-	APUS_WRITE(APUS_REG_LOCK, 
-		   REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
-	APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
-	APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
-	for(;;);
-}
-
-void
-apus_power_off(void)
-{
-	for (;;);
-}
-
-void
-apus_halt(void)
-{
-   apus_restart(NULL);
-}
-
-/****************************************************** from setup.c/IDE */
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-
-#if 0	/* no longer used  -- paulus */
-void
-apus_ide_fix_driveid(struct hd_driveid *id)
-{
-   u_char *p = (u_char *)id;
-   int i, j, cnt;
-   u_char t;
-
-   if (!MACH_IS_AMIGA && !MACH_IS_MAC)
-   	return;
-   for (i = 0; i < num_driveid_types; i++) {
-      cnt = driveid_types[i] & T_MASK_COUNT;
-      switch (driveid_types[i] & T_MASK_TYPE) {
-         case T_CHAR:
-            p += cnt;
-            break;
-         case T_SHORT:
-            for (j = 0; j < cnt; j++) {
-               t = p[0];
-               p[0] = p[1];
-               p[1] = t;
-               p += 2;
-            }
-            break;
-         case T_INT:
-            for (j = 0; j < cnt; j++) {
-               t = p[0];
-               p[0] = p[3];
-               p[3] = t;
-               t = p[1];
-               p[1] = p[2];
-               p[2] = t;
-               p += 4;
-            }
-            break;
-         case T_TEXT:
-            for (j = 0; j < cnt; j += 2) {
-               t = p[0];
-               p[0] = p[1];
-               p[1] = t;
-               p += 2;
-            }
-            break;
-      }
-   }
-}
-#endif /* 0 */
-
-__init
-void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, 
-			       ide_ioreg_t ctrl_port, int *irq)
-{
-        if (data_port || ctrl_port)
-                printk("apus_ide_init_hwif_ports: must not be called\n");
-}
-#endif
-/****************************************************** IRQ stuff */
-
-static unsigned int apus_irq_cannonicalize(unsigned int irq)
-{
-	return irq;
-}
-
-int apus_get_irq_list(char *buf)
-{
-#ifdef CONFIG_APUS
-	extern int amiga_get_irq_list(char *buf);
-	
-	return amiga_get_irq_list (buf);
-#else
-	return 0;
-#endif
-}
-
-/* IPL must be between 0 and 7 */
-static inline void apus_set_IPL(unsigned long ipl)
-{
-	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
-	APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
-	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | ((~ipl) & IPLEMU_IPLMASK));
-	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
-}
-
-static inline unsigned long apus_get_IPL(void)
-{
-	/* This returns the present IPL emulation level. */
-	unsigned long __f;
-	APUS_READ(APUS_IPL_EMU, __f);
-	return ((~__f) & IPLEMU_IPLMASK);
-}
-
-static inline unsigned long apus_get_prev_IPL(struct pt_regs* regs)
-{
-	/* The value saved in mq is the IPL_EMU value at the time of
-	   interrupt. The lower bits are the current interrupt level,
-	   the upper bits the requested level. Thus, to restore the
-	   IPL level to the post-interrupt state, we will need to use
-	   the lower bits. */
-	unsigned long __f = regs->mq;
-	return ((~__f) & IPLEMU_IPLMASK);
-}
-
-
-#ifdef CONFIG_APUS
-void free_irq(unsigned int irq, void *dev_id)
-{
-	extern void amiga_free_irq(unsigned int irq, void *dev_id);
-
-	amiga_free_irq (irq, dev_id);
-}
-
-int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-	unsigned long irqflags, const char * devname, void *dev_id)
-{
-	extern int  amiga_request_irq(unsigned int irq, 
-				      void (*handler)(int, void *, 
-						      struct pt_regs *),
-				      unsigned long flags, 
-				      const char *devname, 
-				      void *dev_id);
-
-	return amiga_request_irq (irq, handler, irqflags, devname, dev_id);
-}
-
-/* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what
-   callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO
-   vectors (24-31), so we put this dummy function in between to adjust
-   the vector argument (rather have cruft here than in the generic irq.c). */
-int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-		    unsigned long irqflags, const char * devname, void *dev_id)
-{
-	extern int request_sysirq(unsigned int irq, 
-				  void (*handler)(int, void *, 
-						  struct pt_regs *),
-				  unsigned long irqflags,
-				  const char * devname, void *dev_id);
-	return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags, 
-			      devname, dev_id);
-}
-#endif
-
-int apus_get_irq(struct pt_regs* regs)
-{
-#ifdef CONFIG_APUS
-	int level = apus_get_IPL();
-
-#ifdef __INTERRUPT_DEBUG
-	printk("<%d:%d>", level, apus_get_prev_IPL(regs));
-#endif
-
-	if (0 == level)
-		return -8;
-	if (7 == level)
-		return -9;
-
-	return level + IRQ_AMIGA_AUTO;
-#else
-	return 0;
-#endif
-}
-
-void apus_post_irq(struct pt_regs* regs, int level)
-{
-#ifdef __INTERRUPT_DEBUG
-	printk("{%d}", apus_get_prev_IPL(regs));
-#endif
-	/* Restore IPL to the previous value */
-	apus_set_IPL(apus_get_prev_IPL(regs));
-}
-
-/****************************************************** keyboard */
-static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
-{
-	return -EOPNOTSUPP;
-}
-
-static int apus_kbd_getkeycode(unsigned int scancode)
-{
-	return scancode > 127 ? -EINVAL : scancode;
-}
-
-static int apus_kbd_translate(unsigned char keycode, unsigned char *keycodep,
-			      char raw_mode)
-{
-	*keycodep = keycode;
-	return 1;
-}
-
-static char apus_kbd_unexpected_up(unsigned char keycode)
-{
-	return 0200;
-}
-
-static void apus_kbd_leds(unsigned char leds)
-{
-}
-
-static void apus_kbd_init_hw(void)
-{
-#ifdef CONFIG_APUS
-	extern int amiga_keyb_init(void);
-
-	amiga_keyb_init();
-#endif
-}
-
-
-/****************************************************** debugging */
-
-/* some serial hardware definitions */
-#define SDR_OVRUN   (1<<15)
-#define SDR_RBF     (1<<14)
-#define SDR_TBE     (1<<13)
-#define SDR_TSRE    (1<<12)
-
-#define AC_SETCLR   (1<<15)
-#define AC_UARTBRK  (1<<11)
-
-#define SER_DTR     (1<<7)
-#define SER_RTS     (1<<6)
-#define SER_DCD     (1<<5)
-#define SER_CTS     (1<<4)
-#define SER_DSR     (1<<3)
-
-static __inline__ void ser_RTSon(void)
-{
-    ciab.pra &= ~SER_RTS; /* active low */
-}
-
-int __debug_ser_out( unsigned char c )
-{
-	custom.serdat = c | 0x100;
-	mb();
-	while (!(custom.serdatr & 0x2000))
-		barrier();
-	return 1;
-}
-
-unsigned char __debug_ser_in( void )
-{
-	unsigned char c;
-
-	/* XXX: is that ok?? derived from amiga_ser.c... */
-	while( !(custom.intreqr & IF_RBF) )
-		barrier();
-	c = custom.serdatr;
-	/* clear the interrupt, so that another character can be read */
-	custom.intreq = IF_RBF;
-	return c;
-}
-
-int __debug_serinit( void )
-{	
-	unsigned long flags;
-	
-	save_flags (flags);
-	cli();
-
-	/* turn off Rx and Tx interrupts */
-	custom.intena = IF_RBF | IF_TBE;
-
-	/* clear any pending interrupt */
-	custom.intreq = IF_RBF | IF_TBE;
-
-	restore_flags (flags);
-
-	/*
-	 * set the appropriate directions for the modem control flags,
-	 * and clear RTS and DTR
-	 */
-	ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
-	ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
-	
-#ifdef CONFIG_KGDB
-	/* turn Rx interrupts on for GDB */
-	custom.intena = IF_SETCLR | IF_RBF;
-	ser_RTSon();
-#endif
-
-	return 0;
-}
-
-void __debug_print_hex(unsigned long x)
-{
-	int i;
-	char hexchars[] = "0123456789ABCDEF";
-
-	for (i = 0; i < 8; i++) {
-		__debug_ser_out(hexchars[(x >> 28) & 15]);
-		x <<= 4;
-	}
-	__debug_ser_out('\n');
-	__debug_ser_out('\r');
-}
-
-void __debug_print_string(char* s)
-{
-	unsigned char c;
-	while((c = *s++))
-		__debug_ser_out(c);
-	__debug_ser_out('\n');
-	__debug_ser_out('\r');
-}
-
-static void apus_progress(char *s, unsigned short value)
-{
-	__debug_print_string(s);
-}
-
-/****************************************************** init */
-
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
-#define NUM_IRQ_NODES 100
-static irq_node_t nodes[NUM_IRQ_NODES];
-
-extern void (*amiga_default_handler[AUTO_IRQS])(int, void *, struct pt_regs *);
-
-static const char *default_names[SYS_IRQS] = {
-	"spurious int", "int1 handler", "int2 handler", "int3 handler",
-	"int4 handler", "int5 handler", "int6 handler", "int7 handler"
-};
-
-irq_node_t *new_irq_node(void)
-{
-	irq_node_t *node;
-	short i;
-
-	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
-		if (!node->handler)
-			return node;
-
-	printk ("new_irq_node: out of nodes\n");
-	return NULL;
-}
-
-extern void amiga_enable_irq(unsigned int irq);
-extern void amiga_disable_irq(unsigned int irq);
-
-struct hw_interrupt_type amiga_irqctrl = {
-	" Amiga  ",
-	NULL,
-	NULL,
-	amiga_enable_irq,
-	amiga_disable_irq,
-	0,
-	0
-};
-
-#define HARDWARE_MAPPED_SIZE (512*1024)
-unsigned long __init apus_find_end_of_memory(void)
-{
-	int shadow = 0;
-	unsigned long total;
-
-	/* The memory size reported by ADOS excludes the 512KB
-	   reserved for PPC exception registers and possibly 512KB
-	   containing a shadow of the ADOS ROM. */
-	{
-		unsigned long size = memory[0].size;
-
-		/* If 2MB aligned, size was probably user
-                   specified. We can't tell anything about shadowing
-                   in this case so skip shadow assignment. */
-		if (0 != (size & 0x1fffff)){
-			/* Align to 512KB to ensure correct handling
-			   of both memfile and system specified
-			   sizes. */
-			size = ((size+0x0007ffff) & 0xfff80000);
-			/* If memory is 1MB aligned, assume
-                           shadowing. */
-			shadow = !(size & 0x80000);
-		}
-
-		/* Add the chunk that ADOS does not see. by aligning
-                   the size to the nearest 2MB limit upwards.  */
-		memory[0].size = ((size+0x001fffff) & 0xffe00000);
-	}
-
-	total = memory[0].size;
-
-	/* Remove the memory chunks that are controlled by special
-           Phase5 hardware. */
-
-	/* Remove the upper 512KB if it contains a shadow of
-	   the ADOS ROM. FIXME: It might be possible to
-	   disable this shadow HW. Check the booter
-	   (ppc_boot.c) */
-	if (shadow)
-		total -= HARDWARE_MAPPED_SIZE;
-
-	/* Remove the upper 512KB where the PPC exception
-	   vectors are mapped. */
-	total -= HARDWARE_MAPPED_SIZE;
-
-	/* Linux/APUS only handles one block of memory -- the one on
-	   the PowerUP board. Other system memory is horrible slow in
-	   comparison. The user can use other memory for swapping
-	   using the z2ram device. */
-	ram_phys_base = memory[0].addr;
-	return total;
-}
-
-static void __init
-apus_map_io(void)
-{
-	/* Map PPC exception vectors. */
-	io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
-	/* Map chip and ZorroII memory */
-	io_block_mapping(zTwoBase,   0x00000000, 0x01000000, _PAGE_IO);
-}
-
-__init
-void apus_init_IRQ(void)
-{
-	int i;
-
-	for ( i = 0 ; i < NR_IRQS ; i++ )
-		irq_desc[i].handler = &amiga_irqctrl;
-
-	for (i = 0; i < NUM_IRQ_NODES; i++)
-		nodes[i].handler = NULL;
-
-	for (i = 0; i < AUTO_IRQS; i++) {
-		if (amiga_default_handler[i] != NULL)
-			sys_request_irq(i, amiga_default_handler[i],
-					0, default_names[i], NULL);
-	}
-
-	amiga_init_IRQ();
-
-}
-
-__init
-void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-		   unsigned long r6, unsigned long r7)
-{
-	extern int parse_bootinfo(const struct bi_record *);
-	extern char _end[];
-	
-	/* Parse bootinfo. The bootinfo is located right after
-           the kernel bss */
-	parse_bootinfo((const struct bi_record *)&_end);
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* Take care of initrd if we have one. Use data from
-	   bootinfo to avoid the need to initialize PPC
-	   registers when kernel is booted via a PPC reset. */
-	if ( ramdisk.addr ) {
-		initrd_start = (unsigned long) __va(ramdisk.addr);
-		initrd_end = (unsigned long) 
-			__va(ramdisk.size + ramdisk.addr);
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	ISA_DMA_THRESHOLD = 0x00ffffff;
-
-	ppc_md.setup_arch     = apus_setup_arch;
-	ppc_md.show_cpuinfo   = apus_show_cpuinfo;
-	ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
-	ppc_md.init_IRQ       = apus_init_IRQ;
-	ppc_md.get_irq        = apus_get_irq;
-	
-#error Should use the ->end() member of irq_desc[x]. -- Cort
-	/*ppc_md.post_irq       = apus_post_irq;*/
-	
-#ifdef CONFIG_HEARTBEAT
-	ppc_md.heartbeat      = apus_heartbeat;
-	ppc_md.heartbeat_count = 1;
-#endif
-#ifdef APUS_DEBUG
-	__debug_serinit();
-	ppc_md.progress       = apus_progress;
-#endif
-	ppc_md.init           = NULL;
-
-	ppc_md.restart        = apus_restart;
-	ppc_md.power_off      = apus_power_off;
-	ppc_md.halt           = apus_halt;
-
-	ppc_md.time_init      = NULL;
-	ppc_md.set_rtc_time   = apus_set_rtc_time;
-	ppc_md.get_rtc_time   = apus_get_rtc_time;
-	ppc_md.calibrate_decr = apus_calibrate_decr;
-
-	ppc_md.find_end_of_memory = apus_find_end_of_memory;
-	ppc_md.setup_io_mappings = apus_map_io;
-
-	ppc_md.nvram_read_val = NULL;
-	ppc_md.nvram_write_val = NULL;
-
-	/* These should not be used for the APUS yet, since it uses
-	   the M68K keyboard now. */
-	ppc_md.kbd_setkeycode    = apus_kbd_setkeycode;
-	ppc_md.kbd_getkeycode    = apus_kbd_getkeycode;
-	ppc_md.kbd_translate     = apus_kbd_translate;
-	ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up;
-	ppc_md.kbd_leds          = apus_kbd_leds;
-	ppc_md.kbd_init_hw       = apus_kbd_init_hw;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-        ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
-#endif		
-}
-
-
-/*************************************************** coexistence */
-void __init adbdev_init(void)
-{
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- linux.orig/arch/ppc/kernel/chrp_pci.c	2001-09-08 19:38:41.000000000 +0000
+++ linux/arch/ppc/kernel/chrp_pci.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,330 +0,0 @@
-/*
- * BK Id: SCCS/s.chrp_pci.c 1.22 09/08/01 15:47:42 paulus
- */
-/*
- * CHRP pci routines.
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/ide.h>
-#include <linux/bootmem.h>
-
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/machdep.h>
-#include <asm/sections.h>
-#include <asm/pci-bridge.h>
-
-#include "open_pic.h"
-#include "pci.h"
-
-/* LongTrail */
-unsigned long gg2_pci_config_base;
-
-#define pci_config_addr(dev, offset) \
-(gg2_pci_config_base | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
-
-volatile struct Hydra *Hydra = NULL;
-
-/*
- * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
- * limit the bus number to 3 bits
- */
-
-#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
-
-#define cfg_read_bad(val, size)		*val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte	0xff
-#define bad_word	0xffff
-#define bad_dword	0xffffffffU
-
-#define GG2_PCI_OP(rw, size, type, op)					    \
-int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
-{									    \
-	if (dev->bus->number > 7) {					    \
-		cfg_##rw##_bad(val, size)				    \
-		return PCIBIOS_DEVICE_NOT_FOUND;			    \
-	}								    \
-	cfg_##rw(val, pci_config_addr(dev, off), type, op);		    \
-	return PCIBIOS_SUCCESSFUL;					    \
-}
-
-GG2_PCI_OP(read, byte, u8 *, in_8)
-GG2_PCI_OP(read, word, u16 *, in_le16)
-GG2_PCI_OP(read, dword, u32 *, in_le32)
-GG2_PCI_OP(write, byte, u8, out_8)
-GG2_PCI_OP(write, word, u16, out_le16)
-GG2_PCI_OP(write, dword, u32, out_le32)
-
-static struct pci_ops gg2_pci_ops =
-{
-	gg2_read_config_byte,
-	gg2_read_config_word,
-	gg2_read_config_dword,
-	gg2_write_config_byte,
-	gg2_write_config_word,
-	gg2_write_config_dword
-};
-
-/*
- * Access functions for PCI config space on IBM "python" host bridges.
- */
-#define PYTHON_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
-				 | (((o) & ~3) << 24))
-
-#define PYTHON_PCI_OP(rw, size, type, op, mask)			    	     \
-int __chrp								     \
-python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) 	     \
-{									     \
-	struct pci_controller *hose = dev->sysdata;			     \
-									     \
-	out_be32(hose->cfg_addr,					     \
-		 PYTHON_CFA(dev->bus->number, dev->devfn, offset));	     \
-	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);   	     \
-	return PCIBIOS_SUCCESSFUL;					     \
-}
-
-PYTHON_PCI_OP(read, byte, u8 *, in_8, 3)
-PYTHON_PCI_OP(read, word, u16 *, in_le16, 2)
-PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0)
-PYTHON_PCI_OP(write, byte, u8, out_8, 3)
-PYTHON_PCI_OP(write, word, u16, out_le16, 2)
-PYTHON_PCI_OP(write, dword, u32, out_le32, 0)
-
-static struct pci_ops python_pci_ops =
-{
-	python_read_config_byte,
-	python_read_config_word,
-	python_read_config_dword,
-	python_write_config_byte,
-	python_write_config_word,
-	python_write_config_dword
-};
-
-/*
- * Access functions for PCI config space using RTAS calls.
- */
-#define RTAS_PCI_READ_OP(size, type, nbytes)			    	  \
-int __chrp								  \
-rtas_read_config_##size(struct pci_dev *dev, int offset, type val) 	  \
-{									  \
-	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
-		| ((dev->bus->number & 0xff) << 16);			  \
-	unsigned long ret = ~0UL;					  \
-	int rval;							  \
-									  \
-	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes);	  \
-	*val = ret;							  \
-	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;    	  \
-}
-
-#define RTAS_PCI_WRITE_OP(size, type, nbytes)				  \
-int __chrp								  \
-rtas_write_config_##size(struct pci_dev *dev, int offset, type val)	  \
-{									  \
-	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
-		| ((dev->bus->number & 0xff) << 16);			  \
-	int rval;							  \
-									  \
-	rval = call_rtas("write-pci-config", 3, 1, NULL,		  \
-			 addr, nbytes, (ulong)val);			  \
-	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;	  \
-}
-
-RTAS_PCI_READ_OP(byte, u8 *, 1)
-RTAS_PCI_READ_OP(word, u16 *, 2)
-RTAS_PCI_READ_OP(dword, u32 *, 4)
-RTAS_PCI_WRITE_OP(byte, u8, 1)
-RTAS_PCI_WRITE_OP(word, u16, 2)
-RTAS_PCI_WRITE_OP(dword, u32, 4)
-
-static struct pci_ops rtas_pci_ops =
-{
-	rtas_read_config_byte,
-	rtas_read_config_word,
-	rtas_read_config_dword,
-	rtas_write_config_byte,
-	rtas_write_config_word,
-	rtas_write_config_dword
-};
-
-    /*
-     *  Temporary fixes for PCI devices. These should be replaced by OF query
-     *  code -- Geert
-     */
-
-static u_char hydra_openpic_initsenses[] __initdata = {
-    1,	/* HYDRA_INT_SIO */
-    0,	/* HYDRA_INT_SCSI_DMA */
-    0,	/* HYDRA_INT_SCCA_TX_DMA */
-    0,	/* HYDRA_INT_SCCA_RX_DMA */
-    0,	/* HYDRA_INT_SCCB_TX_DMA */
-    0,	/* HYDRA_INT_SCCB_RX_DMA */
-    1,	/* HYDRA_INT_SCSI */
-    1,	/* HYDRA_INT_SCCA */
-    1,	/* HYDRA_INT_SCCB */
-    1,	/* HYDRA_INT_VIA */
-    1,	/* HYDRA_INT_ADB */
-    0,	/* HYDRA_INT_ADB_NMI */
-    	/* all others are 1 (= default) */
-};
-
-int __init
-hydra_init(void)
-{
-	struct device_node *np;
-
-	np = find_devices("mac-io");
-	if (np == NULL || np->n_addrs == 0) {
-		printk(KERN_WARNING "Warning: no mac-io found\n");
-		return 0;
-	}
-	Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
-	printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
-	out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
-					   HYDRA_FC_SCSI_CELL_EN |
-					   HYDRA_FC_SCCA_ENABLE |
-					   HYDRA_FC_SCCB_ENABLE |
-					   HYDRA_FC_ARB_BYPASS |
-					   HYDRA_FC_MPIC_ENABLE |
-					   HYDRA_FC_SLOW_SCC_PCLK |
-					   HYDRA_FC_MPIC_IS_MASTER));
-	OpenPIC_Addr = &Hydra->OpenPIC;
-	OpenPIC_InitSenses = hydra_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(hydra_openpic_initsenses);
-	return 1;
-}
-
-void __init
-chrp_pcibios_fixup(void)
-{
-	struct pci_dev *dev;
-	struct device_node *np;
-
-	/* PCI interrupts are controlled by the OpenPIC */
-	pci_for_each_dev(dev) {
-		np = pci_device_to_OF_node(dev);
-		if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
-			dev->irq = np->intrs[0].line;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-}
-
-void __init
-chrp_find_bridges(void)
-{
-	struct device_node *dev;
-	int *bus_range;
-	int len, index = -1;
-	struct pci_controller *hose;
-	volatile unsigned char *cfg;
-	unsigned int *dma;
-	char *model, *machine;
-	int is_longtrail = 0, is_mot = 0;
-	struct device_node *root = find_path_device("/");
-#ifdef CONFIG_POWER3
-	unsigned int *opprop = (unsigned int *)
-		get_property(root, "platform-open-pic", NULL);
-	int i;
-#endif
-
-	/*
-	 * The PCI host bridge nodes on some machines don't have
-	 * properties to adequately identify them, so we have to
-	 * look at what sort of machine this is as well.
-	 */
-	machine = get_property(root, "model", NULL);
-	if (machine != NULL) {
-		is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
-		is_mot = strncmp(machine, "MOT", 3) == 0;
-	}
-	for (dev = root->child; dev != NULL; dev = dev->sibling) {
-		if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
-			continue;
-		++index;
-		/* The GG2 bridge on the LongTrail doesn't have an address */
-		if (dev->n_addrs < 1 && !is_longtrail) {
-			printk(KERN_WARNING "Can't use %s: no address\n",
-			       dev->full_name);
-			continue;
-		}
-		bus_range = (int *) get_property(dev, "bus-range", &len);
-		if (bus_range == NULL || len < 2 * sizeof(int)) {
-			printk(KERN_WARNING "Can't get bus-range for %s\n",
-				dev->full_name);
-			continue;
-		}
-		if (bus_range[1] == bus_range[0])
-			printk(KERN_INFO "PCI bus %d", bus_range[0]);
-		else
-			printk(KERN_INFO "PCI buses %d..%d",
-			       bus_range[0], bus_range[1]);
-		printk(" controlled by %s", dev->type);
-		if (dev->n_addrs > 0)
-			printk(" at %x", dev->addrs[0].address);
-		printk("\n");
-
-		hose = pcibios_alloc_controller();
-		if (!hose) {
-			printk("Can't allocate PCI controller structure for %s\n",
-				dev->full_name);
-			continue;
-		}
-		hose->arch_data = dev;
-		hose->first_busno = bus_range[0];
-		hose->last_busno = bus_range[1];
-
-		model = get_property(dev, "model", NULL);
-		if (model == NULL)
-			model = "<none>";
-		if (device_is_compatible(dev, "IBM,python")) {
-			hose->ops = &python_pci_ops;
-			cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20);
-			hose->cfg_addr = (volatile unsigned int *) cfg;
-			hose->cfg_data = cfg + 0x10;
-		} else if (is_mot
-			   || strncmp(model, "Motorola, Grackle", 17) == 0) {
-			setup_grackle(hose);
-		} else if (is_longtrail) {
-			hose->ops = &gg2_pci_ops;
-			gg2_pci_config_base = (unsigned long)
-				ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
-		} else {
-			printk("No methods for %s (model %s), using RTAS\n",
-			       dev->full_name, model);
-			hose->ops = &rtas_pci_ops;
-		}
-
-		pci_process_bridge_OF_ranges(hose, dev, index == 0);
-
-#ifdef CONFIG_POWER3
-		if (opprop != NULL) {
-			i = prom_n_addr_cells(root) * (index + 2) - 1;
-			openpic_setup_ISU(index, opprop[i]);
-		}
-#endif /* CONFIG_POWER3 */
-
-		/* check the first bridge for a property that we can
-		   use to set pci_dram_offset */
-		dma = (unsigned int *)
-			get_property(dev, "ibm,dma-ranges", &len);
-		if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
-			pci_dram_offset = dma[2] - dma[3];
-			printk("pci_dram_offset = %lx\n", pci_dram_offset);
-		}
-	}
-
-	ppc_md.pcibios_fixup = chrp_pcibios_fixup;
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- linux.orig/arch/ppc/kernel/chrp_setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/chrp_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,634 +0,0 @@
-/*
- * BK Id: SCCS/s.chrp_setup.c 1.42 04/09/02 21:43:09 paulus
- */
-/*
- *  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)
- */
-
-/*
- * 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/slab.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/ioport.h>
-#include <linux/console.h>
-#include <linux/pci.h>
-#include <linux/version.h>
-#include <linux/adb.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/prom.h>
-#include <asm/gg2.h>
-#include <asm/pci-bridge.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/irq.h>
-#include <asm/hydra.h>
-#include <asm/keyboard.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-#include <asm/btext.h>
-
-#include "local_irq.h"
-#include "i8259.h"
-#include "open_pic.h"
-#include "xics.h"
-
-unsigned long chrp_get_rtc_time(void);
-int chrp_set_rtc_time(unsigned long nowtime);
-void chrp_calibrate_decr(void);
-long chrp_time_init(void);
-
-void chrp_find_bridges(void);
-void chrp_event_scan(void);
-void rtas_display_progress(char *, unsigned short);
-void rtas_indicator_progress(char *, unsigned short);
-void btext_progress(char *, unsigned short);
-
-extern unsigned long pmac_find_end_of_memory(void);
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
-			   char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[128];
-extern void select_adb_keyboard(void);
-extern int of_show_percpuinfo(struct seq_file *, int);
-
-extern kdev_t boot_dev;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-static int max_width;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t chrp_smp_ops;
-extern struct smp_ops_t xics_smp_ops;
-#endif
-
-static const char *gg2_memtypes[4] = {
-	"FPM", "SDRAM", "EDO", "BEDO"
-};
-static const char *gg2_cachesizes[4] = {
-	"256 KB", "512 KB", "1 MB", "Reserved"
-};
-static const char *gg2_cachetypes[4] = {
-	"Asynchronous", "Reserved", "Flow-Through Synchronous",
-	"Pipelined Synchronous"
-};
-static const char *gg2_cachemodes[4] = {
-	"Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
-};
-
-int __chrp
-chrp_show_cpuinfo(struct seq_file *m)
-{
-	int i, sdramen;
-	unsigned int t;
-	struct device_node *root;
-	const char *model = "";
-
-	root = find_path_device("/");
-	if (root)
-		model = get_property(root, "model", NULL);
-	seq_printf(m, "machine\t\t: CHRP %s\n", model);
-
-	/* longtrail (goldengate) stuff */
-	if (!strncmp(model, "IBM,LongTrail", 13)) {
-		/* VLSI VAS96011/12 `Golden Gate 2' */
-		/* Memory banks */
-		sdramen = (in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
-						GG2_PCI_DRAM_CTRL))
-			   >>31) & 1;
-		for (i = 0; i < (sdramen ? 4 : 6); i++) {
-			t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
-						 GG2_PCI_DRAM_BANK0+
-						 i*4));
-			if (!(t & 1))
-				continue;
-			switch ((t>>8) & 0x1f) {
-			case 0x1f:
-				model = "4 MB";
-				break;
-			case 0x1e:
-				model = "8 MB";
-				break;
-			case 0x1c:
-				model = "16 MB";
-				break;
-			case 0x18:
-				model = "32 MB";
-				break;
-			case 0x10:
-				model = "64 MB";
-				break;
-			case 0x00:
-				model = "128 MB";
-				break;
-			default:
-				model = "Reserved";
-				break;
-			}
-			seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
-				   gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
-		}
-		/* L2 cache */
-		t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_CC_CTRL));
-		seq_printf(m, "board l2\t: %s %s (%s)\n",
-			   gg2_cachesizes[(t>>7) & 3],
-			   gg2_cachetypes[(t>>2) & 3],
-			   gg2_cachemodes[t & 3]);
-	}
-	return 0;
-}
-
-/*
- *  Fixes for the National Semiconductor PC78308VUL SuperI/O
- *
- *  Some versions of Open Firmware incorrectly initialize the IRQ settings
- *  for keyboard and mouse
- */
-static inline void __init sio_write(u8 val, u8 index)
-{
-	outb(index, 0x15c);
-	outb(val, 0x15d);
-}
-
-static inline u8 __init sio_read(u8 index)
-{
-	outb(index, 0x15c);
-	return inb(0x15d);
-}
-
-static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
-				     u8 type)
-{
-	u8 level0, type0, active;
-
-	/* select logical device */
-	sio_write(device, 0x07);
-	active = sio_read(0x30);
-	level0 = sio_read(0x70);
-	type0 = sio_read(0x71);
-	if (level0 != level || type0 != type || !active) {
-		printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
-		       "remapping to level %d, type %d, active\n",
-		       name, level0, type0, !active ? "in" : "", level, type);
-		sio_write(0x01, 0x30);
-		sio_write(level, 0x70);
-		sio_write(type, 0x71);
-	}
-}
-
-static void __init sio_init(void)
-{
-	struct device_node *root;
-
-	if ((root = find_path_device("/")) &&
-	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
-		/* logical device 0 (KBC/Keyboard) */
-		sio_fixup_irq("keyboard", 0, 1, 2);
-		/* select logical device 1 (KBC/Mouse) */
-		sio_fixup_irq("mouse", 1, 12, 2);
-	}
-}
-
-
-void __init
-chrp_setup_arch(void)
-{
-	struct device_node *device;
-
-	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* this is fine for chrp */
-	initrd_below_start_ok = 1;
-	
-	if (initrd_start)
-		ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-	else
-#endif
-		ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
-
-	/* Lookup PCI host bridges */
-	chrp_find_bridges();
-
-#ifndef CONFIG_PPC64BRIDGE
-	/*
-	 *  Temporary fixes for PCI devices.
-	 *  -- Geert
-	 */
-	hydra_init();		/* Mac I/O */
-
-#endif /* CONFIG_PPC64BRIDGE */
-
-	/* Some IBM machines don't have the hydra -- Cort */
-	if (!OpenPIC_Addr) {
-		struct device_node *root;
-		unsigned long *opprop;
-		int n;
-
-		root = find_path_device("/");
-		opprop = (unsigned long *) get_property
-			(root, "platform-open-pic", NULL);
-		n = prom_n_addr_cells(root);
-		if (opprop != 0) {
-			printk("OpenPIC addrs: %lx %lx %lx\n",
-			       opprop[n-1], opprop[2*n-1], opprop[3*n-1]);
-			OpenPIC_Addr = ioremap(opprop[n-1], 0x40000);
-		}
-	}
-
-	/*
-	 *  Fix the Super I/O configuration
-	 */
-	sio_init();
-
-	/*
-	 *  Setup the console operations
-	 */
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	/* Get the event scan rate for the rtas so we know how
-	 * often it expects a heartbeat. -- Cort
-	 */
-	if ( rtas_data ) {
-		struct property *p;
-		device = find_devices("rtas");
-		for ( p = device->properties;
-		      p && strncmp(p->name, "rtas-event-scan-rate", 20);
-		      p = p->next )
-			/* nothing */ ;
-		if ( p && *(unsigned long *)p->value ) {
-			ppc_md.heartbeat = chrp_event_scan;
-			ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
-			ppc_md.heartbeat_count = 1;
-			printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
-			       *(unsigned long *)p->value, ppc_md.heartbeat_reset );
-		}
-	}
-}
-
-void __chrp
-chrp_event_scan(void)
-{
-	unsigned char log[1024];
-	unsigned long ret = 0;
-	/* XXX: we should loop until the hardware says no more error logs -- Cort */
-	call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
-		   __pa(log), 1024 );
-	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-	
-void __chrp
-chrp_restart(char *cmd)
-{
-	printk("RTAS system-reboot returned %d\n",
-	       call_rtas("system-reboot", 0, 1, NULL));
-	for (;;);
-}
-
-void __chrp
-chrp_power_off(void)
-{
-	/* allow power on only with power button press */
-	printk("RTAS power-off returned %d\n",
-	       call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
-	for (;;);
-}
-
-void __chrp
-chrp_halt(void)
-{
-	chrp_power_off();
-}
-
-u_int __chrp
-chrp_irq_cannonicalize(u_int irq)
-{
-	if (irq == 2)
-		return 9;
-	return irq;
-}
-
-void __init chrp_init_IRQ(void)
-{
-	struct device_node *np;
-	int i;
-	unsigned int *addrp;
-	unsigned char* chrp_int_ack_special = 0;
-	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
-	int nmi_irq = -1;
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)	
-	struct device_node *kbd;
-#endif
-
-	if (!(np = find_devices("pci"))
-	    || !(addrp = (unsigned int *)
-		 get_property(np, "8259-interrupt-acknowledge", NULL)))
-		printk("Cannot find pci to get ack address\n");
-	else
-		chrp_int_ack_special = (unsigned char *)
-			ioremap(addrp[prom_n_addr_cells(np)-1], 1);
-	/* hydra still sets OpenPIC_InitSenses to a static set of values */
-	if (OpenPIC_InitSenses == NULL) {
-		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
-		OpenPIC_InitSenses = init_senses;
-		OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
-	}
-	openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq);
-	for ( i = 0 ; i < NUM_8259_INTERRUPTS  ; i++ )
-		irq_desc[i].handler = &i8259_pic;
-	i8259_init(0);
-#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
-	/* see if there is a keyboard in the device tree
-	   with a parent of type "adb" */
-	for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
-		if (kbd->parent && kbd->parent->type
-		    && strcmp(kbd->parent->type, "adb") == 0)
-			break;
-	if (kbd)
-		request_irq( HYDRA_INT_ADB_NMI, xmon_irq, 0, "XMON break", 0);
-#endif
-}
-
-void __init
-chrp_init2(void)
-{
-#ifdef CONFIG_NVRAM  
-	pmac_nvram_init();
-#endif
-
-	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");
-
-	if (ppc_md.progress)
-		ppc_md.progress("  Have fun!    ", 0x7777);
-
-#if defined(CONFIG_VT) && (defined(CONFIG_ADB_KEYBOARD) || defined(CONFIG_INPUT))
-	/* see if there is a keyboard in the device tree
-	   with a parent of type "adb" */
-	{
-		struct device_node *kbd;
-
-		for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) {
-			if (kbd->parent && kbd->parent->type
-			    && strcmp(kbd->parent->type, "adb") == 0) {
-				select_adb_keyboard();
-				break;
-			}
-		}
-	}
-#endif /* CONFIG_VT && (CONFIG_ADB_KEYBOARD || CONFIG_INPUT) */
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-
-static int __chrp
-chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-        return check_region(from, extent);
-}
-
-static void __chrp
-chrp_ide_request_region(ide_ioreg_t from,
-			unsigned int extent,
-			const char *name)
-{
-        request_region(from, extent, name);
-}
-
-static void __chrp
-chrp_ide_release_region(ide_ioreg_t from,
-			unsigned int extent)
-{
-        release_region(from, extent);
-}
-
-static void __chrp
-chrp_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;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-}
-#endif
-
-/*
- * One of the main thing these mappings are needed for is so that
- * xmon can get to the serial port early on.  We probably should
- * handle the machines with the mpc106 as well as the python (F50)
- * and the GG2 (longtrail).  Actually we should look in the device
- * tree and do the right thing.
- */
-static void __init
-chrp_map_io(void)
-{
-	char *name;
-
-	/*
-	 * The code below tends to get removed, please don't take it out.
-	 * The F50 needs this mapping and it you take it out I'll track you
-	 * down and slap your hands.  If it causes problems please email me.
-	 *  -- Cort <cort@fsmlabs.com>
-	 */
-	name = get_property(find_path_device("/"), "name", NULL);
-	if (name && strncmp(name, "IBM-70", 6) == 0
-	    && strstr(name, "-F50")) {
-		io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
-		io_block_mapping(0x90000000, 0x90000000, 0x10000000, _PAGE_IO);
-		return;
-	} else {
-		io_block_mapping(0xf8000000, 0xf8000000, 0x04000000, _PAGE_IO);
-	}
-}
-
-void __init
-chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7)
-{
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* take care of initrd if we have one */
-	if ( r6 )
-	{
-		initrd_start = r6 + KERNELBASE;
-		initrd_end = r6 + r7 + KERNELBASE;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	ISA_DMA_THRESHOLD = ~0L;
-	DMA_MODE_READ = 0x44;
-	DMA_MODE_WRITE = 0x48;
-	isa_io_base = CHRP_ISA_IO_BASE;		/* default value */
-
-	ppc_md.setup_arch     = chrp_setup_arch;
-	ppc_md.show_percpuinfo = of_show_percpuinfo;
-	ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
-	ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
-#ifndef CONFIG_POWER4
-	ppc_md.init_IRQ       = chrp_init_IRQ;
-	ppc_md.get_irq        = openpic_get_irq;
-#else
-	ppc_md.init_IRQ	      = xics_init_IRQ;
-	ppc_md.get_irq	      = xics_get_irq;
-#endif /* CONFIG_POWER4 */
-
-	ppc_md.init           = chrp_init2;
-
-	ppc_md.restart        = chrp_restart;
-	ppc_md.power_off      = chrp_power_off;
-	ppc_md.halt           = chrp_halt;
-
-	ppc_md.time_init      = chrp_time_init;
-	ppc_md.set_rtc_time   = chrp_set_rtc_time;
-	ppc_md.get_rtc_time   = chrp_get_rtc_time;
-	ppc_md.calibrate_decr = chrp_calibrate_decr;
-
-	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
-	ppc_md.setup_io_mappings = chrp_map_io;
-
-#ifdef CONFIG_VT
-	/* these are adjusted in chrp_init2 if we have an ADB keyboard */
-	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.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-	SYSRQ_KEY = 0x54;
-#endif /* CONFIG_MAGIC_SYSRQ */
-#endif /* CONFIG_VT */
-
-	if (rtas_data) {
-		struct device_node *rtas;
-		unsigned int *p;
-
-		rtas = find_devices("rtas");
-		if (rtas != NULL) {
-			if (get_property(rtas, "display-character", NULL)) {
-				ppc_md.progress = rtas_display_progress;
-				p = (unsigned int *) get_property
-				       (rtas, "ibm,display-line-length", NULL);
-				if (p)
-					max_width = *p;
-			} else if (get_property(rtas, "set-indicator", NULL))
-				ppc_md.progress = rtas_indicator_progress;
-		}
-	}
-#ifdef CONFIG_BOOTX_TEXT
-	if (ppc_md.progress == NULL && boot_text_mapped)
-		ppc_md.progress = btext_progress;
-#endif
-
-#ifdef CONFIG_SMP
-#ifndef CONFIG_POWER4
-	ppc_md.smp_ops = &chrp_smp_ops;
-#else
-	ppc_md.smp_ops = &xics_smp_ops;
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_SMP */
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-        ppc_ide_md.ide_check_region = chrp_ide_check_region;
-        ppc_ide_md.ide_request_region = chrp_ide_request_region;
-        ppc_ide_md.ide_release_region = chrp_ide_release_region;
-        ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
-#endif
-
-	/*
-	 * Print the banner, then scroll down so boot progress
-	 * can be printed.  -- Cort 
-	 */
-	if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
-}
-
-void __chrp
-rtas_display_progress(char *s, unsigned short hex)
-{
-	int width;
-	char *os = s;
-
-	if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
-		return;
-
-	width = max_width;
-	while ( *os )
-	{
-		if ( (*os == '\n') || (*os == '\r') )
-			width = max_width;
-		else
-			width--;
-		call_rtas( "display-character", 1, 1, NULL, *os++ );
-		/* if we overwrite the screen length */
-		if ( width == 0 )
-			while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
-				os++;
-	}
-
-	/*while ( width-- > 0 )*/
-	call_rtas( "display-character", 1, 1, NULL, ' ' );
-}
-
-void __chrp
-rtas_indicator_progress(char *s, unsigned short hex)
-{
-	call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void
-btext_progress(char *s, unsigned short hex)
-{
-	prom_print(s);
-	prom_print("\n");
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/chrp_smp.c linux/arch/ppc/kernel/chrp_smp.c
--- linux.orig/arch/ppc/kernel/chrp_smp.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/chrp_smp.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,148 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- * Smp support for CHRP machines.
- *
- * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
- * deal of code from the sparc and intel versions.
- *
- * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/hardirq.h>
-#include <asm/softirq.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/time.h>
-
-#include "open_pic.h"
-
-extern unsigned long smp_chrp_cpu_nr;
-
-static int __init
-smp_chrp_probe(void)
-{
-	if (smp_chrp_cpu_nr > 1)
-		openpic_request_IPIs();
-
-	return smp_chrp_cpu_nr;
-}
-
-static void __init
-smp_chrp_kick_cpu(int nr)
-{
-	*(unsigned long *)KERNELBASE = nr;
-	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-}
-
-static void __init
-smp_chrp_setup_cpu(int cpu_nr)
-{
-	static atomic_t ready = ATOMIC_INIT(1);
-	static volatile int frozen = 0;
-
-	if (cpu_nr == 0) {
-		/* wait for all the others */
-		while (atomic_read(&ready) < smp_num_cpus)
-			barrier();
-		atomic_set(&ready, 1);
-		/* freeze the timebase */
-		call_rtas("freeze-time-base", 0, 1, NULL);
-		mb();
-		frozen = 1;
-		/* XXX assumes this is not a 601 */
-		set_tb(0, 0);
-		last_jiffy_stamp(0) = 0;
-		while (atomic_read(&ready) < smp_num_cpus)
-			barrier();
-		/* thaw the timebase again */
-		call_rtas("thaw-time-base", 0, 1, NULL);
-		mb();
-		frozen = 0;
-		smp_tb_synchronized = 1;
-	} else {
-		atomic_inc(&ready);
-		while (!frozen)
-			barrier();
-		set_tb(0, 0);
-		last_jiffy_stamp(0) = 0;
-		mb();
-		atomic_inc(&ready);
-		while (frozen)
-			barrier();
-	}
-
-	if (OpenPIC_Addr)
-		do_openpic_setup_cpu();
-}
-
-#ifdef CONFIG_POWER4
-static void __chrp
-smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
-{
-	/* for now, only do reschedule messages
-	   since we only have one IPI */
-	if (msg != PPC_MSG_RESCHEDULE)
-		return;
-	for (i = 0; i < smp_num_cpus; ++i) {
-		if (target == MSG_ALL || target == i
-		    || (target == MSG_ALL_BUT_SELF
-			&& i != smp_processor_id()))
-			xics_cause_IPI(i);
-	}
-}
-
-static int __chrp
-smp_xics_probe(void)
-{
-	return smp_chrp_cpu_nr;
-}
-
-static void __chrp
-smp_xics_setup_cpu(int cpu_nr)
-{
-	if (cpu_nr > 0)
-		xics_setup_cpu();
-}
-#endif /* CONFIG_POWER4 */
-
-/* CHRP with openpic */
-struct smp_ops_t chrp_smp_ops __chrpdata = {
-	smp_openpic_message_pass,
-	smp_chrp_probe,
-	smp_chrp_kick_cpu,
-	smp_chrp_setup_cpu,
-};
-
-#ifdef CONFIG_POWER4
-/* CHRP with new XICS interrupt controller */
-struct smp_ops_t xics_smp_ops __chrpdata = {
-	smp_xics_message_pass,
-	smp_xics_probe,
-	smp_chrp_kick_cpu,
-	smp_xics_setup_cpu,
-};
-#endif /* CONFIG_POWER4 */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/chrp_time.c linux/arch/ppc/kernel/chrp_time.c
--- linux.orig/arch/ppc/kernel/chrp_time.c	2001-09-08 19:38:41.000000000 +0000
+++ linux/arch/ppc/kernel/chrp_time.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,195 +0,0 @@
-/*
- * BK Id: SCCS/s.chrp_time.c 1.10 09/08/01 15:47:42 paulus
- */
-/*
- *  linux/arch/i386/kernel/time.c
- *
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * Adapted for PowerPC (PreP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- *  copied and modified from intel version
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/mc146818rtc.h>
-#include <linux/init.h>
-
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/nvram.h>
-#include <asm/prom.h>
-#include <asm/sections.h>
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-static int nvram_as1 = NVRAM_AS1;
-static int nvram_as0 = NVRAM_AS0;
-static int nvram_data = NVRAM_DATA;
-
-long __init chrp_time_init(void)
-{
-	struct device_node *rtcs;
-	int base;
-
-	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
-	if (rtcs == NULL || rtcs->addrs == NULL)
-		return 0;
-	base = rtcs->addrs[0].address;
-	nvram_as1 = 0;
-	nvram_as0 = base;
-	nvram_data = base + 1;
-	
-	return 0;
-}
-
-int __chrp chrp_cmos_clock_read(int addr)
-{
-	if (nvram_as1 != 0)
-		outb(addr>>8, nvram_as1);
-	outb(addr, nvram_as0);
-	return (inb(nvram_data));
-}
-
-void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
-{
-	if (nvram_as1 != 0)
-		outb(addr>>8, nvram_as1);
-	outb(addr, nvram_as0);
-	outb(val, nvram_data);
-	return;
-}
-
-/*
- * Set the hardware clock. -- Cort
- */
-int __chrp chrp_set_rtc_time(unsigned long nowtime)
-{
-	unsigned char save_control, save_freq_select;
-	struct rtc_time tm;
-
-	spin_lock(&rtc_lock);
-	to_tm(nowtime, &tm);
-
-	save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
-
-	chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
-
-	save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
-	
-	chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-
-        tm.tm_year -= 1900;
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-		BIN_TO_BCD(tm.tm_sec);
-		BIN_TO_BCD(tm.tm_min);
-		BIN_TO_BCD(tm.tm_hour);
-		BIN_TO_BCD(tm.tm_mon);
-		BIN_TO_BCD(tm.tm_mday);
-		BIN_TO_BCD(tm.tm_year);
-	}
-	chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
-	chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
-	chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
-	chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
-	chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
-	chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
-	
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	chrp_cmos_clock_write(save_control, RTC_CONTROL);
-	chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
-
-	if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
-		time_state = TIME_OK;
-	spin_unlock(&rtc_lock);
-	return 0;
-}
-
-unsigned long __chrp chrp_get_rtc_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-	int uip, i;
-
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-
-	/* Since the UIP flag is set for about 2.2 ms and the clock
-	 * is typically written with a precision of 1 jiffy, trying
-	 * to obtain a precision better than a few milliseconds is 
-	 * an illusion. Only consistency is interesting, this also
-	 * allows to use the routine for /dev/rtc without a potential
-	 * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
-	 */
-
-	for ( i = 0; i<1000000; i++) {
-		uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
-		sec = chrp_cmos_clock_read(RTC_SECONDS);
-		min = chrp_cmos_clock_read(RTC_MINUTES);
-		hour = chrp_cmos_clock_read(RTC_HOURS);
-		day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
-		mon = chrp_cmos_clock_read(RTC_MONTH);
-		year = chrp_cmos_clock_read(RTC_YEAR);
-		uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
-		if ((uip & RTC_UIP)==0) break;
-	}
-
-	if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-	  {
-	    BCD_TO_BIN(sec);
-	    BCD_TO_BIN(min);
-	    BCD_TO_BIN(hour);
-	    BCD_TO_BIN(day);
-	    BCD_TO_BIN(mon);
-	    BCD_TO_BIN(year);
-	  }
-	if ((year += 1900) < 1970)
-		year += 100;
-	return mktime(year, mon, day, hour, min, sec);
-}
-
-
-void __init chrp_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	unsigned int freq, *fp;
-
-	if (via_calibrate_decr())
-		return;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	freq = 16666000;		/* hardcoded default */
-	cpu = find_type_devices("cpu");
-	if (cpu != 0) {
-		fp = (unsigned int *)
-			get_property(cpu, "timebase-frequency", NULL);
-		if (fp != 0)
-			freq = *fp;
-	}
-	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
- 	       freq/1000000, freq%1000000);
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/cputable.c linux/arch/ppc/kernel/cputable.c
--- linux.orig/arch/ppc/kernel/cputable.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/cputable.c	2002-08-12 22:14:21.000000000 +0000
@@ -189,7 +189,7 @@
     {	/* 7450 2.0 - no doze/nap */
     	0xffffffff, 0x80000200, "7450",
     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
 	COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
 	32, 32,
@@ -198,7 +198,7 @@
     {	/* 7450 2.1 */
     	0xffffffff, 0x80000201, "7450",
     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
 	COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
 	32, 32,
@@ -207,7 +207,7 @@
     {	/* 7450 2.3 and newer */
     	0xffff0000, 0x80000000, "7450",
     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
 	COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
 	32, 32,
@@ -216,7 +216,7 @@
     {	/* 7455 */
     	0xffff0000, 0x80010000, "7455",
     	CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_CAN_NAP |
-	CPU_FTR_L2CR | CPU_FTR_TAU | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
+	CPU_FTR_L2CR | CPU_FTR_ALTIVEC_COMP | CPU_FTR_L3CR |
 	CPU_FTR_HPTE_TABLE | CPU_FTR_SPEC7450,
 	COMMON_PPC | PPC_FEATURE_HAS_ALTIVEC,
 	32, 32,
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- linux.orig/arch/ppc/kernel/entry.S	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/entry.S	2002-08-12 22:14:14.000000000 +0000
@@ -22,7 +22,6 @@
  *	
  */
 
-#include "ppc_asm.h"
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sys.h>
@@ -31,6 +30,8 @@
 #include <asm/page.h>
 #include <asm/mmu.h>
 #include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
 
 #undef SHOW_SYSCALLS
 #undef SHOW_SYSCALLS_TASK
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/error_log.c linux/arch/ppc/kernel/error_log.c
--- linux.orig/arch/ppc/kernel/error_log.c	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/error_log.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,186 +0,0 @@
-/*
- * BK Id: SCCS/s.error_log.c 1.6 05/17/01 18:14:21 cort
- */
-/*
- *  arch/ppc/kernel/error_log.c
- *  
- *  Copyright (c) 2000 Tilmann Bitterberg
- *  (tilmann@bitterberg.de)
- *
- *  Error processing of errors found by rtas even-scan routine
- *  which is done with every heartbeat. (chrp_setup.c)
- */
-
-#include <linux/sched.h>
-
-#include <asm/prom.h>
-
-#include "error_log.h"
-
-/* ****************************************************************** */
-/* 
- * EVENT-SCAN
- * The whole stuff below here doesn't take any action when it found
- * an error, it just prints as much information as possible and 
- * then its up to the user to decide what to do.
- *
- * Returns 0 if no errors were found
- * Returns 1 if there may be more errors
- */
-int ppc_rtas_errorlog_scan(void)
-{
-const char *_errlog_severity[] = {
-#ifdef VERBOSE_ERRORS
-	"No Error\n\t\
-Should require no further information",
-	"Event\n\t\
-This is not really an error, it is an event. I use events\n\t\
-to communicate with RTAS back and forth.",
-	"Warning\n\t\
-Indicates a non-state-losing error, either fully recovered\n\t\
-by RTAS or not needing recovery. Ignore it.",
-	"Error sync\n\t\
-May only be fatal to a certain program or thread. Recovery\n\t\
-and continuation is possible, if I only had a handler for\n\t\
-this. Less serious",
-	"Error\n\t\
-Less serious, but still causing a loss of data and state.\n\t\
-I can't tell you exactly what to do, You have to decide\n\t\
-with help from the target and initiator field, what kind\n\t\
-of further actions may take place.",
-	"Fatal\n\t\
-Represent a permanent hardware failure and I believe this\n\t\
-affects my overall performance and behaviour. I would not\n\t\
-attempt to continue normal operation."
-#else
-	"No Error",
-	"Event",
-	"Warning",
-	"Error sync",
-	"Error",
-	"Fatal"
-#endif /* VERBOSE_ERRORS */
-};
-
-#if 0 /* unused?? */
-const char *_errlog_disposition[] = {
-#ifdef VERBOSE_ERRORS
-	"Fully recovered\n\t\
-There was an error, but it is fully recovered by RTAS.",
-	"Limited recovery\n\t\
-RTAS was able to recover the state of the machine, but some\n\t\
-feature of the machine has been disabled or lost (for example\n\t\
-error checking) or performance may suffer.",
-	"Not recovered\n\t\
-Whether RTAS did not try to recover anything or recovery failed:\n\t\
-HOUSTON, WE HAVE A PROBLEM!"
-#else
-	"Fully recovered",
-	"Limited recovery",
-	"Not recovered"
-#endif /* VERBOSE_ERRORS */
-};
-#endif
-
-const char *_errlog_extended[] = {
-#ifdef VERBOSE_ERRORS
-	"Not present\n\t\
-Sad, the RTAS call didn't return an extended error log.",
-	"Present\n\t\
-The extended log is present and hopefully it contains a lot of\n\t\
-useful information, which leads to the solution of the problem."
-#else
-	"Not present",
-	"Present"
-#endif /* VERBOSE_ERRORS */
-};
-
-const char *_errlog_initiator[] = { 
-	"Unknown or not applicable",
-	"CPU",
-	"PCI",
-	"ISA",
-	"Memory",
-	"Power management"
-};
-
-const char *_errlog_target[] = { 
-	"Unknown or not applicable",
-	"CPU",
-	"PCI",
-	"ISA",
-	"Memory",
-	"Power management"
-};
-	rtas_error_log error_log;
-	char logdata[1024];
-	int error;
-#if 0 /* unused?? */
-	int retries = 0; /* if HW error, try 10 times */
-#endif
-
-	error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log,
-			INTERNAL_ERROR | EPOW_WARNING,
-			0, __pa(logdata), 1024);
-
-	if (error == 1) /* no errors found */
-		return 0;
-
-	if (error == -1) {
-		printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n");
-		return 0;
-	}
-	if (error_log.version != 1)
-		printk(KERN_WARNING "Unknown version (%d), please implement me\n", 
-				error_log.version);
-
-	switch (error_log.disposition) {
-		case DISP_FULLY_RECOVERED:
-			/* there was an error, but everything is fine now */
-			return 0;
-		case DISP_NOT_RECOVERED:
-			printk("We have a really serious Problem!\n");
-		case DISP_LIMITED_RECOVERY:
-			printk("Error classification\n");
-			printk("Severity  : %s\n", 
-					ppc_rtas_errorlog_check_severity (error_log));
-			printk("Initiator : %s\n", 
-					ppc_rtas_errorlog_check_initiator (error_log));
-			printk("Target    : %s\n", 
-					ppc_rtas_errorlog_check_target (error_log));
-			printk("Type      : %s\n", 
-					ppc_rtas_errorlog_check_type (error_log));
-			printk("Ext. log  : %s\n", 
-					ppc_rtas_errorlog_check_extended (error_log));
-			if (error_log.extended)
-				ppc_rtas_errorlog_disect_extended (logdata);
-			return 1;	
-		default:
-			/* nothing */
-			break;
-	}
-	return 0;
-}
-/* ****************************************************************** */
-const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log)
-{
-	const char *_errlog_type[] = {
-		"unknown type",
-		"too many tries failed",
-		"TCE error",
-		"RTAS device failed",
-		"target timed out",
-		"parity error on data",			/* 5 */
-		"parity error on address",
-		"parity error on external cache",
-		"access to invalid address",
-		"uncorrectable ECC error",
-		"corrected ECC error"			/* 10 */
-	};
-	if (error_log.type == TYPE_EPOW) 
-		return "EPOW"; 
-	if (error_log.type >= TYPE_PMGM_POWER_SW_ON)
-		return "PowerMGM Event (not handled right now)";
-	return _errlog_type[error_log.type];
-}
-
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/error_log.h linux/arch/ppc/kernel/error_log.h
--- linux.orig/arch/ppc/kernel/error_log.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/error_log.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,98 +0,0 @@
-/*
- * BK Id: SCCS/s.error_log.h 1.5 05/17/01 18:14:21 cort
- */
-#ifndef __ERROR_LOG_H__
-#define __ERROR_LOG_H__
-
-#define VERBOSE_ERRORS		1 /* Maybe I enlarge the kernel too much */
-#undef VERBOSE_ERRORS
-
-/* Event classes */
-/* XXX: Endianess correct? NOW*/
-#define INTERNAL_ERROR		0x80000000 /* set bit 0 */
-#define EPOW_WARNING		0x40000000 /* set bit 1 */
-#define POWERMGM_EVENTS		0x20000000 /* set bit 2 */
-
-/* event-scan returns */
-#define SEVERITY_FATAL		0x5
-#define SEVERITY_ERROR		0x4
-#define SEVERITY_ERROR_SYNC	0x3
-#define SEVERITY_WARNING	0x2
-#define SEVERITY_EVENT		0x1
-#define SEVERITY_NO_ERROR	0x0
-#define DISP_FULLY_RECOVERED	0x0
-#define DISP_LIMITED_RECOVERY	0x1
-#define DISP_NOT_RECOVERED	0x2
-#define PART_PRESENT		0x0
-#define PART_NOT_PRESENT	0x1
-#define INITIATOR_UNKNOWN	0x0
-#define INITIATOR_CPU		0x1
-#define INITIATOR_PCI		0x2
-#define INITIATOR_ISA		0x3
-#define INITIATOR_MEMORY	0x4
-#define INITIATOR_POWERMGM	0x5
-#define TARGET_UNKNOWN		0x0
-#define TARGET_CPU		0x1
-#define TARGET_PCI		0x2
-#define TARGET_ISA		0x3
-#define TARGET_MEMORY		0x4
-#define TARGET_POWERMGM		0x5
-#define TYPE_RETRY		0x01
-#define TYPE_TCE_ERR		0x02
-#define TYPE_INTERN_DEV_FAIL	0x03
-#define TYPE_TIMEOUT		0x04
-#define TYPE_DATA_PARITY	0x05
-#define TYPE_ADDR_PARITY	0x06
-#define TYPE_CACHE_PARITY	0x07
-#define TYPE_ADDR_INVALID	0x08
-#define TYPE_ECC_UNCORR		0x09
-#define TYPE_ECC_CORR		0x0a
-#define TYPE_EPOW		0x40
-/* I don't add PowerMGM events right now, this is a different topic */ 
-#define TYPE_PMGM_POWER_SW_ON	0x60
-#define TYPE_PMGM_POWER_SW_OFF	0x61
-#define TYPE_PMGM_LID_OPEN	0x62
-#define TYPE_PMGM_LID_CLOSE	0x63
-#define TYPE_PMGM_SLEEP_BTN	0x64
-#define TYPE_PMGM_WAKE_BTN	0x65
-#define TYPE_PMGM_BATTERY_WARN	0x66
-#define TYPE_PMGM_BATTERY_CRIT	0x67
-#define TYPE_PMGM_SWITCH_TO_BAT	0x68
-#define TYPE_PMGM_SWITCH_TO_AC	0x69
-#define TYPE_PMGM_KBD_OR_MOUSE	0x6a
-#define TYPE_PMGM_ENCLOS_OPEN	0x6b
-#define TYPE_PMGM_ENCLOS_CLOSED	0x6c
-#define TYPE_PMGM_RING_INDICATE	0x6d
-#define TYPE_PMGM_LAN_ATTENTION	0x6e
-#define TYPE_PMGM_TIME_ALARM	0x6f
-#define TYPE_PMGM_CONFIG_CHANGE	0x70
-#define TYPE_PMGM_SERVICE_PROC	0x71
-
-typedef struct _rtas_error_log {
-	unsigned long version:8;		/* Architectural version */
-	unsigned long severity:3;		/* Severity level of error */
-	unsigned long disposition:2;		/* Degree of recovery */
-	unsigned long extended:1;		/* extended log present? */
-	unsigned long /* reserved */ :2;	/* Reserved for future use */
-	unsigned long initiator:4;		/* Initiator of event */
-	unsigned long target:4;			/* Target of failed operation */
-	unsigned long type:8;			/* General event or error*/
-	unsigned long extended_log_length:32;	/* length in bytes */
-} rtas_error_log;
-
-/* ****************************************************************** */
-#define ppc_rtas_errorlog_check_severity(x) \
-	(_errlog_severity[x.severity])
-#define ppc_rtas_errorlog_check_target(x) \
-	(_errlog_target[x.target])
-#define ppc_rtas_errorlog_check_initiator(x) \
-	(_errlog_initiator[x.initiator])
-#define ppc_rtas_errorlog_check_extended(x) \
-	(_errlog_extended[x.extended])
-#define ppc_rtas_errorlog_disect_extended(x) \
-	do { /* implement me */ } while(0)
-extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log);
-extern int ppc_rtas_errorlog_scan(void);
-
-
-#endif /* __ERROR_LOG_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/galaxy_pci.c linux/arch/ppc/kernel/galaxy_pci.c
--- linux.orig/arch/ppc/kernel/galaxy_pci.c	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/galaxy_pci.c	2002-08-12 22:14:21.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.galaxy_pci.c 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  *
@@ -27,8 +27,7 @@
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/machdep.h>
-
-#include "pci.h"
+#include <asm/pci-bridge.h>
 
 
 /* Preprocessor Defines */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/gemini_pci.c linux/arch/ppc/kernel/gemini_pci.c
--- linux.orig/arch/ppc/kernel/gemini_pci.c	2001-11-03 01:43:54.000000000 +0000
+++ linux/arch/ppc/kernel/gemini_pci.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,124 +0,0 @@
-/*
- * BK Id: SCCS/s.gemini_pci.c 1.6 10/11/01 08:51:46 trini
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-
-#include <asm/machdep.h>
-#include <asm/gemini.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/pci-bridge.h>
-
-#include "pci.h"
-
-#define pci_config_addr(bus,dev,offset) \
-        (0x80000000 | (bus<<16) | (dev<<8) | offset)
-
-
-int
-gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
-{
-	unsigned long reg;
-	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
-					   (offset & ~(0x3))));
-	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
-{
-	unsigned long reg;
-	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
-					   (offset & ~(0x3))));
-	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
-{
-	*val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
-					    (offset & ~(0x3))));
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
-{
-	unsigned long reg;
-	int shifts = offset & 0x3;
-	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
-					    (offset & ~(0x3)));
-
-	reg = grackle_read(addr);
-	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
-	grackle_write(addr, reg );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
-{
-	unsigned long reg;
-	int shifts = offset & 0x3;
-	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
-					    (offset & ~(0x3)));
-
-	reg = grackle_read(addr);
-	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
-	grackle_write(addr, reg );
-	return PCIBIOS_SUCCESSFUL;
-}
-
-int
-gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
-{
-	grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
-				      (offset & ~(0x3))), val);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops gemini_pci_ops =
-{
-	gemini_pcibios_read_config_byte,
-	gemini_pcibios_read_config_word,
-	gemini_pcibios_read_config_dword,
-	gemini_pcibios_write_config_byte,
-	gemini_pcibios_write_config_word,
-	gemini_pcibios_write_config_dword
-};
-
-void __init gemini_pcibios_fixup(void)
-{
-	int i;
-	struct pci_dev *dev;
-	
-	pci_for_each_dev(dev) {
-		for(i = 0; i < 6; i++) {
-			if (dev->resource[i].flags & IORESOURCE_IO) {
-				dev->resource[i].start |= (0xfe << 24);
-				dev->resource[i].end |= (0xfe << 24);
-			}
-		}
-	}
-}
-
-
-/* The "bootloader" for Synergy boards does none of this for us, so we need to
-   lay it all out ourselves... --Dan */
-void __init gemini_find_bridges(void)
-{
-	struct pci_controller* hose;
-	
-	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
-
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-	hose->ops = &gemini_pci_ops;
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/gemini_prom.S linux/arch/ppc/kernel/gemini_prom.S
--- linux.orig/arch/ppc/kernel/gemini_prom.S	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/gemini_prom.S	1970-01-01 00:00:00.000000000 +0000
@@ -1,99 +0,0 @@
-/*
- * BK Id: SCCS/s.gemini_prom.S 1.5 05/17/01 18:14:21 cort
- */
-/*
- *  arch/ppc/kernel/gemini_prom.S
- *
- *  Not really prom support code (yet), but sort of anti-prom code.  The current
- *  bootloader does a number of things it shouldn't and doesn't do things that it
- *  should.  The stuff in here is mainly a hodge-podge collection of setup code
- *  to get the board up and running.
- *    ---Dan
- */
-
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
-#include <linux/config.h>
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/gemini.h>
-
-#define HID0_ABE (1<<3)
-
-/*
- *  On 750's the MMU is on when Linux is booted, so we need to clear out the
- *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
- *  and turn off the MMU.
- *
- */
-
-_GLOBAL(gemini_prom_init)
-#ifdef CONFIG_SMP
-	/* Since the MMU's on, get stuff in rom space that we'll need */
-	lis	r4,GEMINI_CPUSTAT@h
-	ori	r4,r4,GEMINI_CPUSTAT@l
-	lbz	r5,0(r4)
-	andi.	r5,r5,3
-	mr	r24,r5		/* cpu # used later on */
-#endif
-	mfmsr	r4
-	li	r3,MSR_PR	/* ensure supervisor! */
-	ori	r3,r3,MSR_IR|MSR_DR
-	andc	r4,r4,r3
-	mtmsr	r4
-	isync
-#if 0
-	/* zero out the bats now that the MMU is off */
-prom_no_mmu:	
-	li	r3,0
-        mtspr   IBAT0U,r3
-        mtspr   IBAT0L,r3
-        mtspr   IBAT1U,r3
-        mtspr   IBAT1L,r3
-        mtspr   IBAT2U,r3
-        mtspr   IBAT2L,r3
-        mtspr   IBAT3U,r3
-        mtspr   IBAT3L,r3
-
-        mtspr   DBAT0U,r3
-        mtspr   DBAT0L,r3
-        mtspr   DBAT1U,r3
-        mtspr   DBAT1L,r3
-        mtspr   DBAT2U,r3
-	mtspr   DBAT2L,r3
-        mtspr   DBAT3U,r3
-        mtspr   DBAT3L,r3
-#endif
-
-	/* the bootloader (as far as I'm currently aware) doesn't mess with page
-	   tables, but since we're already here, might as well zap these, too */
-	li	r4,0
-	mtspr	SDR1,r4
-
-	li	r4,16
-	mtctr	r4
-	li	r3,0
-	li	r4,0
-3:	mtsrin	r3,r4
-	addi	r3,r3,1
-	bdnz	3b
-
-#ifdef CONFIG_SMP
-	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
-	   when in SMP.  Not sure yet whether this should stay or leave... */
-	mfspr	r4,HID0
-	ori	r4,r4,HID0_ABE
-	mtspr	HID0,r4
-	sync
-#endif /* CONFIG_SMP */
-	blr
-
-/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
-    branch to 0xfff00100 */
-_GLOBAL(_gemini_reboot)
-	lis	r5,GEMINI_BOOT_INIT@h
-	ori	r5,r5,GEMINI_BOOT_INIT@l
-	li	r6,MSR_IP
-	mtspr	SRR0,r5
-	mtspr	SRR1,r6
-	rfi
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/gemini_setup.c linux/arch/ppc/kernel/gemini_setup.c
--- linux.orig/arch/ppc/kernel/gemini_setup.c	2001-11-16 18:10:08.000000000 +0000
+++ linux/arch/ppc/kernel/gemini_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,584 +0,0 @@
-/*
- * BK Id: SCCS/s.gemini_setup.c 1.14 10/18/01 11:16:28 trini
- */
-/*
- *  linux/arch/ppc/kernel/setup.c
- *
- *  Copyright (C) 1995 Linus Torvalds
- *  Adapted from 'alpha' version by Gary Thomas
- *  Modified by Cort Dougan (cort@cs.nmt.edu)
- *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
- *
- */
-
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/errno.h> 
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <linux/time.h>
-#include <linux/kdev_t.h>
-#include <linux/types.h>
-#include <linux/major.h>
-#include <linux/blk.h>
-#include <linux/console.h>
-#include <linux/seq_file.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/page.h>
-#include <asm/dma.h>
-#include <asm/io.h>
-#include <asm/m48t35.h>
-#include <asm/gemini.h>
-#include <asm/time.h>
-
-#include "local_irq.h"
-#include "open_pic.h"
-
-void gemini_find_bridges(void);
-static int gemini_get_clock_speed(void);
-extern void gemini_pcibios_fixup(void);
-
-static char *gemini_board_families[] = {
-  "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
-};
-static int gemini_board_count = sizeof(gemini_board_families) /
-                                 sizeof(gemini_board_families[0]);
-
-static unsigned int cpu_7xx[16] = {
-	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
-};
-static unsigned int cpu_6xx[16] = {
-	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
-};
-
-/*
- * prom_init is the Gemini version of prom.c:prom_init.  We only need
- * the BSS clearing code, so I copied that out of prom.c.  This is a
- * lot simpler than hacking prom.c so it will build with Gemini. -VAL
- */
-
-#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
-
-unsigned long
-prom_init(void)
-{
-	unsigned long offset = reloc_offset();
-	unsigned long phys;
-	extern char __bss_start, _end;
-
-	/* First zero the BSS -- use memset, some arches don't have
-	 * caches on yet */
-	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
-
- 	/* Default */
- 	phys = offset + KERNELBASE;
-
-	gemini_prom_init();
-
-	return phys;
-}
-
-int
-gemini_show_cpuinfo(struct seq_file *m)
-{
-	unsigned char reg, rev;
-	char *family;
-	unsigned int type;
-
-	reg = readb(GEMINI_FEAT);
-	family = gemini_board_families[((reg>>4) & 0xf)];
-	if (((reg>>4) & 0xf) > gemini_board_count)
-		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
-
-	reg = readb(GEMINI_BREV);
-	type = (reg>>4) & 0xf;
-	rev = reg & 0xf;
-
-	reg = readb(GEMINI_BECO);
-
-	seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
-		   family, type, (rev + 'A'), (reg & 0xf));
-
-	seq_printf(m, "board\t\t: Gemini %s", family);
-	if (type > 9)
-		seq_printf(m, "%c", (type - 10) + 'A');
-	else
-		seq_printf(m, "%d", type);
-
-	seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf));
-
-	seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed());
-
-	return 0;
-}
-
-static u_char gemini_openpic_initsenses[] = {
-	1,
-	1,
-	1,
-	1,
-	0,
-	0,
-	1, /* remainder are level-triggered */
-};
-
-#define GEMINI_MPIC_ADDR (0xfcfc0000)
-#define GEMINI_MPIC_PCI_CFG (0x80005800)
-
-void __init gemini_openpic_init(void)
-{
-
-	OpenPIC_Addr = (volatile struct OpenPIC *)
-		grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
-	OpenPIC_InitSenses = gemini_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
-
-	ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
-}
-
-
-extern unsigned long loops_per_jiffy;
-extern int root_mountflags;
-extern char cmd_line[];
-
-void
-gemini_heartbeat(void)
-{
-	static unsigned long led = GEMINI_LEDBASE+(4*8);
-	static char direction = 8;
-
-	/* We only want to do this on 1 CPU */
-	if (smp_processor_id())
-		return;
-	*(char *)led = 0;
-	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
-	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
-		direction *= -1;
-	led += direction;
-	*(char *)led = 0xff;
-	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
-}
-
-void __init gemini_setup_arch(void)
-{
-	extern char cmd_line[];
-
-
-	loops_per_jiffy = 50000000/HZ;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	/* bootable off CDROM */
-	if (initrd_start)
-		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
-	else
-#endif
-		ROOT_DEV = to_kdev_t(0x0801);
-
-	/* nothing but serial consoles... */
-	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
-
-	printk("Boot arguments: %s\n", cmd_line);
-
-	ppc_md.heartbeat = gemini_heartbeat;
-	ppc_md.heartbeat_reset = HZ/8;
-	ppc_md.heartbeat_count = 1;
-	
-	/* Lookup PCI hosts */
-	gemini_find_bridges();
-	/* take special pains to map the MPIC, since it isn't mapped yet */
-	gemini_openpic_init();
-	/* start the L2 */
-	gemini_init_l2();
-}
-
-
-int
-gemini_get_clock_speed(void)
-{
-	unsigned long hid1, pvr;
-	int clock;
-
-	pvr = mfspr(PVR);
-	hid1 = (mfspr(HID1) >> 28) & 0xf;
-	if (PVR_VER(pvr) == 8 ||
-	    PVR_VER(pvr) == 12)
-		hid1 = cpu_7xx[hid1];
-	else
-		hid1 = cpu_6xx[hid1];
-
-	switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
-
-	case 0:
-	default:
-		clock = (hid1*100)/3;
-		break;
-  
-	case 1:
-		clock = (hid1*125)/3;
-		break;
-  
-	case 2:
-		clock = (hid1*50);
-		break;
-	}
-
-	return clock;
-}
-
-void __init gemini_init_l2(void)
-{
-        unsigned char reg, brev, fam, creg;
-        unsigned long cache;
-        unsigned long pvr;
-
-        reg = readb(GEMINI_L2CFG);
-        brev = readb(GEMINI_BREV);
-        fam = readb(GEMINI_FEAT);
-        pvr = mfspr(PVR);
-
-        switch(PVR_VER(pvr)) {
-
-        case 8:
-                if (reg & 0xc0)
-                        cache = (((reg >> 6) & 0x3) << 28);
-                else
-                        cache = 0x3 << 28;
-
-#ifdef CONFIG_SMP
-                /* Pre-3.0 processor revs had snooping errata.  Leave
-                   their L2's disabled with SMP. -- Dan */
-                if (PVR_CFG(pvr) < 3) {
-                        printk("Pre-3.0 750; L2 left disabled!\n");
-                        return;
-                }
-#endif /* CONFIG_SMP */
-
-                /* Special case: VGM5-B's came before L2 ratios were set on
-                   the board.  Processor speed shouldn't be too high, so
-                   set L2 ratio to 1:1.5.  */
-                if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
-                        reg |= 1;
-
-                /* determine best cache ratio based upon what the board
-                   tells us (which sometimes _may_ not be true) and
-                   the processor speed. */
-                else {
-                        if (gemini_get_clock_speed() > 250)
-                                reg = 2;
-                }
-                break;
-        case 12:
-	{
-		static unsigned long l2_size_val = 0;
-		
-		if (!l2_size_val)
-			l2_size_val = _get_L2CR();
-		cache = l2_size_val;
-                break;
-	}
-        case 4:
-        case 9:
-                creg = readb(GEMINI_CPUSTAT);
-                if (((creg & 0xc) >> 2) != 1)
-                        printk("Dual-604 boards don't support the use of L2\n");
-                else
-                        writeb(1, GEMINI_L2CFG);
-                return;
-        default:
-                printk("Unknown processor; L2 left disabled\n");
-                return;
-        }
-
-        cache |= ((1<<reg) << 25);
-        cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
-        _set_L2CR(0);
-        _set_L2CR(cache | L2CR_L2E);
-
-}
-
-void
-gemini_restart(char *cmd)
-{
-	__cli();
-	/* make a clean restart, not via the MPIC */
-	_gemini_reboot();
-	for(;;);
-}
-
-void
-gemini_power_off(void)
-{
-	for(;;);
-}
-
-void
-gemini_halt(void)
-{
-	gemini_restart(NULL);
-}
-
-void __init gemini_init_IRQ(void)
-{
-	/* gemini has no 8259 */
-	openpic_init(1, 0, 0, -1);
-}
-
-#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
-#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
-
-/* ensure that the RTC is up and running */
-long __init gemini_time_init(void)
-{
-	unsigned char reg;
-
-	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-
-	if ( reg & M48T35_RTC_STOPPED ) {
-		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
-		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
-		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
-	}
-	return 0;
-}
-
-#undef DEBUG_RTC
-
-unsigned long
-gemini_get_rtc_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-	unsigned char reg;
-
-	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
-#ifdef DEBUG_RTC
-	printk("get rtc: reg = %x\n", reg);
-#endif
-  
-	do {
-		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
-		min = gemini_rtc_read(M48T35_RTC_MINUTES);
-		hour = gemini_rtc_read(M48T35_RTC_HOURS);
-		day = gemini_rtc_read(M48T35_RTC_DOM);
-		mon = gemini_rtc_read(M48T35_RTC_MONTH);
-		year = gemini_rtc_read(M48T35_RTC_YEAR);
-	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
-#ifdef DEBUG_RTC
-	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
-	       sec, min, hour, day, mon, year);
-#endif
-
-	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
-
-	BCD_TO_BIN(sec);
-	BCD_TO_BIN(min);
-	BCD_TO_BIN(hour);
-	BCD_TO_BIN(day);
-	BCD_TO_BIN(mon);
-	BCD_TO_BIN(year);
-
-	if ((year += 1900) < 1970)
-		year += 100;
-#ifdef DEBUG_RTC
-	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
-	       sec, min, hour, day, mon, year);
-#endif
-
-	return mktime( year, mon, day, hour, min, sec );
-}
-
-
-int
-gemini_set_rtc_time( unsigned long now )
-{
-	unsigned char reg;
-	struct rtc_time tm;
-
-	to_tm( now, &tm );
-
-	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
-#if DEBUG_RTC
-	printk("set rtc: reg = %x\n", reg);
-#endif
-  
-	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
-#if DEBUG_RTC
-	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
-	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
-#endif
-  
-	tm.tm_year -= 1900;
-	BIN_TO_BCD(tm.tm_sec);
-	BIN_TO_BCD(tm.tm_min);
-	BIN_TO_BCD(tm.tm_hour);
-	BIN_TO_BCD(tm.tm_mon);
-	BIN_TO_BCD(tm.tm_mday);
-	BIN_TO_BCD(tm.tm_year);
-#ifdef DEBUG_RTC
-	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
-	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
-#endif
-
-	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
-	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
-	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
-	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
-	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
-	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
-
-	/* done writing */
-	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
-
-	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
-		time_state = TIME_OK;
-  
-	return 0;
-}
-
-/*  use the RTC to determine the decrementer count */
-void __init gemini_calibrate_decr(void)
-{
-	int freq, divisor;
-	unsigned char reg;
-
-	/* determine processor bus speed */
-	reg = readb(GEMINI_BSTAT);
-
-	switch(((reg & 0x0c)>>2)&0x3) {
-	case 0:
-	default:
-		freq = 66667;
-		break;
-	case 1:
-		freq = 83000;
-		break;
-	case 2:
-		freq = 100000;
-		break;
-	}
-
-	freq *= 1000;
-	divisor = 4;
-	tb_ticks_per_jiffy = freq / HZ / divisor;
-	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
-}
-
-unsigned long __init gemini_find_end_of_memory(void)
-{
-	unsigned long total;
-	unsigned char reg;
-
-	reg = readb(GEMINI_MEMCFG);
-	total = ((1<<((reg & 0x7) - 1)) *
-		 (8<<((reg >> 3) & 0x7)));
-	total *= (1024*1024);
-	return total;
-}
-
-static void __init
-gemini_map_io(void)
-{
-	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
-	io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
-}
-
-#ifdef CONFIG_SMP
-static int
-smp_gemini_probe(void)
-{
-	int i, nr;
-
-        nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
-	if (nr == 0)
-		nr = 4;
-
-	if (nr > 1) {
-		openpic_request_IPIs();
-		for (i = 1; i < nr; ++i)
-			smp_hw_index[i] = i;
-	}
-
-	return nr;
-}
-
-static void
-smp_gemini_kick_cpu(int nr)
-{
-	openpic_reset_processor_phys(1 << nr);
-	openpic_reset_processor_phys(0);
-}
-
-static void
-smp_gemini_setup_cpu(int cpu_nr)
-{
-	if (OpenPIC_Addr)
-		do_openpic_setup_cpu();
-	if (cpu_nr > 0)
-		gemini_init_l2();
-}
-
-static struct smp_ops_t gemini_smp_ops = {
-	smp_openpic_message_pass,
-	smp_gemini_probe,
-	smp_gemini_kick_cpu,
-	smp_gemini_setup_cpu,
-};
-#endif /* CONFIG_SMP */
-
-void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
-			  unsigned long r6, unsigned long r7)
-{
-	int i;
-
-	for(i = 0; i < GEMINI_LEDS; i++)
-		gemini_led_off(i);
- 
-	ISA_DMA_THRESHOLD = 0;
-	DMA_MODE_READ = 0;
-	DMA_MODE_WRITE = 0;
-
-#ifdef CONFIG_BLK_DEV_INITRD
-	if ( r4 )
-	{
-		initrd_start = r4 + KERNELBASE;
-		initrd_end = r5 + KERNELBASE;
-	}
-#endif
-
-	ppc_md.setup_arch = gemini_setup_arch;
-	ppc_md.show_cpuinfo = gemini_show_cpuinfo;
-	ppc_md.irq_cannonicalize = NULL;
-	ppc_md.init_IRQ = gemini_init_IRQ;
-	ppc_md.get_irq = openpic_get_irq;
-	ppc_md.init = NULL;
-
-	ppc_md.restart = gemini_restart;
-	ppc_md.power_off = gemini_power_off;
-	ppc_md.halt = gemini_halt;
-
-	ppc_md.time_init = gemini_time_init;
-	ppc_md.set_rtc_time = gemini_set_rtc_time;
-	ppc_md.get_rtc_time = gemini_get_rtc_time;
-	ppc_md.calibrate_decr = gemini_calibrate_decr;
-
-	ppc_md.find_end_of_memory = gemini_find_end_of_memory;
-	ppc_md.setup_io_mappings = gemini_map_io;
-
-	/* no keyboard/mouse/video stuff yet.. */
-	ppc_md.kbd_setkeycode = NULL;
-	ppc_md.kbd_getkeycode = NULL;
-	ppc_md.kbd_translate = NULL;
-	ppc_md.kbd_unexpected_up = NULL;
-	ppc_md.kbd_leds = NULL;
-	ppc_md.kbd_init_hw = NULL;
-	ppc_md.ppc_kbd_sysrq_xlate = NULL;
-	ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
-
-#ifdef CONFIG_SMP
-	ppc_md.smp_ops = &gemini_smp_ops;
-#endif /* CONFIG_SMP */
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- linux.orig/arch/ppc/kernel/head.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/head.S	2002-08-12 22:14:00.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.head.S 1.43 06/25/02 17:24:29 benh
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  *  PowerPC version 
@@ -26,13 +26,14 @@
  */
 
 #include <linux/config.h>
-#include "ppc_asm.h"
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/mmu.h>
 #include <asm/pgtable.h>
 #include <asm/cputable.h>
 #include <asm/cache.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/head_4xx.S linux/arch/ppc/kernel/head_4xx.S
--- linux.orig/arch/ppc/kernel/head_4xx.S	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/head_4xx.S	2002-08-12 22:14:18.000000000 +0000
@@ -34,7 +34,8 @@
 #include <asm/pgtable.h>
 #include <asm/mmu.h>
 
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
 
 
 /* Preprocessor Defines */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- linux.orig/arch/ppc/kernel/head_8xx.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/head_8xx.S	2002-08-12 22:14:19.000000000 +0000
@@ -24,7 +24,6 @@
  *	
  */
 
-#include "ppc_asm.h"
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <linux/config.h>
@@ -32,6 +31,8 @@
 #include <asm/cache.h>
 #include <asm/pgtable.h>
 #include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
 
 	.text
 	.globl	_stext
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/i8259.c linux/arch/ppc/kernel/i8259.c
--- linux.orig/arch/ppc/kernel/i8259.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/i8259.c	2002-08-12 22:14:18.000000000 +0000
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <asm/io.h>
-#include "i8259.h"
+#include <asm/i8259.h>
 
 static volatile char *pci_intack; /* RO, gives us the irq vector */
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/i8259.h linux/arch/ppc/kernel/i8259.h
--- linux.orig/arch/ppc/kernel/i8259.h	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/i8259.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-/*
- * BK Id: SCCS/s.i8259.h 1.8 12/19/01 09:45:54 trini
- */
-
-#ifndef _PPC_KERNEL_i8259_H
-#define _PPC_KERNEL_i8259_H
-
-#include "local_irq.h"
-
-extern struct hw_interrupt_type i8259_pic;
-
-void i8259_init(long);
-int i8259_irq(void);
-int i8259_poll(void);
-
-#endif /* _PPC_KERNEL_i8259_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/indirect_pci.c linux/arch/ppc/kernel/indirect_pci.c
--- linux.orig/arch/ppc/kernel/indirect_pci.c	2001-09-08 19:38:41.000000000 +0000
+++ linux/arch/ppc/kernel/indirect_pci.c	2002-08-12 22:14:04.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.indirect_pci.c 1.10 09/08/01 15:47:42 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * Support for indirect PCI bridges.
@@ -24,8 +24,6 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 
-#include "pci.h"
-
 #define cfg_read(val, addr, type, op)	*val = op((type)(addr))
 #define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- linux.orig/arch/ppc/kernel/irq.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/irq.c	2002-08-12 22:14:10.000000000 +0000
@@ -63,8 +63,6 @@
 #include <asm/amigappc.h>
 #include <asm/ptrace.h>
 
-#include "local_irq.h"
-
 extern atomic_t ipi_recv;
 extern atomic_t ipi_sent;
 void enable_irq(unsigned int irq_nr);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/l2cr.S linux/arch/ppc/kernel/l2cr.S
--- linux.orig/arch/ppc/kernel/l2cr.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/l2cr.S	2002-08-12 22:14:22.000000000 +0000
@@ -42,7 +42,7 @@
 */
 #include <asm/processor.h>
 #include <asm/cputable.h>
-#include "ppc_asm.h"
+#include <asm/ppc_asm.h>
 
 /* Usage:
 	
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/local_irq.h linux/arch/ppc/kernel/local_irq.h
--- linux.orig/arch/ppc/kernel/local_irq.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/local_irq.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,22 +0,0 @@
-/*
- * BK Id: SCCS/s.local_irq.h 1.7 05/17/01 18:14:21 cort
- */
-
-#ifndef _PPC_KERNEL_LOCAL_IRQ_H
-#define _PPC_KERNEL_LOCAL_IRQ_H
-
-#include <linux/kernel_stat.h>
-#include <linux/interrupt.h>
-#include <linux/cache.h>
-#include <linux/spinlock.h>
-#include <linux/irq.h>
-
-void ppc_irq_dispatch_handler(struct pt_regs *regs, int irq);
-
-#define NR_MASK_WORDS	((NR_IRQS + 31) / 32)
-
-extern int ppc_spurious_interrupts;
-extern int ppc_second_irq;
-extern struct irqaction *ppc_irq_action[NR_IRQS];
-
-#endif /* _PPC_KERNEL_LOCAL_IRQ_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c
--- linux.orig/arch/ppc/kernel/m8260_setup.c	2001-11-16 18:10:08.000000000 +0000
+++ linux/arch/ppc/kernel/m8260_setup.c	2002-08-12 22:14:20.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.m8260_setup.c 1.30 11/13/01 21:26:07 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -45,8 +45,9 @@
 #include <asm/mpc8260.h>
 #include <asm/immap_8260.h>
 #include <asm/machdep.h>
-
+#include <asm/bootinfo.h>
 #include <asm/time.h>
+
 #include "ppc8260_pic.h"
 
 static int m8260_set_rtc_time(unsigned long time);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- linux.orig/arch/ppc/kernel/m8xx_setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/m8xx_setup.c	2002-08-12 22:14:17.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.m8xx_setup.c 1.40 11/13/01 21:26:07 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  *
  *  linux/arch/ppc/kernel/setup.c
  *
@@ -43,8 +43,9 @@
 #include <asm/mpc8xx.h>
 #include <asm/8xx_immap.h>
 #include <asm/machdep.h>
-
+#include <asm/bootinfo.h>
 #include <asm/time.h>
+
 #include "ppc8xx_pic.h"
 
 static int m8xx_set_rtc_time(unsigned long time);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- linux.orig/arch/ppc/kernel/misc.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/misc.S	2002-08-12 22:14:15.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.misc.S 1.44 06/25/02 17:24:30 benh
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * This file contains miscellaneous low-level functions.
@@ -23,7 +23,9 @@
 #include <asm/page.h>
 #include <asm/cache.h>
 #include <asm/cputable.h>
-#include "ppc_asm.h"
+#include <asm/mmu.h>
+#include <asm/ppc_asm.h>
+#include "ppc_defs.h"
 
 	.text
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/oak_setup.c linux/arch/ppc/kernel/oak_setup.c
--- linux.orig/arch/ppc/kernel/oak_setup.c	2001-11-16 18:10:08.000000000 +0000
+++ linux/arch/ppc/kernel/oak_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,297 +0,0 @@
-/*
- * BK Id: SCCS/s.oak_setup.c 1.12 11/13/01 21:26:07 paulus
- */
-/*
- *
- *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: oak_setup.c
- *
- *    Description:
- *      Architecture- / platform-specific boot-time initialization code for
- *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- *      <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-#include <linux/seq_file.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include <asm/time.h>
-#include "oak_setup.h"
-
-
-
-
-
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init oak_init()
- *
- * Description:
- *   This routine...
- *
- * Input(s):
- *   r3 - Optional pointer to a board information structure.
- *   r4 - Optional pointer to the physical starting address of the init RAM
- *        disk.
- *   r5 - Optional pointer to the physical ending address of the init RAM
- *        disk.
- *   r6 - Optional pointer to the physical starting address of any kernel
- *        command-line parameters.
- *   r7 - Optional pointer to the physical ending address of any kernel
- *        command-line parameters.
- *
- * Output(s):
- *   N/A
- *
- * Returns:
- *   N/A
- *
- */
-void __init
-platform_init(unsigned long r3, unsigned long r4, unsigned long r5, 
-	      unsigned long r6, unsigned long r7)
-{
-	/*
-	 * If we were passed in a board information, copy it into the
-	 * residual data area.
-	 */
-	if (r3) {
-		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
-	}
-
-#if defined(CONFIG_BLK_DEV_INITRD)
-	/*
-	 * If the init RAM disk has been configured in, and there's a valid
-	 * starting address for it, set it up.
-	 */
-	if (r4) {
-		initrd_start = r4 + KERNELBASE;
-		initrd_end = r5 + KERNELBASE;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	/* Copy the kernel command line arguments to a safe place. */
-
-	if (r6) {
- 		*(char *)(r7 + KERNELBASE) = 0;
-		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
-	}
-
-	/* Initialize machine-dependency vectors */
-
-	ppc_md.setup_arch	 	= oak_setup_arch;
-	ppc_md.show_percpuinfo	 	= oak_show_percpuinfo;
-	ppc_md.irq_cannonicalize 	= NULL;
-	ppc_md.init_IRQ		 	= oak_init_IRQ;
-	ppc_md.get_irq		 	= oak_get_irq;
-	ppc_md.init		 	= NULL;
-
-	ppc_md.restart		 	= oak_restart;
-	ppc_md.power_off	 	= oak_power_off;
-	ppc_md.halt		 	= oak_halt;
-
-	ppc_md.time_init	 	= oak_time_init;
-	ppc_md.set_rtc_time	 	= oak_set_rtc_time;
-	ppc_md.get_rtc_time	 	= oak_get_rtc_time;
-	ppc_md.calibrate_decr	 	= oak_calibrate_decr;
-
-	ppc_md.kbd_setkeycode    	= NULL;
-	ppc_md.kbd_getkeycode    	= NULL;
-	ppc_md.kbd_translate     	= NULL;
-	ppc_md.kbd_unexpected_up 	= NULL;
-	ppc_md.kbd_leds          	= NULL;
-	ppc_md.kbd_init_hw       	= NULL;
-	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
-}
-
-/*
- * Document me.
- */
-void __init
-oak_setup_arch(void)
-{
-	/* XXX - Implement me */
-}
-
-/*
- * int oak_show_percpuinfo()
- *
- * Description:
- *   This routine pretty-prints the platform's internal CPU and bus clock
- *   frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- *  *buffer - Buffer into which CPU and bus clock frequencies are to be
- *            printed.
- *
- * Output(s):
- *  *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
- *   on error.
- */
-int
-oak_show_percpuinfo(struct seq_file *m, int i)
-{
-	bd_t *bp = (bd_t *)__res;
-
-	seq_printf(m, "clock\t\t: %dMHz\n"
-		   "bus clock\t\t: %dMHz\n",
-		   bp->bi_intfreq / 1000000,
-		   bp->bi_busfreq / 1000000);
-
-	return 0;
-}
-
-/*
- * Document me.
- */
-void __init
-oak_init_IRQ(void)
-{
-	int i;
-
-	ppc4xx_pic_init();
-
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc[i].handler = ppc4xx_pic;
-	}
-
-	return;
-}
-
-/*
- * Document me.
- */
-int
-oak_get_irq(struct pt_regs *regs)
-{
-	return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-oak_restart(char *cmd)
-{
-	abort();
-}
-
-/*
- * Document me.
- */
-void
-oak_power_off(void)
-{
-	oak_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-oak_halt(void)
-{
-	oak_restart(NULL);
-}
-
-/*
- * Document me.
- */
-long __init
-oak_time_init(void)
-{
-	/* XXX - Implement me */
-	return 0;
-}
-
-/*
- * Document me.
- */
-int __init
-oak_set_rtc_time(unsigned long time)
-{
-	/* XXX - Implement me */
-
-	return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-oak_get_rtc_time(void)
-{
-	/* XXX - Implement me */
-
-	return (0);
-}
-
-/*
- * void __init oak_calibrate_decr()
- *
- * Description:
- *   This routine retrieves the internal processor frequency from the board
- *   information structure, sets up the kernel timer decrementer based on
- *   that value, enables the 403 programmable interval timer (PIT) and sets
- *   it up for auto-reload.
- *
- * Input(s):
- *   N/A
- *
- * Output(s):
- *   N/A
- *
- * Returns:
- *   N/A
- *
- */
-void __init
-oak_calibrate_decr(void)
-{
-	unsigned int freq;
-	bd_t *bip = (bd_t *)__res;
-
-	freq = bip->bi_intfreq;
-
-	decrementer_count = freq / HZ;
-	count_period_num = 1;
-	count_period_den = freq;
-
-	/* Enable the PIT and set auto-reload of its value */
-
-	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
-	/* Clear any pending timer interrupts */
-
-	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/oak_setup.h linux/arch/ppc/kernel/oak_setup.h
--- linux.orig/arch/ppc/kernel/oak_setup.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/oak_setup.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,53 +0,0 @@
-/*
- * BK Id: SCCS/s.oak_setup.h 1.5 05/17/01 18:14:21 cort
- */
-/*
- *
- *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: oak_setup.h
- *
- *    Description:
- *      Architecture- / platform-specific boot-time initialization code for
- *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
- *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- *      <dan@netx4.com>.
- *
- */
-
-#ifndef	__OAK_SETUP_H__
-#define	__OAK_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char	 __res[sizeof(bd_t)];
-
-extern void		 oak_init(unsigned long r3,
-				  unsigned long ird_start,
-				  unsigned long ird_end,
-				  unsigned long cline_start,
-				  unsigned long cline_end);
-extern void		 oak_setup_arch(void);
-extern int		 oak_setup_residual(char *buffer);
-extern void		 oak_init_IRQ(void);
-extern int		 oak_get_irq(struct pt_regs *regs);
-extern void		 oak_restart(char *cmd);
-extern void		 oak_power_off(void);
-extern void		 oak_halt(void);
-extern void		 oak_time_init(void);
-extern int		 oak_set_rtc_time(unsigned long now);
-extern unsigned long	 oak_get_rtc_time(void);
-extern void		 oak_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __OAK_SETUP_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/open_pic.c linux/arch/ppc/kernel/open_pic.c
--- linux.orig/arch/ppc/kernel/open_pic.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/open_pic.c	2002-08-12 22:14:22.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.open_pic.c 1.33 12/19/01 09:45:54 trini
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  *  arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling
@@ -17,18 +17,16 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/init.h>
 #include <asm/ptrace.h>
 #include <asm/signal.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/prom.h>
 #include <asm/sections.h>
+#include <asm/open_pic.h>
+#include <asm/i8259.h>
 
-#include "local_irq.h"
-#include "open_pic.h"
 #include "open_pic_defs.h"
-#include "i8259.h"
 
 void* OpenPIC_Addr;
 static volatile struct OpenPIC *OpenPIC = NULL;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/open_pic.h linux/arch/ppc/kernel/open_pic.h
--- linux.orig/arch/ppc/kernel/open_pic.h	2001-11-03 01:43:54.000000000 +0000
+++ linux/arch/ppc/kernel/open_pic.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,68 +0,0 @@
-/*
- * BK Id: SCCS/s.open_pic.h 1.14 10/11/01 12:09:12 trini
- */
-/*
- *  arch/ppc/kernel/open_pic.h -- OpenPIC Interrupt Handling
- *
- *  Copyright (C) 1997 Geert Uytterhoeven
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- *  
- */
-
-#ifndef _PPC_KERNEL_OPEN_PIC_H
-#define _PPC_KERNEL_OPEN_PIC_H
-
-#include <linux/config.h>
-
-#define OPENPIC_SIZE	0x40000
-
-/*
- *  Non-offset'ed vector numbers
- */
-
-#define OPENPIC_VEC_TIMER	64	/* and up */
-#define OPENPIC_VEC_IPI		72	/* and up */
-#define OPENPIC_VEC_SPURIOUS	127
-
-/* OpenPIC IRQ controller structure */
-extern struct hw_interrupt_type open_pic;
-
-/* OpenPIC IPI controller structure */
-#ifdef CONFIG_SMP
-extern struct hw_interrupt_type open_pic_ipi;
-#endif /* CONFIG_SMP */
-
-extern u_int OpenPIC_NumInitSenses;
-extern u_char *OpenPIC_InitSenses;
-extern void* OpenPIC_Addr;
-
-/* Exported functions */
-extern void openpic_init(int, int, unsigned char *, int);
-extern u_int openpic_irq(void);
-extern void openpic_eoi(void);
-extern void openpic_request_IPIs(void);
-extern void do_openpic_setup_cpu(void);
-extern int openpic_get_irq(struct pt_regs *regs);
-extern void openpic_reset_processor_phys(u_int cpumask);
-extern void openpic_setup_ISU(int isu_num, unsigned long addr);
-extern void openpic_cause_IPI(u_int ipi, u_int cpumask);
-extern void smp_openpic_message_pass(int target, int msg, unsigned long data,
-				     int wait);
-
-extern inline int openpic_to_irq(int irq)
-{
-	/* IRQ 0 usually means 'disabled'.. don't mess with it 
-	 * exceptions to this (sandpoint maybe?) 
-	 * shouldn't use openpic_to_irq 
-	 */
-	if (irq != 0){
-		return irq += NUM_8259_INTERRUPTS;
-	} else {
-		return 0;
-	}
-}
-/*extern int open_pic_irq_offset;*/
-#endif /* _PPC_KERNEL_OPEN_PIC_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- linux.orig/arch/ppc/kernel/pci.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/pci.c	2002-08-12 22:14:19.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pci.c 1.43 05/08/02 15:01:15 benh
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * Common pmac/prep/chrp pci routines. -- Cort
@@ -21,15 +21,11 @@
 #include <asm/prom.h>
 #include <asm/sections.h>
 #include <asm/pci-bridge.h>
-#include <asm/residual.h>
 #include <asm/byteorder.h>
 #include <asm/irq.h>
-#include <asm/gg2.h>
 #include <asm/uaccess.h>
 
-#include "pci.h"
-
-#define DEBUG
+#undef DEBUG
 
 #ifdef DEBUG
 #define DBG(x...) printk(x)
@@ -840,12 +836,6 @@
 		ppc_md.pcibios_after_init();
 }
 
-int __init
-pcibios_assign_all_busses(void)
-{
-	return pci_assign_all_busses;
-}
-
 void __init
 pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
 {
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_backlight.c linux/arch/ppc/kernel/pmac_backlight.c
--- linux.orig/arch/ppc/kernel/pmac_backlight.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_backlight.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,150 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_backlight.c 1.10 12/01/01 20:09:06 benh
- */
-/*
- * Miscellaneous procedures for dealing with the PowerMac hardware.
- * Contains support for the backlight.
- * 
- *   Copyright (C) 2000 Benjamin Herrenschmidt
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/reboot.h>
-#include <linux/nvram.h>
-#include <asm/sections.h>
-#include <asm/ptrace.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-#include <asm/backlight.h>
-
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-static struct backlight_controller *backlighter = NULL;
-static void* backlighter_data = NULL;
-static int backlight_autosave = 0;
-static int backlight_level = BACKLIGHT_MAX;
-static int backlight_enabled = 1;
-
-void __pmac
-register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
-{
-	struct device_node* bk_node;
-	char *prop;
-	int valid = 0;
-
-	bk_node = find_devices("backlight");
-	
-#ifdef CONFIG_ADB_PMU
-	/* Special case for the old PowerBook since I can't test on it */
-	backlight_autosave = machine_is_compatible("AAPL,3400/2400")
-		|| machine_is_compatible("AAPL,3500");
-	if ((backlight_autosave
-	     || machine_is_compatible("AAPL,PowerBook1998")
-	     || machine_is_compatible("PowerBook1,1"))
-	    && !strcmp(type, "pmu"))
-		valid = 1;
-#endif
-	if (bk_node) {
-		prop = get_property(bk_node, "backlight-control", NULL);
-		if (prop && !strncmp(prop, type, strlen(type)))
-			valid = 1;
-	}
-	if (!valid)
-		return;
-	backlighter = ctrler;
-	backlighter_data = data;
-	
-	if (bk_node && !backlight_autosave)
-		prop = get_property(bk_node, "bklt", NULL);
-	else
-		prop = NULL;
-	if (prop) {
-		backlight_level = ((*prop)+1) >> 1;
-		if (backlight_level > BACKLIGHT_MAX)
-			backlight_level = BACKLIGHT_MAX;
-	}
-	
-#ifdef CONFIG_ADB_PMU
-	if (backlight_autosave) {
-		struct adb_request req;
-		pmu_request(&req, NULL, 2, 0xd9, 0);
-		while (!req.complete)
-			pmu_poll();
-		backlight_level = req.reply[0] >> 4;
-	}
-#endif
-	if (!backlighter->set_enable(1, backlight_level, data))
-		backlight_enabled = 1;
-
-	printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n",
-		type, backlight_level);
-}
-
-void __pmac
-unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
-{
-	/* We keep the current backlight level (for now) */
-	if (ctrler == backlighter && data == backlighter_data)
-		backlighter = NULL;
-}
-
-int __pmac
-set_backlight_enable(int enable)
-{
-	int rc;
-	
-	if (!backlighter)
-		return -ENODEV;
-	rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
-	if (!rc)
-		backlight_enabled = enable;
-	return rc;
-}
-
-int __pmac
-get_backlight_enable(void)
-{
-	if (!backlighter)
-		return -ENODEV;
-	return backlight_enabled;
-}
-
-int __pmac
-set_backlight_level(int level)
-{
-	int rc = 0;
-	
-	if (!backlighter)
-		return -ENODEV;
-	if (level < BACKLIGHT_MIN)
-		level = BACKLIGHT_OFF;
-	if (level > BACKLIGHT_MAX)
-		level = BACKLIGHT_MAX;
-	if (backlight_enabled)
-		rc = backlighter->set_level(level, backlighter_data);
-	if (!rc)
-		backlight_level = level;
-	if (!rc && !backlight_autosave) {
-		level <<=1;
-		if (level & 0x10)
-			level |= 0x01;
-		// -- todo: save to property "bklt"
-	}
-	return rc;
-}
-
-int __pmac
-get_backlight_level(void)
-{
-	if (!backlighter)
-		return -ENODEV;
-	return backlight_level;
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_feature.c linux/arch/ppc/kernel/pmac_feature.c
--- linux.orig/arch/ppc/kernel/pmac_feature.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_feature.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,2139 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- *  arch/ppc/kernel/pmac_feature.c
- *
- *  Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
- *                          Ben. Herrenschmidt (benh@kernel.crashing.org)
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *  
- *  TODO: 
- *  
- *   - Replace mdelay with some schedule loop if possible
- *   - Shorten some obfuscated delays on some routines (like modem
- *     power)
- *
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/spinlock.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-#include <asm/sections.h>
-#include <asm/errno.h>
-#include <asm/ohare.h>
-#include <asm/heathrow.h>
-#include <asm/keylargo.h>
-#include <asm/uninorth.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/dbdma.h>
-
-#undef DEBUG_FEATURE
-
-#ifdef DEBUG_FEATURE
-#define DBG(fmt,...) printk(KERN_DEBUG fmt)
-#else
-#define DBG(fmt,...)
-#endif
-
-/* Exported from arch/ppc/kernel/idle.c */
-extern unsigned long powersave_nap;
-
-/*
- * We use a single global lock to protect accesses. Each driver has
- * to take care of it's own locking
- */
-static spinlock_t feature_lock  __pmacdata = SPIN_LOCK_UNLOCKED;
-
-#define LOCK(flags)	spin_lock_irqsave(&feature_lock, flags);
-#define UNLOCK(flags)	spin_unlock_irqrestore(&feature_lock, flags);
-
-/*
- * Helper functions regarding the various flavors of mac-io
- */
- 
-#define MAX_MACIO_CHIPS		2
-
-enum {
-	macio_unknown = 0,
-	macio_grand_central,
-	macio_ohare,
-	macio_ohareII,
-	macio_heathrow,
-	macio_gatwick,
-	macio_paddington,
-	macio_keylargo,
-	macio_pangea
-};
-
-static const char* macio_names[] __pmacdata = 
-{
-	"Unknown",
-	"Grand Central",
-	"OHare",
-	"OHareII",
-	"Heathrow",
-	"Gatwick",
-	"Paddington",
-	"Keylargo",
-	"Pangea"
-};
-
-static struct macio_chip
-{
-	struct device_node*	of_node;
-	int			type;
-	int			rev;
-	volatile u32*		base;
-	unsigned long		flags;
-} macio_chips[MAX_MACIO_CHIPS]  __pmacdata;
-
-#define MACIO_FLAG_SCCA_ON	0x00000001
-#define MACIO_FLAG_SCCB_ON	0x00000002
-#define MACIO_FLAG_SCC_LOCKED	0x00000004
-#define MACIO_FLAG_AIRPORT_ON	0x00000010
-#define MACIO_FLAG_FW_SUPPORTED	0x00000020
-
-static struct macio_chip* __pmac
-macio_find(struct device_node* child, int type)
-{
-	while(child) {
-		int	i;
-	
-		for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
-			if (child == macio_chips[i].of_node &&
-			    (!type || macio_chips[i].type == type))
-				return &macio_chips[i];
-		child = child->parent;
-	}
-	return NULL;
-}
-
-#define MACIO_FCR32(macio, r)	((macio)->base + ((r) >> 2))
-#define MACIO_FCR8(macio, r)	(((volatile u8*)((macio)->base)) + (r))
-
-#define MACIO_IN32(r)		(in_le32(MACIO_FCR32(macio,r)))
-#define MACIO_OUT32(r,v)	(out_le32(MACIO_FCR32(macio,r), (v)))
-#define MACIO_BIS(r,v)		(MACIO_OUT32((r), MACIO_IN32(r) | (v)))
-#define MACIO_BIC(r,v)		(MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
-#define MACIO_IN8(r)		(in_8(MACIO_FCR8(macio,r)))
-#define MACIO_OUT8(r,v)		(out_8(MACIO_FCR8(macio,r), (v)))
-
-/*
- * Uninorth reg. access. Note that Uni-N regs are big endian
- */
- 
-#define UN_REG(r)	(uninorth_base + ((r) >> 2))
-#define UN_IN(r)	(in_be32(UN_REG(r)))
-#define UN_OUT(r,v)	(out_be32(UN_REG(r), (v)))
-#define UN_BIS(r,v)	(UN_OUT((r), UN_IN(r) | (v)))
-#define UN_BIC(r,v)	(UN_OUT((r), UN_IN(r) & ~(v)))
-
-static struct device_node* uninorth_node __pmacdata;
-static u32* uninorth_base __pmacdata;
-static u32 uninorth_rev __pmacdata;
-
-
-/*
- * For each motherboard family, we have a table of functions pointers
- * that handle the various features.
- */
-
-typedef int (*feature_call)(struct device_node* node, int param, int value);
-
-struct feature_table_entry {
-	unsigned int	selector;	
-	feature_call	function;
-};
-
-struct pmac_mb_def
-{
-	const char*			model_string;
-	const char*			model_name;
-	int				model_id;
-	struct feature_table_entry* 	features;
-	unsigned long			board_flags;
-};
-static struct pmac_mb_def pmac_mb __pmacdata;
-
-/*
- * Here are the chip specific feature functions
- */
-
-static inline int __pmac
-simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, type);
-	if (!macio)
-		return -ENODEV;
-	LOCK(flags);
-	if (value)
-		MACIO_BIS(reg, mask);
-	else
-		MACIO_BIC(reg, mask);
-	(void)MACIO_IN32(reg);
-	UNLOCK(flags);
-
-	return 0;
-}
-
-static int __pmac
-ohare_htw_scc_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		chan_mask;
-	unsigned long		fcr;
-	unsigned long		flags;
-	int			htw, trans;
-	unsigned long		rmask;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	if (!strcmp(node->name, "ch-a"))
-		chan_mask = MACIO_FLAG_SCCA_ON;
-	else if (!strcmp(node->name, "ch-b"))
-		chan_mask = MACIO_FLAG_SCCB_ON;
-	else
-		return -ENODEV;
-
-	htw = (macio->type == macio_heathrow || macio->type == macio_paddington
-		|| macio->type == macio_gatwick);
-	/* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
-	trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
-	    	 pmac_mb.model_id != PMAC_TYPE_YIKES);
-	if (value) {
-#ifdef CONFIG_ADB_PMU
-		if ((param & 0xfff) == PMAC_SCC_IRDA)
-			pmu_enable_irled(1);
-#endif /* CONFIG_ADB_PMU */		
-		LOCK(flags);
-		fcr = MACIO_IN32(OHARE_FCR);
-		/* Check if scc cell need enabling */
-		if (!(fcr & OH_SCC_ENABLE)) {
-			fcr |= OH_SCC_ENABLE;
-			if (htw) {
-				/* Side effect: this will also power up the
-				 * modem, but it's too messy to figure out on which
-				 * ports this controls the tranceiver and on which
-				 * it controls the modem
-				 */
-				if (trans)
-					fcr &= ~HRW_SCC_TRANS_EN_N;
-				MACIO_OUT32(OHARE_FCR, fcr);
-				fcr |= (rmask = HRW_RESET_SCC);
-				MACIO_OUT32(OHARE_FCR, fcr);
-			} else {
-				fcr |= (rmask = OH_SCC_RESET);
-				MACIO_OUT32(OHARE_FCR, fcr);
-			}
-			UNLOCK(flags);
-			(void)MACIO_IN32(OHARE_FCR);
-			mdelay(15);
-			LOCK(flags);
-			fcr &= ~rmask;
-			MACIO_OUT32(OHARE_FCR, fcr);
-		}
-		if (chan_mask & MACIO_FLAG_SCCA_ON)
-			fcr |= OH_SCCA_IO;
-		if (chan_mask & MACIO_FLAG_SCCB_ON)
-			fcr |= OH_SCCB_IO;
-		MACIO_OUT32(OHARE_FCR, fcr);
-		macio->flags |= chan_mask;
-		UNLOCK(flags);
-		if (param & PMAC_SCC_FLAG_XMON)
-			macio->flags |= MACIO_FLAG_SCC_LOCKED;
-	} else {
-		if (macio->flags & MACIO_FLAG_SCC_LOCKED)
-			return -EPERM;
-		LOCK(flags);
-		fcr = MACIO_IN32(OHARE_FCR);
-		if (chan_mask & MACIO_FLAG_SCCA_ON)
-			fcr &= ~OH_SCCA_IO;
-		if (chan_mask & MACIO_FLAG_SCCB_ON)
-			fcr &= ~OH_SCCB_IO;
-		MACIO_OUT32(OHARE_FCR, fcr);
-		if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
-			fcr &= ~OH_SCC_ENABLE;
-			if (htw && trans)
-				fcr |= HRW_SCC_TRANS_EN_N;
-			MACIO_OUT32(OHARE_FCR, fcr);
-		}
-		macio->flags &= ~(chan_mask);
-		UNLOCK(flags);
-		mdelay(10);
-#ifdef CONFIG_ADB_PMU
-		if ((param & 0xfff) == PMAC_SCC_IRDA)
-			pmu_enable_irled(0);
-#endif /* CONFIG_ADB_PMU */		
-	}
-	return 0;
-}
-
-static int __pmac
-ohare_floppy_enable(struct device_node* node, int param, int value)
-{
-	return simple_feature_tweak(node, macio_ohare,
-		OHARE_FCR, OH_FLOPPY_ENABLE, value);
-}
-
-static int __pmac
-ohare_mesh_enable(struct device_node* node, int param, int value)
-{
-	return simple_feature_tweak(node, macio_ohare,
-		OHARE_FCR, OH_MESH_ENABLE, value);
-}
-
-static int __pmac
-ohare_ide_enable(struct device_node* node, int param, int value)
-{
-	switch(param) {
-	    case 0:
-	    	/* For some reason, setting the bit in set_initial_features()
-	    	 * doesn't stick. I'm still investigating... --BenH.
-	    	 */
-	    	if (value)
-	    		simple_feature_tweak(node, macio_ohare,
-				OHARE_FCR, OH_IOBUS_ENABLE, 1);
-		return simple_feature_tweak(node, macio_ohare,
-			OHARE_FCR, OH_IDE0_ENABLE, value);
-	    case 1:
-		return simple_feature_tweak(node, macio_ohare,
-			OHARE_FCR, OH_BAY_IDE_ENABLE, value);
-	    default:
-	    	return -ENODEV;
-	}
-}
-
-static int __pmac
-ohare_ide_reset(struct device_node* node, int param, int value)
-{
-	switch(param) {
-	    case 0:
-		return simple_feature_tweak(node, macio_ohare,
-			OHARE_FCR, OH_IDE0_RESET_N, !value);
-	    case 1:
-		return simple_feature_tweak(node, macio_ohare,
-			OHARE_FCR, OH_IDE1_RESET_N, !value);
-	    default:
-	    	return -ENODEV;
-	}
-}
-
-static int __pmac
-ohare_sleep_state(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio = &macio_chips[0];
-
-	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
-		return -EPERM;
-	if (value == 1) {
-		MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
-	} else if (value == 0) {
-		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
-	}
-	
-	return 0;
-}
-
-static int __pmac
-heathrow_modem_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	u8			gpio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, macio_unknown);
-	if (!macio)
-		return -ENODEV;
-	gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
-	if (!value) {
-		LOCK(flags);
-		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
-		UNLOCK(flags);
-		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-		mdelay(250);
-	}
-	if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
-	    pmac_mb.model_id != PMAC_TYPE_YIKES) {
-	    	LOCK(flags);
-	    	if (value)
-	    		MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
-	    	else
-	    		MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
-	    	UNLOCK(flags);
-	    	(void)MACIO_IN32(HEATHROW_FCR);
-		mdelay(250);
-	}
-	if (value) {
-		LOCK(flags);
-		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
-		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250); LOCK(flags);
-		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
-		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250); LOCK(flags);
-		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
-		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250);
-	}
-	return 0;
-}
-
-static int __pmac
-heathrow_floppy_enable(struct device_node* node, int param, int value)
-{
-	return simple_feature_tweak(node, macio_unknown,
-		HEATHROW_FCR,
-		HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
-		value);
-}
-
-static int __pmac
-heathrow_mesh_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, macio_unknown);
-	if (!macio)
-		return -ENODEV;
-	LOCK(flags);
-	/* Set clear mesh cell enable */
-	if (value)
-		MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
-	else
-		MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
-	(void)MACIO_IN32(HEATHROW_FCR);
-	udelay(10);
-	/* Set/Clear termination power (todo: test ! the bit value
-	 * used by Darwin doesn't seem to match what we used so
-	 * far. If you experience problems, turn #if 1 into #if 0
-	 * and tell me about it --BenH.
-	 */
-#if 1
-	if (value)
-		MACIO_BIC(HEATHROW_MBCR, 0x00000004);
-	else
-		MACIO_BIS(HEATHROW_MBCR, 0x00000004);
-#else
-	if (value)
-		MACIO_BIC(HEATHROW_MBCR, 0x00040000);
-	else
-		MACIO_BIS(HEATHROW_MBCR, 0x00040000);
-#endif		
-	(void)MACIO_IN32(HEATHROW_MBCR);
-	udelay(10);
-	UNLOCK(flags);
-
-	return 0;
-}
-
-static int __pmac
-heathrow_ide_enable(struct device_node* node, int param, int value)
-{
-	switch(param) {
-	    case 0:
-		return simple_feature_tweak(node, macio_unknown,
-			HEATHROW_FCR, HRW_IDE0_ENABLE, value);
-	    case 1:
-		return simple_feature_tweak(node, macio_unknown,
-			HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
-	    default:
-	    	return -ENODEV;
-	}
-}
-
-static int __pmac
-heathrow_ide_reset(struct device_node* node, int param, int value)
-{
-	switch(param) {
-	    case 0:
-		return simple_feature_tweak(node, macio_unknown,
-			HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
-	    case 1:
-		return simple_feature_tweak(node, macio_unknown,
-			HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
-	    default:
-	    	return -ENODEV;
-	}
-}
-
-static int __pmac
-heathrow_bmac_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	if (value) {
-		LOCK(flags);
-		MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
-		MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
-		UNLOCK(flags);
-		(void)MACIO_IN32(HEATHROW_FCR);
-		mdelay(10);
-		LOCK(flags);
-		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
-		UNLOCK(flags);
-		(void)MACIO_IN32(HEATHROW_FCR);
-		mdelay(10);
-	} else {
-		LOCK(flags);
-		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
-		UNLOCK(flags);
-	}
-	return 0;
-}
-
-static int __pmac
-heathrow_sound_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-
-	/* B&W G3 and Yikes don't support that properly (the
-	 * sound appear to never come back after beeing shut down).
-	 */
-	if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
-	    pmac_mb.model_id == PMAC_TYPE_YIKES)
-		return 0;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	if (value) {
-		LOCK(flags);
-		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
-		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
-		UNLOCK(flags);
-		(void)MACIO_IN32(HEATHROW_FCR);
-	} else {
-		LOCK(flags);
-		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
-		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
-		UNLOCK(flags);
-	}
-	return 0;
-}
-
-static u32 save_fcr[5] __pmacdata;
-static u32 save_mbcr __pmacdata;
-static u32 save_gpio_levels[2] __pmacdata;
-static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
-static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata;
-static u32 save_unin_clock_ctl __pmacdata;
-static struct dbdma_regs save_dbdma[13] __pmacdata;
-static struct dbdma_regs save_alt_dbdma[13] __pmacdata;
-
-static void __pmac
-dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)
-{
-	int i;
-	
-	/* Save state & config of DBDMA channels */
-	for (i=0; i<13; i++) {
-		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
-			(macio->base + ((0x8000+i*0x100)>>2));
-		save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
-		save[i].cmdptr = in_le32(&chan->cmdptr);
-		save[i].intr_sel = in_le32(&chan->intr_sel);
-		save[i].br_sel = in_le32(&chan->br_sel);
-		save[i].wait_sel = in_le32(&chan->wait_sel);
-	}
-}
-
-static void __pmac
-dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)
-{
-	int i;
-	
-	/* Save state & config of DBDMA channels */
-	for (i=0; i<13; i++) {
-		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
-			(macio->base + ((0x8000+i*0x100)>>2));
-		out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
-		while (in_le32(&chan->status) & ACTIVE)
-			mb();
-		out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
-		out_le32(&chan->cmdptr, save[i].cmdptr);
-		out_le32(&chan->intr_sel, save[i].intr_sel);
-		out_le32(&chan->br_sel, save[i].br_sel);
-		out_le32(&chan->wait_sel, save[i].wait_sel);
-	}
-}
-
-static void __pmac
-heathrow_sleep(struct macio_chip* macio, int secondary)
-{
-	if (secondary) {
-		dbdma_save(macio, save_alt_dbdma);
-		save_fcr[2] = MACIO_IN32(0x38);
-		save_fcr[3] = MACIO_IN32(0x3c);
-	} else {
-		dbdma_save(macio, save_dbdma);
-		save_fcr[0] = MACIO_IN32(0x38);
-		save_fcr[1] = MACIO_IN32(0x3c);
-		save_mbcr = MACIO_IN32(0x34);
-		/* Make sure sound is shut down */
-		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
-		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
-		/* This seems to be necessary as well or the fan
-		 * keeps coming up and battery drains fast */
-		MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
-		/* Make sure eth is down even if module or sleep
-		 * won't work properly */
-		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
-	}
-	/* Make sure modem is shut down */
-	MACIO_OUT8(HRW_GPIO_MODEM_RESET,
-		MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
-	MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
-	MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
-
-	/* Let things settle */
-	(void)MACIO_IN32(HEATHROW_FCR);
-	mdelay(1);
-}
-
-static void __pmac
-heathrow_wakeup(struct macio_chip* macio, int secondary)
-{
-	if (secondary) {
-		MACIO_OUT32(0x38, save_fcr[2]);
-		(void)MACIO_IN32(0x38);
-		mdelay(1);
-		MACIO_OUT32(0x3c, save_fcr[3]);
-		(void)MACIO_IN32(0x38);
-		mdelay(10);
-		dbdma_restore(macio, save_alt_dbdma);
-	} else {
-		MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
-		(void)MACIO_IN32(0x38);
-		mdelay(1);
-		MACIO_OUT32(0x3c, save_fcr[1]);
-		(void)MACIO_IN32(0x38);
-		mdelay(1);
-		MACIO_OUT32(0x34, save_mbcr);
-		(void)MACIO_IN32(0x38);
-		mdelay(10);
-		dbdma_restore(macio, save_dbdma);
-	}
-}
-
-static int __pmac
-heathrow_sleep_state(struct device_node* node, int param, int value)
-{
-	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
-		return -EPERM;
-	if (value == 1) {
-		if (macio_chips[1].type == macio_gatwick)
-			heathrow_sleep(&macio_chips[0], 1);
-		heathrow_sleep(&macio_chips[0], 0);
-	} else if (value == 0) {
-		heathrow_wakeup(&macio_chips[0], 0);
-		if (macio_chips[1].type == macio_gatwick)
-			heathrow_wakeup(&macio_chips[0], 1);
-	}
-	return 0;
-}
-
-static int __pmac
-core99_scc_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-	unsigned long		chan_mask;
-	u32			fcr;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	if (!strcmp(node->name, "ch-a"))
-		chan_mask = MACIO_FLAG_SCCA_ON;
-	else if (!strcmp(node->name, "ch-b"))
-		chan_mask = MACIO_FLAG_SCCB_ON;
-	else
-		return -ENODEV;
-
-	if (value) {
-		int need_reset_scc = 0;
-		int need_reset_irda = 0;
-		
-		LOCK(flags);
-		fcr = MACIO_IN32(KEYLARGO_FCR0);
-		/* Check if scc cell need enabling */
-		if (!(fcr & KL0_SCC_CELL_ENABLE)) {
-			fcr |= KL0_SCC_CELL_ENABLE;
-			need_reset_scc = 1;
-		}
-		if (chan_mask & MACIO_FLAG_SCCA_ON) {
-			fcr |= KL0_SCCA_ENABLE;
-			/* Don't enable line drivers for I2S modem */
-			if ((param & 0xfff) == PMAC_SCC_I2S1)
-				fcr &= ~KL0_SCC_A_INTF_ENABLE;
-			else
-				fcr |= KL0_SCC_A_INTF_ENABLE;
-		}
-		if (chan_mask & MACIO_FLAG_SCCB_ON) {
-			fcr |= KL0_SCCB_ENABLE;
-			/* Perform irda specific inits */
-			if ((param & 0xfff) == PMAC_SCC_IRDA) {
-				fcr &= ~KL0_SCC_B_INTF_ENABLE;
-				fcr |= KL0_IRDA_ENABLE;
-				fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
-				fcr |= KL0_IRDA_SOURCE1_SEL;
-				fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
-				fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
-				need_reset_irda = 1;
-			} else
-				fcr |= KL0_SCC_B_INTF_ENABLE;
-		}
-		MACIO_OUT32(KEYLARGO_FCR0, fcr);
-		macio->flags |= chan_mask;
-		if (need_reset_scc)  {
-			MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-			UNLOCK(flags);
-			mdelay(15);
-			LOCK(flags);
-			MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
-		}
-		if (need_reset_irda)  {
-			MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-			UNLOCK(flags);
-			mdelay(15);
-			LOCK(flags);
-			MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
-		}
-		UNLOCK(flags);
-		if (param & PMAC_SCC_FLAG_XMON)
-			macio->flags |= MACIO_FLAG_SCC_LOCKED;
-	} else {
-		if (macio->flags & MACIO_FLAG_SCC_LOCKED)
-			return -EPERM;
-		LOCK(flags);
-		fcr = MACIO_IN32(KEYLARGO_FCR0);
-		if (chan_mask & MACIO_FLAG_SCCA_ON)
-			fcr &= ~KL0_SCCA_ENABLE;
-		if (chan_mask & MACIO_FLAG_SCCB_ON) {
-			fcr &= ~KL0_SCCB_ENABLE;
-			/* Perform irda specific clears */
-			if ((param & 0xfff) == PMAC_SCC_IRDA) {
-				fcr &= ~KL0_IRDA_ENABLE;
-				fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
-				fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
-				fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
-			}
-		}
-		MACIO_OUT32(KEYLARGO_FCR0, fcr);
-		if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
-			fcr &= ~KL0_SCC_CELL_ENABLE;
-			MACIO_OUT32(KEYLARGO_FCR0, fcr);
-		}
-		macio->flags &= ~(chan_mask);
-		UNLOCK(flags);
-		mdelay(10);
-	}
-	return 0;
-}
-
-static int __pmac
-core99_modem_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	u8			gpio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
-	gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
-	gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
-	
-	if (!value) {
-		LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
-		UNLOCK(flags);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-		mdelay(250);
-	}
-    	LOCK(flags);
-    	if (value) {
-    		MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
-	    	UNLOCK(flags);
-	    	(void)MACIO_IN32(KEYLARGO_FCR2);
-		mdelay(250);
-    	} else {
-    		MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
-	    	UNLOCK(flags);
-    	}
-	if (value) {
-		LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250); LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250); LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250);
-	}
-	return 0;
-}
-
-static int __pmac
-core99_ide_enable(struct device_node* node, int param, int value)
-{
-	switch(param) {
-	    case 0:
-		return simple_feature_tweak(node, macio_unknown,
-			KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
-	    case 1:
-		return simple_feature_tweak(node, macio_unknown,
-			KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
-	    case 2:
-		return simple_feature_tweak(node, macio_unknown,
-			KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
-	    default:
-	    	return -ENODEV;
-	}
-}
-
-static int __pmac
-core99_ide_reset(struct device_node* node, int param, int value)
-{
-	switch(param) {
-	    case 0:
-		return simple_feature_tweak(node, macio_unknown,
-			KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
-	    case 1:
-		return simple_feature_tweak(node, macio_unknown,
-			KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
-	    case 2:
-		return simple_feature_tweak(node, macio_unknown,
-			KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
-	    default:
-	    	return -ENODEV;
-	}
-}
-
-static int __pmac
-core99_gmac_enable(struct device_node* node, int param, int value)
-{
-	unsigned long flags;
-
-	LOCK(flags);
-	if (value)
-		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
-	else
-		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
-	(void)UN_IN(UNI_N_CLOCK_CNTL);
-	UNLOCK(flags);
-	udelay(20);
-
-	return 0;
-}
-
-static int __pmac
-core99_gmac_phy_reset(struct device_node* node, int param, int value)
-{
-	unsigned long flags;
-	struct macio_chip* macio;
-	
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-
-	LOCK(flags);
-	MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
-	(void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
-	UNLOCK(flags);
-	mdelay(10);
-	LOCK(flags);
-	MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE
-		| KEYLARGO_GPIO_OUTOUT_DATA);
-	UNLOCK(flags);
-	mdelay(10);
-
-	return 0;
-}
-
-static int __pmac
-core99_sound_chip_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-
-	/* Do a better probe code, screamer G4 desktops &
-	 * iMacs can do that too, add a recalibrate  in
-	 * the driver as well
-	 */
-	if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
-	    pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
-		LOCK(flags);
-		if (value)
-	    		MACIO_OUT8(KL_GPIO_SOUND_POWER,
-	    			KEYLARGO_GPIO_OUTPUT_ENABLE |
-	    			KEYLARGO_GPIO_OUTOUT_DATA);
-	    	else
-	    		MACIO_OUT8(KL_GPIO_SOUND_POWER,
-	    			KEYLARGO_GPIO_OUTPUT_ENABLE);
-	    	(void)MACIO_IN8(KL_GPIO_SOUND_POWER);
-	    	UNLOCK(flags);
-	}
-	return 0;
-}
-
-static int __pmac
-core99_airport_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	unsigned long		flags;
-	int			state;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	
-	/* Hint: we allow passing of macio itself for the sake of the
-	 * sleep code
-	 */
-	if (node != macio->of_node &&
-	    (!node->parent || node->parent != macio->of_node))
-		return -ENODEV;
-	state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
-	if (value == state)
-		return 0;
-	if (value) {
-		/* This code is a reproduction of OF enable-cardslot
-		 * and init-wireless methods, slightly hacked until
-		 * I got it working.
-		 */
-		LOCK(flags);
-		MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
-		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
-		UNLOCK(flags);
-		mdelay(10);
-		LOCK(flags);
-		MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
-		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
-		UNLOCK(flags);
-
-		mdelay(10);
-
-		LOCK(flags);
-		MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
-		(void)MACIO_IN32(KEYLARGO_FCR2);
-		udelay(10);
-		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
-		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
-		udelay(10);
-		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
-		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
-		udelay(10);
-		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
-		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
-		udelay(10);
-		MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
-		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
-		udelay(10);
-		MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
-		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
-		UNLOCK(flags);
-		udelay(10);
-		MACIO_OUT32(0x1c000, 0);
-		mdelay(1);
-		MACIO_OUT8(0x1a3e0, 0x41);
-		(void)MACIO_IN8(0x1a3e0);
-		udelay(10);
-		LOCK(flags);
-		MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
-		(void)MACIO_IN32(KEYLARGO_FCR2);
-		UNLOCK(flags);
-		mdelay(100);
-
-		macio->flags |= MACIO_FLAG_AIRPORT_ON;
-	} else {
-		LOCK(flags);
-		MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
-		(void)MACIO_IN32(KEYLARGO_FCR2);
-		MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
-		MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
-		MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
-		MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
-		MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
-		(void)MACIO_IN8(KL_GPIO_AIRPORT_4);
-		UNLOCK(flags);
-
-		macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
-	}
-	return 0;
-}
-
-#ifdef CONFIG_SMP
-static int __pmac
-core99_reset_cpu(struct device_node* node, int param, int value)
-{
-	const int reset_lines[] = {	KL_GPIO_RESET_CPU0,
-					KL_GPIO_RESET_CPU1,
-					KL_GPIO_RESET_CPU2,
-					KL_GPIO_RESET_CPU3 };
-	int reset_io;
-	unsigned long flags;
-	struct macio_chip* macio;
-	
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-	if (param > 3 || param < 0)
-		return -ENODEV;
-
-	reset_io = reset_lines[param];
-	
-	LOCK(flags);
-	MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
-	(void)MACIO_IN8(reset_io);
-	udelay(1);
-	MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
-	(void)MACIO_IN8(reset_io);
-	UNLOCK(flags);
-
-	return 0;
-}
-#endif /* CONFIG_SMP */
-
-static int __pmac
-core99_usb_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip* macio;
-	unsigned long flags;
-	char* prop;
-	int number;
-	u32 reg;
-	
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-	
-	prop = (char *)get_property(node, "AAPL,clock-id", NULL);
-	if (!prop)
-		return -ENODEV;
-	if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
-		number = 0;
-	else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
-		number = 2;
-	else
-		return -ENODEV;
-
-	/* Sorry for the brute-force locking, but this is only used during
-	 * sleep and the timing seem to be critical
-	 */
-	LOCK(flags);
-	if (value) {
-		/* Turn ON */
-		if (number == 0) {
-			MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-			UNLOCK(flags);
-			mdelay(1);
-			LOCK(flags);
-			MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
-		} else {
-			MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
-			UNLOCK(flags);
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-			mdelay(1);
-			LOCK(flags);
-			MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
-		}
-		reg = MACIO_IN32(KEYLARGO_FCR4);
-		reg &=	~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
-			KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
-		reg &=	~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
-			KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
-		MACIO_OUT32(KEYLARGO_FCR4, reg);
-		(void)MACIO_IN32(KEYLARGO_FCR4);
-		udelay(10);
-	} else {
-		/* Turn OFF */
-		reg = MACIO_IN32(KEYLARGO_FCR4);
-		reg |=	KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
-			KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
-		reg |=	KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
-			KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
-		MACIO_OUT32(KEYLARGO_FCR4, reg);
-		(void)MACIO_IN32(KEYLARGO_FCR4);
-		udelay(1);
-		if (number == 0) {
-			MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-			udelay(1);
-			MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-		} else {
-			MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-			udelay(1);
-			MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
-			(void)MACIO_IN32(KEYLARGO_FCR0);
-		}
-		udelay(1);
-	}
-	UNLOCK(flags);
-
-	return 0;
-}
-
-static int __pmac
-core99_firewire_enable(struct device_node* node, int param, int value)
-{
-	unsigned long flags;
-	struct macio_chip* macio;
-
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-	if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
-		return -ENODEV;
-	
-	LOCK(flags);
-	if (value) {
-		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
-		(void)UN_IN(UNI_N_CLOCK_CNTL);
-	} else {
-		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
-		(void)UN_IN(UNI_N_CLOCK_CNTL);
-	}
-	UNLOCK(flags);
-	mdelay(1);
-
-	return 0;
-}
-
-static int __pmac
-core99_firewire_cable_power(struct device_node* node, int param, int value)
-{
-	unsigned long flags;
-	struct macio_chip* macio;
-
-	/* Trick: we allow NULL node */
-	if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
-	    	return -ENODEV;
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-	if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
-		return -ENODEV;
-	
-	LOCK(flags);
-	if (value) {
-		MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
-		MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
-		udelay(10);
-	} else {
-		MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
-		MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
-	}
-	UNLOCK(flags);
-	mdelay(1);
-
-	return 0;
-}
-
-static int __pmac
-core99_read_gpio(struct device_node* node, int param, int value)
-{
-	struct macio_chip* macio = &macio_chips[0];
-	
-	return MACIO_IN8(param);
-}
-
-
-static int __pmac
-core99_write_gpio(struct device_node* node, int param, int value)
-{
-	struct macio_chip* macio = &macio_chips[0];
-
-	MACIO_OUT8(param, (u8)(value & 0xff));
-	return 0;
-}
-
-static void __pmac
-keylargo_shutdown(struct macio_chip* macio, int restart)
-{
-	u32 temp;
-
-	mdelay(1);
-	MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
-	(void)MACIO_IN32(KEYLARGO_FCR0);
-	mdelay(100);
-
-	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
-				KL0_SCC_CELL_ENABLE |
-		      		KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
-		      		KL0_IRDA_CLK19_ENABLE);
-
-	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
-	MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
-	(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
-
-	MACIO_BIC(KEYLARGO_FCR1,
-		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
-		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
-		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
-		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
-		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
-		KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
-		KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
-		KL1_UIDE_ENABLE);
-	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
-
-	MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- 	udelay(10);
- 	MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
- 	udelay(10);
-	temp = MACIO_IN32(KEYLARGO_FCR3);
-	if (macio->rev >= 2)
-		temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
-		
-	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
-		KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
-	temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
-		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
-		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
-	MACIO_OUT32(KEYLARGO_FCR3, temp);
-	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
-}
-
-static void __pmac
-pangea_shutdown(struct macio_chip* macio, int restart)
-{
-	u32 temp;
-
-	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
-				KL0_SCC_CELL_ENABLE |
-				KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
-
-	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
-	MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
-	(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
-
-	MACIO_BIC(KEYLARGO_FCR1,
-		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
-		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
-		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
-		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
-		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
-		KL1_UIDE_ENABLE);
-	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
-
-	MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
- 	udelay(10);
-	temp = MACIO_IN32(KEYLARGO_FCR3);
-	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
-		KL3_SHUTDOWN_PLLKW35;
-	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
-		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
-		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
-	MACIO_OUT32(KEYLARGO_FCR3, temp);
-	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
-}
-
-static int __pmac
-core99_sleep(void)
-{
-	struct macio_chip* macio;
-	int i;
-
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-	
-	/* We power off the wireless slot in case it was not done
-	 * by the driver. We don't power it on automatically however
-	 */
-	if (macio->flags & MACIO_FLAG_AIRPORT_ON)
-		core99_airport_enable(macio->of_node, 0, 0);
-
-	/* We power off the FW cable. Should be done by the driver... */
-	if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
-		core99_firewire_enable(NULL, 0, 0);
-		core99_firewire_cable_power(NULL, 0, 0);
-	}
-
-	/* We make sure int. modem is off (in case driver lost it) */
-	core99_modem_enable(macio->of_node, 0, 0);
-	/* We make sure the sound is off as well */
-	core99_sound_chip_enable(macio->of_node, 0, 0);
-	 
-	/*
-	 * Save various bits of KeyLargo
-	 */
-
-	/* Save the state of the various GPIOs */
-	save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
-	save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
-	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
-		save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
-	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
-		save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
-
-	/* Save the FCRs */
-	save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
-	save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
-	save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
-	save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
-	save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
-	save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
-
-	/* Save state & config of DBDMA channels */
-	dbdma_save(macio, save_dbdma);
-	
-	/*
-	 * Turn off as much as we can
-	 */
-	if (macio->type == macio_pangea)
-		pangea_shutdown(macio, 0);
-	else if (macio->type == macio_keylargo)
-		keylargo_shutdown(macio, 0);
-	
-	/* 
-	 * Put the host bridge to sleep
-	 */
-
-	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
-	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
-		~(UNI_N_CLOCK_CNTL_GMAC|UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
-	udelay(100);
-	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
-	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
-
-	/*
-	 * FIXME: A bit of black magic with OpenPIC (don't ask me why)
-	 */
-	if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
-		MACIO_BIS(0x506e0, 0x00400000);
-		MACIO_BIS(0x506e0, 0x80000000);
-	}
-	return 0;
-}
-
-static int __pmac
-core99_wake_up(void)
-{
-	struct macio_chip* macio;
-	int i;
-
-	macio = &macio_chips[0];
-	if (macio->type != macio_keylargo && macio->type != macio_pangea)
-		return -ENODEV;
-
-	/*
-	 * Wakeup the host bridge
-	 */
-	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
-	udelay(10);
-	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
-	udelay(10);
-	
-	/*
-	 * Restore KeyLargo
-	 */
-	 
-	MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
-	(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
-	MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
-	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
-	MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
-	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
-	MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
-	(void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
-	MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
-	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
-	MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
-	(void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
-
-	dbdma_restore(macio, save_dbdma);
-
-	MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
-	MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
-	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
-		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
-	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
-		MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
-
-	/* FIXME more black magic with OpenPIC ... */
-	if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
-		MACIO_BIC(0x506e0, 0x00400000);
-		MACIO_BIC(0x506e0, 0x80000000);
-	}
-
-	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
-	udelay(100);
-
-	return 0;
-}
-
-static int __pmac
-core99_sleep_state(struct device_node* node, int param, int value)
-{
-	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
-		return -EPERM;
-	if (value == 1)
-		return core99_sleep();
-	else if (value == 0)
-		return core99_wake_up();
-	return 0;
-}
-
-static int __pmac
-pangea_modem_enable(struct device_node* node, int param, int value)
-{
-	struct macio_chip*	macio;
-	u8			gpio;
-	unsigned long		flags;
-	
-	macio = macio_find(node, 0);
-	if (!macio)
-		return -ENODEV;
-	gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
-	gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
-	gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
-	
-	if (!value) {
-		LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
-		UNLOCK(flags);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-		mdelay(250);
-	}
-    	LOCK(flags);
-	if (value) {
-		MACIO_OUT8(KL_GPIO_MODEM_POWER,
-			KEYLARGO_GPIO_OUTPUT_ENABLE);
-    		UNLOCK(flags);
-	    	(void)MACIO_IN32(KEYLARGO_FCR2);
-		mdelay(250);
-	} else {
-		MACIO_OUT8(KL_GPIO_MODEM_POWER,
-			KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
-    		UNLOCK(flags);
-	}
-	if (value) {
-		LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250); LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250); LOCK(flags);
-		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
-		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
-	    	UNLOCK(flags); mdelay(250);
-	}
-	return 0;
-}
-
-
-static int __pmac
-generic_get_mb_info(struct device_node* node, int param, int value)
-{
-	switch(param) {
-		case PMAC_MB_INFO_MODEL:
-			return pmac_mb.model_id;
-		case PMAC_MB_INFO_FLAGS:
-			return pmac_mb.board_flags;
-		case PMAC_MB_INFO_NAME:	
-			/* hack hack hack... but should work */
-			*((const char **)value) = pmac_mb.model_name;
-			break;
-	}
-	return 0;
-}
-
-
-/* 
- * Table definitions
- */
- 
-/* Used on any machine
- */
-static struct feature_table_entry any_features[]  __pmacdata = {
-	{ PMAC_FTR_GET_MB_INFO,		generic_get_mb_info },
-	{ 0, NULL }
-};
-
-/* OHare based motherboards. Currently, we only use these on the
- * 2400,3400 and 3500 series powerbooks. Some older desktops seem
- * to have issues with turning on/off those asic cells
- */
-static struct feature_table_entry ohare_features[]  __pmacdata = {
-	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
-	{ PMAC_FTR_SWIM3_ENABLE,	ohare_floppy_enable },
-	{ PMAC_FTR_MESH_ENABLE,		ohare_mesh_enable },
-	{ PMAC_FTR_IDE_ENABLE,		ohare_ide_enable},
-	{ PMAC_FTR_IDE_RESET,		ohare_ide_reset},
-	{ PMAC_FTR_SLEEP_STATE,		ohare_sleep_state },
-	{ 0, NULL }
-};
-
-/* Heathrow desktop machines (Beige G3).
- * Separated as some features couldn't be properly tested
- * and the serial port control bits appear to confuse it.
- */
-static struct feature_table_entry heathrow_desktop_features[]  __pmacdata = {
-	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
-	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
-	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
-	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
-	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
-	{ 0, NULL }
-};
-
-/* Heathrow based laptop, that is the Wallstreet and mainstreet
- * powerbooks.
- */
-static struct feature_table_entry heathrow_laptop_features[]  __pmacdata = {
-	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
-	{ PMAC_FTR_MODEM_ENABLE,	heathrow_modem_enable },
-	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
-	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
-	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
-	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
-	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
-	{ PMAC_FTR_SOUND_CHIP_ENABLE,	heathrow_sound_enable },
-	{ PMAC_FTR_SLEEP_STATE,		heathrow_sleep_state },
-	{ 0, NULL }
-};
-
-/* Paddington based machines
- * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
- */
-static struct feature_table_entry paddington_features[]  __pmacdata = {
-	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
-	{ PMAC_FTR_MODEM_ENABLE,	heathrow_modem_enable },
-	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
-	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
-	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
-	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
-	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
-	{ PMAC_FTR_SOUND_CHIP_ENABLE,	heathrow_sound_enable },
-	{ PMAC_FTR_SLEEP_STATE,		heathrow_sleep_state },
-	{ 0, NULL }
-};
-
-/* Core99 & MacRISC 2 machines (all machines released since the
- * iBook (included), that is all AGP machines, except pangea
- * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
- * used on iBook2 & iMac "flow power".
- */
-static struct feature_table_entry core99_features[]  __pmacdata = {
-	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
-	{ PMAC_FTR_MODEM_ENABLE,	core99_modem_enable },
-	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
-	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
-	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
-	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
-	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
-	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
-	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
-	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
-	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
-	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
-#ifdef CONFIG_SMP
-	{ PMAC_FTR_RESET_CPU,		core99_reset_cpu },
-#endif /* CONFIG_SMP */
-	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
-	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
-	{ 0, NULL }
-};
-
-/* Pangea features
- */
-static struct feature_table_entry pangea_features[]  __pmacdata = {
-	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
-	{ PMAC_FTR_MODEM_ENABLE,	pangea_modem_enable },
-	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
-	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
-	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
-	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
-	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
-	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
-	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
-	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
-	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
-	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
-	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
-	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
-	{ 0, NULL }
-};
-	
-static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
-	/* Warning: ordering is important as some models may claim
-	 * beeing compatible with several types
-	 */
-	{	"AAPL,8500",			"PowerMac 8500/8600",
-		PMAC_TYPE_PSURGE,		NULL,
-		0
-	},
-	{	"AAPL,9500",			"PowerMac 9500/9600",
-		PMAC_TYPE_PSURGE,		NULL,
-		0
-	},
-	{	"AAPL,7500",			"PowerMac 7500",
-		PMAC_TYPE_PSURGE,		NULL,
-		0
-	},
-	{	"AAPL,ShinerESB",		"Apple Network Server",
-		PMAC_TYPE_ANS,			NULL,
-		0
-	},
-	{	"AAPL,e407",			"Alchemy",
-		PMAC_TYPE_ALCHEMY,		NULL,
-		0
-	},
-	{	"AAPL,e411",			"Gazelle",
-		PMAC_TYPE_GAZELLE,		NULL,
-		0
-	},
-	{	"AAPL,3400/2400",		"PowerBook 3400",
-		PMAC_TYPE_HOOPER,		ohare_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"AAPL,3500",			"PowerBook 3500",
-		PMAC_TYPE_KANGA,		ohare_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"AAPL,Gossamer",		"PowerMac G3 (Gossamer)",
-		PMAC_TYPE_GOSSAMER,		heathrow_desktop_features,
-		0
-	},
-	{	"AAPL,PowerMac G3",		"PowerMac G3 (Silk)",
-		PMAC_TYPE_SILK,			heathrow_desktop_features,
-		0
-	},
-	{	"AAPL,PowerBook1998",		"PowerBook Wallstreet",
-		PMAC_TYPE_WALLSTREET,		heathrow_laptop_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"AAPL,PowerBook1,1",		"PowerBook 101 (Lombard)",
-		PMAC_TYPE_101_PBOOK,		paddington_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"iMac,1",			"iMac (first generation)",
-		PMAC_TYPE_ORIG_IMAC,		paddington_features,
-		0
-	},
-	{	"PowerMac4,1",			"iMac \"Flower Power\"",
-		PMAC_TYPE_PANGEA_IMAC,		pangea_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"PowerBook4,3",			"iBook 2 with 14\" LCD",
-		PMAC_TYPE_IBOOK2,		pangea_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerBook4,2",			"iBook 2 with 14\" LCD",
-		PMAC_TYPE_IBOOK2,		pangea_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerBook4,1",			"iBook 2",
-		PMAC_TYPE_IBOOK2,		pangea_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerMac4,2",			"Flat panel iMac",
-		PMAC_TYPE_FLAT_PANEL_IMAC,	pangea_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"PowerMac1,1",			"Blue&White G3",
-		PMAC_TYPE_YOSEMITE,		paddington_features,
-		0
-	},
-	{	"PowerMac1,2",			"PowerMac G4 PCI Graphics",
-		PMAC_TYPE_YIKES,		paddington_features,
-		0
-	},
-	{	"PowerBook2,1",			"iBook (first generation)",
-		PMAC_TYPE_ORIG_IBOOK,		core99_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"PowerMac3,1",			"PowerMac G4 AGP Graphics",
-		PMAC_TYPE_SAWTOOTH,		core99_features,
-		0
-	},
-	{	"PowerMac3,2",			"PowerMac G4 AGP Graphics",
-		PMAC_TYPE_SAWTOOTH,		core99_features,
-		0
-	},
-	{	"PowerMac3,3",			"PowerMac G4 AGP Graphics",
-		PMAC_TYPE_SAWTOOTH,		core99_features,
-		0
-	},
-	{	"PowerMac2,1",			"iMac FireWire",
-		PMAC_TYPE_FW_IMAC,		core99_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"PowerMac2,2",			"iMac FireWire",
-		PMAC_TYPE_FW_IMAC,		core99_features,
-		PMAC_MB_CAN_SLEEP
-	},
-	{	"PowerBook2,2",			"iBook FireWire",
-		PMAC_TYPE_FW_IBOOK,		core99_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerMac5,1",			"PowerMac G4 Cube",
-		PMAC_TYPE_CUBE,			core99_features,
-	},
-	{	"PowerMac3,4",			"PowerMac G4 Silver",
-		PMAC_TYPE_QUICKSILVER,		core99_features,
-		0
-	},
-	{	"PowerMac3,5",			"PowerMac G4 Silver",
-		PMAC_TYPE_QUICKSILVER,		core99_features,
-		0
-	},
-	{	"PowerBook3,1",			"PowerBook Pismo",
-		PMAC_TYPE_PISMO,		core99_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerBook3,2",			"PowerBook Titanium",
-		PMAC_TYPE_TITANIUM,		core99_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerBook3,3",			"PowerBook Titanium II",
-		PMAC_TYPE_TITANIUM2,		core99_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-	{	"PowerBook3,4",			"PowerBook Titanium III",
-		PMAC_TYPE_TITANIUM3,		core99_features,
-		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
-	},
-};
-
-/*
- * The toplevel feature_call callback
- */
-int __pmac
-pmac_do_feature_call(unsigned int selector, ...)
-{
-	struct device_node* node;
-	int param, value, i;
-	feature_call func = NULL;
-	va_list args;
-	
-	if (pmac_mb.features)
-		for (i=0; pmac_mb.features[i].function; i++)
-			if (pmac_mb.features[i].selector == selector) {
-				func = pmac_mb.features[i].function;
-				break;
-			}
-	if (!func)
-		for (i=0; any_features[i].function; i++)
-			if (any_features[i].selector == selector) {
-				func = any_features[i].function;
-				break;
-			}
-	if (!func)
-		return -ENODEV;
-
-	va_start(args, selector);
-	node = (struct device_node*)va_arg(args, void*);
-	param = va_arg(args, int);
-	value = va_arg(args, int);
-	va_end(args);
-
-	return func(node, param, value);
-}
-
-static int __init
-probe_motherboard(void)
-{
-	int i;
-	struct macio_chip* macio = &macio_chips[0];
-
-	/* Lookup known motherboard type in device-tree */
-	for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
-	    if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
-		pmac_mb = pmac_mb_defs[i];
-		goto found;
-	    }
-	}
-
-	/* Fallback to selection depending on mac-io chip type */
-	switch(macio->type) {
-	    case macio_grand_central:
-		pmac_mb.model_id = PMAC_TYPE_PSURGE;
-		pmac_mb.model_name = "Unknown PowerSurge";
-		break;
-	    case macio_ohare:
-		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
-		pmac_mb.model_name = "Unknown OHare-based";
-	    	break;
-	    case macio_heathrow:
-		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
-		pmac_mb.model_name = "Unknown Heathrow-based";
-		pmac_mb.features = heathrow_desktop_features;
-		break;
-	    case macio_paddington:
-		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
-		pmac_mb.model_name = "Unknown Paddington-based";
-	    	pmac_mb.features = paddington_features;
-		break;
-	    case macio_keylargo:
-		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
-		pmac_mb.model_name = "Unknown Keylargo-based";
-	    	pmac_mb.features = core99_features;
-		break;
-	    case macio_pangea:
-		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
-		pmac_mb.model_name = "Unknown Pangea-based";
-	    	pmac_mb.features = pangea_features;
-		break;
-	    default:
-	    	return -ENODEV;
-	}
-found:
-	/* Fixup Hooper vs. Comet */
-	if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
-		u32* mach_id_ptr = (u32*)ioremap(0xf3000034, 4);
-		if (!mach_id_ptr)
-			return -ENODEV;
-		/* Here, I used to disable the media-bay on comet. It
-		 * appears this is wrong, the floppy connector is actually
-		 * a kind of media-bay and works with the current driver.
-		 */
-		if ((*mach_id_ptr) & 0x20000000UL)
-			pmac_mb.model_id = PMAC_TYPE_COMET;
-		iounmap(mach_id_ptr);
-	}
-
-	/* Set default value of powersave_nap on machines that support it.
-	 * It appears that uninorth rev 3 has a problem with it, we don't
-	 * enable it on those. In theory, the flush-on-lock property is
-	 * supposed to be set when not supported, but I'm not very confident
-	 * that all Apple OF revs did it properly, I do it the paranoid way.
-	 */
-	while (uninorth_base && uninorth_rev > 3) {
-		struct device_node* np = find_path_device("/cpus");
-		u32 pvr = mfspr(PVR);
-		if (!np || !np->child) {
-			printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
-			break;
-		}
-		np = np->child;
-		/* Nap mode not supported on SMP */
-		if (np->sibling)
-			break;
-		/* Nap mode not supported if flush-on-lock property is present */
-		if (get_property(np, "flush-on-lock", NULL))
-			break;
-		/* Some 7450 may have problem with NAP mode too ... */
-		if (((pvr >> 16) == 0x8000) && ((pvr & 0xffff) < 0x0201))
-			break;
-		powersave_nap = 1;
-		printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
-		break;
-	}
-
-	printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
-	return 0;
-}
-
-/* Initialize the Core99 UniNorth host bridge and memory controller
- */
-static void __init
-probe_uninorth(void)
-{
-	unsigned long actrl;
-	
-	/* Locate core99 Uni-N */
-	uninorth_node = find_devices("uni-n");
-	if (uninorth_node && uninorth_node->n_addrs > 0) {
-		uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x1000);
-		uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
-	} else
-		uninorth_node = NULL;
-		
-	if (!uninorth_node)
-		return;
-	
-	printk(KERN_INFO "Found Uninorth memory controller & host bridge, revision: %d\n",
-			uninorth_rev);
-
-	/* Set the arbitrer QAck delay according to what Apple does
-	 */
-	if (uninorth_rev < 0x10) {
-		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
-		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
-			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
-		UN_OUT(UNI_N_ARB_CTRL, actrl);
-	}
-}	
-
-static void __init
-probe_one_macio(const char* name, const char* compat, int type)
-{
-	struct device_node*	node;
-	int			i;
-	volatile u32*		base;
-	u32*			revp;
-	
-	node = find_devices(name);
-	if (!node || !node->n_addrs)
-		return;
-	if (compat)
-		do {
-			if (device_is_compatible(node, compat))
-				break;
-			node = node->next;
-		} while (node);
-	if (!node)
-		return;
-	for(i=0; i<MAX_MACIO_CHIPS; i++) {
-		if (!macio_chips[i].of_node)
-			break;
-		if (macio_chips[i].of_node == node)
-			return;
-	}
-	if (i >= MAX_MACIO_CHIPS) {
-		printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
-		printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
-		return;
-	}
-	base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size);
-	if (!base) {
-		printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
-		return;
-	}
-	if (type == macio_keylargo) {
-		u32* did = (u32 *)get_property(node, "device-id", NULL);
-		if (*did == 0x00000025)
-			type = macio_pangea;
-	}
-	macio_chips[i].of_node	= node;
-	macio_chips[i].type	= type;
-	macio_chips[i].base	= base;
-	macio_chips[i].flags	= MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
-	revp = (u32 *)get_property(node, "revision-id", NULL);
-	if (revp)
-		macio_chips[i].rev = *revp;
-	printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
-		macio_names[type], macio_chips[i].rev, macio_chips[i].base);
-}
-
-static int __init
-probe_macios(void)
-{
-	/* Warning, ordering is important */
-	probe_one_macio("gc", NULL, macio_grand_central);
-	probe_one_macio("ohare", NULL, macio_ohare);
-	probe_one_macio("pci106b,7", NULL, macio_ohareII);
-	probe_one_macio("mac-io", "keylargo", macio_keylargo);
-	probe_one_macio("mac-io", "paddington", macio_paddington);
-	probe_one_macio("mac-io", "gatwick", macio_gatwick);
-	probe_one_macio("mac-io", "heathrow", macio_heathrow);
-
-	/* Make sure the "main" macio chip appear first */
-	if (macio_chips[0].type == macio_gatwick
-	    && macio_chips[1].type == macio_heathrow) {
-		struct macio_chip temp = macio_chips[0];
-		macio_chips[0] = macio_chips[1];
-		macio_chips[1] = temp;
-	}
-	if (macio_chips[0].type == macio_ohareII
-	    && macio_chips[1].type == macio_ohare) {
-		struct macio_chip temp = macio_chips[0];
-		macio_chips[0] = macio_chips[1];
-		macio_chips[1] = temp;
-	}
-
-	return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
-}
-
-static void __init
-initial_serial_shutdown(struct device_node* np)
-{
-	int len;
-	struct slot_names_prop {
-		int	count;
-		char	name[1];
-	} *slots;
-	char *conn;
-	int port_type = PMAC_SCC_ASYNC;
-	int modem = 0;
-	
-	slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
-	conn = get_property(np, "AAPL,connector", &len);
-	if (conn && (strcmp(conn, "infrared") == 0))
-		port_type = PMAC_SCC_IRDA;
-	else if (device_is_compatible(np, "cobalt"))
-		modem = 1;
-	else if (slots && slots->count > 0) {
-		if (strcmp(slots->name, "IrDA") == 0)
-			port_type = PMAC_SCC_IRDA;
-		else if (strcmp(slots->name, "Modem") == 0)
-			modem = 1;
-	}
-	if (modem)
-		pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
-	pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
-}
-
-static void __init
-set_initial_features(void)
-{
-	struct device_node* np;
-	
-	/* That hack appears to be necessary for some StarMax motherboards
-	 * but I'm not too sure it was audited for side-effects on other
-	 * ohare based machines...
-	 * Since I still have difficulties figuring the right way to
-	 * differenciate them all and since that hack was there for a long
-	 * time, I'll keep it around
-	 */
-	if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
-		struct macio_chip* macio = &macio_chips[0];
-		MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
-	} else if (macio_chips[0].type == macio_ohare) {
-		struct macio_chip* macio = &macio_chips[0];
-		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
-	} else if (macio_chips[1].type == macio_ohare) {
-		struct macio_chip* macio = &macio_chips[1];
-		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
-	}
-
-	if (macio_chips[0].type == macio_keylargo ||
-	    macio_chips[0].type == macio_pangea) {
-		/* Enable GMAC for now for PCI probing. It will be disabled
-		 * later on after PCI probe
-		 */
-		np = find_devices("ethernet");
-		while(np) {
-			if (np->parent
-			    && device_is_compatible(np->parent, "uni-north")
-			    && device_is_compatible(np, "gmac"))
-				core99_gmac_enable(np, 0, 1);
-			np = np->next;
-		}
-
-		/* Enable FW before PCI probe. Will be disabled later on
-		 * Note: We should have a batter way to check that we are
-		 * dealing with uninorth internal cell and not a PCI cell
-		 * on the external PCI. The code below works though.
-		 */
-		np = find_devices("firewire");
-		while(np) {
-			if (np->parent
-			    && device_is_compatible(np->parent, "uni-north")
-			    && (device_is_compatible(np, "pci106b,18") || 
-	     		        device_is_compatible(np, "pci106b,30") ||
-	     		        device_is_compatible(np, "pci11c1,5811"))) {
-				macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
-				core99_firewire_enable(np, 0, 1);
-			}
-			np = np->next;
-		}
-		
-		/* Switch airport off */
-		np = find_devices("radio");
-		while(np) {
-			if (np && np->parent == macio_chips[0].of_node) {
-				macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
-				core99_airport_enable(np, 0, 0);
-			}
-			np = np->next;
-		}
-	}
-
-	/* On all machines that support sound PM, switch sound off */
-	if (macio_chips[0].of_node)
-		pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
-			macio_chips[0].of_node, 0, 0);
-
-	/* While on some desktop G3s, we turn it back on */
-	if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
-		&& (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
-		    pmac_mb.model_id == PMAC_TYPE_SILK)) {
-		struct macio_chip* macio = &macio_chips[0];
-		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
-		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
-	}
-
-
-	/* On all machines, switch modem & serial ports off */
-	np = find_devices("ch-a");
-	while(np) {
-		initial_serial_shutdown(np);
-		np = np->next;
-	}
-	np = find_devices("ch-b");
-	while(np) {
-		initial_serial_shutdown(np);
-		np = np->next;
-	}
-	
-	/* Let hardware settle down */
-	mdelay(10);
-}
-
-void __init
-pmac_feature_init(void)
-{
-	/* Detect the UniNorth memory controller */
-	probe_uninorth();
-
-	/* Probe mac-io controllers */
-	if (probe_macios()) {
-		printk(KERN_WARNING "No mac-io chip found\n");
-		return;
-	}
-
-	/* Probe machine type */
-	if (probe_motherboard())
-		printk(KERN_WARNING "Unknown PowerMac !\n");
-
-	/* Set some initial features (turn off some chips that will
-	 * be later turned on)
-	 */
-	set_initial_features();
-}
-
-void __init
-pmac_feature_late_init(void)
-{
-	struct device_node* np;
-	
-	/* Request some resources late */
-	if (uninorth_node)
-		request_OF_resource(uninorth_node, 0, NULL);
-	np = find_devices("hammerhead");
-	if (np)
-		request_OF_resource(np, 0, NULL);
-	np = find_devices("interrupt-controller");
-	if (np)
-		request_OF_resource(np, 0, NULL);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_nvram.c linux/arch/ppc/kernel/pmac_nvram.c
--- linux.orig/arch/ppc/kernel/pmac_nvram.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_nvram.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,402 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_nvram.c 1.17 12/01/01 20:09:06 benh
- */
-/*
- * Miscellaneous procedures for dealing with the PowerMac hardware.
- */
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/stddef.h>
-#include <linux/nvram.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/prom.h>
-#include <asm/machdep.h>
-#include <asm/nvram.h>
-#include <linux/adb.h>
-#include <linux/pmu.h>
-
-#undef DEBUG
-
-#define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
-
-#define CORE99_SIGNATURE	0x5a
-#define CORE99_ADLER_START	0x14
-
-/* Core99 nvram is a flash */
-#define CORE99_FLASH_STATUS_DONE	0x80
-#define CORE99_FLASH_STATUS_ERR		0x38
-#define CORE99_FLASH_CMD_ERASE_CONFIRM	0xd0
-#define CORE99_FLASH_CMD_ERASE_SETUP	0x20
-#define CORE99_FLASH_CMD_RESET		0xff
-#define CORE99_FLASH_CMD_WRITE_SETUP	0x40
-
-/* CHRP NVRAM header */
-struct chrp_header {
-  u8		signature;
-  u8		cksum;
-  u16		len;
-  char          name[12];
-  u8		data[0];
-};
-
-struct core99_header {
-  struct chrp_header	hdr;
-  u32			adler;
-  u32			generation;
-  u32			reserved[2];
-};
-
-/*
- * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
- */
-static int nvram_naddrs;
-static volatile unsigned char *nvram_addr;
-static volatile unsigned char *nvram_data;
-static int nvram_mult, is_core_99;
-static int core99_bank = 0;
-static int nvram_partitions[3];
-
-/* FIXME: kmalloc fails to allocate the image now that I had to move it
- *        before time_init(). For now, I allocate a static buffer here
- *        but it's a waste of space on all but core99 machines
- */
-#if 0
-static char* nvram_image;
-#else
-static char nvram_image[NVRAM_SIZE] __pmacdata;
-#endif
-
-extern int pmac_newworld;
-
-static u8 __openfirmware
-chrp_checksum(struct chrp_header* hdr)
-{
-	u8 *ptr;
-	u16 sum = hdr->signature;
-	for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
-		sum += *ptr;
-	while (sum > 0xFF)
-		sum = (sum & 0xFF) + (sum>>8);
-	return sum;
-}
-
-static u32 __pmac
-core99_calc_adler(u8 *buffer)
-{
-	int cnt;
-	u32 low, high;
-
-   	buffer += CORE99_ADLER_START;
-	low = 1;
-	high = 0;
-	for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
-		if ((cnt % 5000) == 0) {
-			high  %= 65521UL;
-			high %= 65521UL;
-		}
-		low += buffer[cnt];
-		high += low;
-	}
-	low  %= 65521UL;
-	high %= 65521UL;
-  
-	return (high << 16) | low;
-}
-
-static u32 __pmac
-core99_check(u8* datas)
-{
-	struct core99_header* hdr99 = (struct core99_header*)datas;
-
-	if (hdr99->hdr.signature != CORE99_SIGNATURE) {
-#ifdef DEBUG
-		printk("Invalid signature\n");
-#endif		
-		return 0;
-	}
-	if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
-#ifdef DEBUG
-		printk("Invalid checksum\n");
-#endif
-		return 0;
-	}
-	if (hdr99->adler != core99_calc_adler(datas)) {
-#ifdef DEBUG
-		printk("Invalid adler\n");
-#endif
-		return 0;
-	}
-	return hdr99->generation;
-}
-
-static int __pmac
-core99_erase_bank(int bank)
-{
-	int stat, i;
-	
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-	
-	out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
-	out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
-	do { stat = in_8(base); }
-	while(!(stat & CORE99_FLASH_STATUS_DONE));
-	out_8(base, CORE99_FLASH_CMD_RESET);
-	if (stat & CORE99_FLASH_STATUS_ERR) {
-		printk("nvram: flash error 0x%02x on erase !\n", stat);
-		return -ENXIO;
-	}
-	for (i=0; i<NVRAM_SIZE; i++)
-		if (base[i] != 0xff) {
-			printk("nvram: flash erase failed !\n");
-			return -ENXIO;
-		}
-	return 0;
-}
-
-static int __pmac
-core99_write_bank(int bank, u8* datas)
-{
-	int i, stat = 0;
-	
-	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
-	
-	for (i=0; i<NVRAM_SIZE; i++) {
-		out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
-		out_8(base+i, datas[i]);
-		do { stat = in_8(base); }
-		while(!(stat & CORE99_FLASH_STATUS_DONE));
-		if (stat & CORE99_FLASH_STATUS_ERR)
-			break;
-	}
-	out_8(base, CORE99_FLASH_CMD_RESET);
-	if (stat & CORE99_FLASH_STATUS_ERR) {
-		printk("nvram: flash error 0x%02x on write !\n", stat);
-		return -ENXIO;
-	}
-	for (i=0; i<NVRAM_SIZE; i++)
-		if (base[i] != datas[i]) {
-			printk("nvram: flash write failed !\n");
-			return -ENXIO;
-		}
-	return 0;	
-}
-
-static void __init
-lookup_partitions(void)
-{
-	u8 buffer[17];
-	int i, offset;
-	struct chrp_header* hdr;
-
-	if (pmac_newworld) {
-		nvram_partitions[pmac_nvram_OF] = -1;
-		nvram_partitions[pmac_nvram_XPRAM] = -1;
-		nvram_partitions[pmac_nvram_NR] = -1;
-		hdr = (struct chrp_header *)buffer;
-	
-		offset = 0;
-		buffer[16] = 0;
-		do {
-			for (i=0;i<16;i++)
-				buffer[i] = nvram_read_byte(offset+i);
-			if (!strcmp(hdr->name, "common"))
-				nvram_partitions[pmac_nvram_OF] = offset + 0x10;
-			if (!strcmp(hdr->name, "APL,MacOS75")) {
-				nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
-				nvram_partitions[pmac_nvram_NR] = offset + 0x110;
-			}
-			offset += (hdr->len * 0x10);
-		} while(offset < NVRAM_SIZE);
-	} else {
-		nvram_partitions[pmac_nvram_OF] = 0x1800;
-		nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
-		nvram_partitions[pmac_nvram_NR] = 0x1400;
-	}	
-#ifdef DEBUG
-	printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
-	printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
-	printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
-#endif	
-}
-
-void __init
-pmac_nvram_init(void)
-{
-	struct device_node *dp;
-
-	nvram_naddrs = 0;
-
-	dp = find_devices("nvram");
-	if (dp == NULL) {
-		printk(KERN_ERR "Can't find NVRAM device\n");
-		return;
-	}
-	nvram_naddrs = dp->n_addrs;
-	is_core_99 = device_is_compatible(dp, "nvram,flash");
-	if (is_core_99) {
-		int i;
-		u32 gen_bank0, gen_bank1;
-		
-		if (nvram_naddrs < 1) {
-			printk(KERN_ERR "nvram: no address\n");
-			return;
-		}
-#if 0
-		nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
-		if (!nvram_image) {
-			printk(KERN_ERR "nvram: can't allocate image\n");
-			return;
-		}
-#endif
-		nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
-#ifdef DEBUG
-		printk("nvram: Checking bank 0...\n");
-#endif
-		gen_bank0 = core99_check((u8 *)nvram_data);
-		gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
-		core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
-#ifdef DEBUG
-		printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
-		printk("nvram: Active bank is: %d\n", core99_bank);
-#endif
-		for (i=0; i<NVRAM_SIZE; i++)
-			nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
-	} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
-		nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
-				     dp->addrs[0].size);
-		nvram_mult = 1;
-	} else if (nvram_naddrs == 1) {
-		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
-		nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
-	} else if (nvram_naddrs == 2) {
-		nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
-		nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
-	} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
-		nvram_naddrs = -1;
-	} else {
-		printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
-		       nvram_naddrs);
-	}
-	lookup_partitions();
-}
-
-void __pmac
-pmac_nvram_update(void)
-{
-	struct core99_header* hdr99;
-	
-	if (!is_core_99 || !nvram_data || !nvram_image)
-		return;
-	if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
-		NVRAM_SIZE))
-		return;
-#ifdef DEBUG
-	printk("Updating nvram...\n");
-#endif
-	hdr99 = (struct core99_header*)nvram_image;
-	hdr99->generation++;
-	hdr99->hdr.signature = CORE99_SIGNATURE;
-	hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
-	hdr99->adler = core99_calc_adler(nvram_image);
-	core99_bank = core99_bank ? 0 : 1;
-	if (core99_erase_bank(core99_bank)) {
-		printk("nvram: Error erasing bank %d\n", core99_bank);
-		return;
-	}
-	if (core99_write_bank(core99_bank, nvram_image))
-		printk("nvram: Error writing bank %d\n", core99_bank);
-}
-
-unsigned char __openfirmware
-nvram_read_byte(int addr)
-{
-	switch (nvram_naddrs) {
-#ifdef CONFIG_ADB_PMU
-	case -1: {
-		struct adb_request req;
-
-		if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
-				(addr >> 8) & 0xff, addr & 0xff))
-			break;
-		while (!req.complete)
-			pmu_poll();
-		return req.reply[0];
-	}
-#endif
-	case 1:
-		if (is_core_99)
-			return nvram_image[addr];
-		return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
-	case 2:
-		*nvram_addr = addr >> 5;
-		eieio();
-		return nvram_data[(addr & 0x1f) << 4];
-	}
-	return 0;
-}
-
-void __openfirmware
-nvram_write_byte(unsigned char val, int addr)
-{
-	switch (nvram_naddrs) {
-#ifdef CONFIG_ADB_PMU
-	case -1: {
-		struct adb_request req;
-
-		if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
-				(addr >> 8) & 0xff, addr & 0xff, val))
-			break;
-		while (!req.complete)
-			pmu_poll();
-		break;
-	}
-#endif
-	case 1:
-		if (is_core_99) {
-			nvram_image[addr] = val;
-			break;
-		}
-		nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
-		break;
-	case 2:
-		*nvram_addr = addr >> 5;
-		eieio();
-		nvram_data[(addr & 0x1f) << 4] = val;
-		break;
-	}
-	eieio();
-}
-
-int __pmac
-pmac_get_partition(int partition)
-{
-	return nvram_partitions[partition];
-}
-
-u8 __pmac
-pmac_xpram_read(int xpaddr)
-{
-	int offset = nvram_partitions[pmac_nvram_XPRAM];
-	
-	if (offset < 0)
-		return 0;
-		
-	return nvram_read_byte(xpaddr + offset);
-}
-
-void __pmac
-pmac_xpram_write(int xpaddr, u8 data)
-{
-	int offset = nvram_partitions[pmac_nvram_XPRAM];
-	
-	if (offset < 0)
-		return;
-		
-	nvram_write_byte(xpaddr + offset, data);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- linux.orig/arch/ppc/kernel/pmac_pci.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_pci.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,615 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_pci.c 1.35 05/06/02 01:37:30 benh
- */
-/*
- * Support for PCI bridges found on Power Macintoshes.
- * At present the "bandit" and "chaos" bridges are supported.
- * Fortunately you access configuration space in the same
- * way with either bridge.
- *
- * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-
-#include "pci.h"
-
-#undef DEBUG
-
-static void add_bridges(struct device_node *dev);
-
-/* XXX Could be per-controller, but I don't think we risk anything by
- * assuming we won't have both UniNorth and Bandit */
-static int has_uninorth;
-
-/*
- * Magic constants for enabling cache coherency in the bandit/PSX bridge.
- */
-#define BANDIT_DEVID_2	8
-#define BANDIT_REVID	3
-
-#define BANDIT_DEVNUM	11
-#define BANDIT_MAGIC	0x50
-#define BANDIT_COHERENT	0x40
-
-static int __init
-fixup_one_level_bus_range(struct device_node *node, int higher)
-{
-	for (; node != 0;node = node->sibling) {
-		int * bus_range;
-		unsigned int *class_code;			
-		int len;
-
-		/* For PCI<->PCI bridges or CardBus bridges, we go down */
-		class_code = (unsigned int *) get_property(node, "class-code", 0);
-		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
-			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
-			continue;
-		bus_range = (int *) get_property(node, "bus-range", &len);
-		if (bus_range != NULL && len > 2 * sizeof(int)) {
-			if (bus_range[1] > higher)
-				higher = bus_range[1];
-		}
-		higher = fixup_one_level_bus_range(node->child, higher);
-	}
-	return higher;
-}
-
-/* This routine fixes the "bus-range" property of all bridges in the
- * system since they tend to have their "last" member wrong on macs
- * 
- * Note that the bus numbers manipulated here are OF bus numbers, they
- * are not Linux bus numbers.
- */
-static void __init
-fixup_bus_range(struct device_node *bridge)
-{
-	int * bus_range;
-	int len;
-	
-	/* Lookup the "bus-range" property for the hose */		
-	bus_range = (int *) get_property(bridge, "bus-range", &len);
-	if (bus_range == NULL || len < 2 * sizeof(int)) {
-		printk(KERN_WARNING "Can't get bus-range for %s\n",
-			       bridge->full_name);
-		return;
-	}
-	bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
-}
-
-/*
- * Apple MacRISC (UniNorth, Bandit, Chaos) PCI controllers.
- * 
- * The "Bandit" version is present in all early PCI PowerMacs,
- * and up to the first ones using Grackle. Some machines may
- * have 2 bandit controllers (2 PCI busses).
- * 
- * "Chaos" is used in some "Bandit"-type machines as a bridge
- * for the separate display bus. It is accessed the same
- * way as bandit, but cannot be probed for devices. It therefore
- * has its own config access functions.
- *
- * The "UniNorth" version is present in all Core99 machines
- * (iBook, G4, new IMacs, and all the recent Apple machines).
- * It contains 3 controllers in one ASIC.
- */
-
-#define MACRISC_CFA0(devfn, off)	\
-	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
-	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
-	| (((unsigned long)(off)) & 0xFCUL))
-
-#define MACRISC_CFA1(bus, devfn, off)	\
-	((((unsigned long)(bus)) << 16) \
-	|(((unsigned long)(devfn)) << 8) \
-	|(((unsigned long)(off)) & 0xFCUL) \
-	|1UL)
-	
-static unsigned int __pmac
-macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
-{
-	unsigned int caddr;
-	
-	if (bus == hose->first_busno) {
-		if (dev_fn < (11 << 3))
-			return 0;
-		caddr = MACRISC_CFA0(dev_fn, offset);
-	} else
-		caddr = MACRISC_CFA1(bus, dev_fn, offset);
-	
-	/* Uninorth will return garbage if we don't read back the value ! */
-	do {
-		out_le32(hose->cfg_addr, caddr);
-	} while(in_le32(hose->cfg_addr) != caddr);
-
-	offset &= has_uninorth ? 0x07 : 0x03;
-	return (unsigned int)(hose->cfg_data) + (unsigned int)offset;
-}
-
-#define cfg_read(val, addr, type, op, op2)	\
-	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op, op2)	\
-	op((type *)(addr), (val)); (void) op2((type *)(addr))
-
-#define cfg_read_bad(val, size)		*val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte	0xff
-#define bad_word	0xffff
-#define bad_dword	0xffffffffU
-
-#define MACRISC_PCI_OP(rw, size, type, op, op2)				    \
-static int __pmac							    \
-macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val)	    \
-{									    \
-	struct pci_controller *hose = dev->sysdata;			    \
-	unsigned int addr;						    \
-									    \
-	addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
-	if (!addr) {							    \
-		cfg_##rw##_bad(val, size)				    \
-		return PCIBIOS_DEVICE_NOT_FOUND;			    \
-	}								    \
-	cfg_##rw(val, addr, type, op, op2);				    \
-	return PCIBIOS_SUCCESSFUL;					    \
-}
-
-MACRISC_PCI_OP(read, byte, u8 *, in_8, x)
-MACRISC_PCI_OP(read, word, u16 *, in_le16, x)
-MACRISC_PCI_OP(read, dword, u32 *, in_le32, x)
-MACRISC_PCI_OP(write, byte, u8, out_8, in_8)
-MACRISC_PCI_OP(write, word, u16, out_le16, in_le16)
-MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32)
-
-static struct pci_ops macrisc_pci_ops =
-{
-	macrisc_read_config_byte,
-	macrisc_read_config_word,
-	macrisc_read_config_dword,
-	macrisc_write_config_byte,
-	macrisc_write_config_word,
-	macrisc_write_config_dword
-};
-
-/*
- * Verifiy that a specific (bus, dev_fn) exists on chaos
- */
-static int __pmac
-chaos_validate_dev(struct pci_dev *dev, int offset)
-{
-	if(pci_device_to_OF_node(dev) == 0)
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) &&
-	    (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	}
-	return PCIBIOS_SUCCESSFUL;
-}
-
-#define CHAOS_PCI_OP(rw, size, type)					\
-static int __pmac							\
-chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val)	\
-{									\
-	int result = chaos_validate_dev(dev, off);			\
-	if(result == PCIBIOS_BAD_REGISTER_NUMBER) {			\
-		cfg_##rw##_bad(val, size)				\
-		return PCIBIOS_BAD_REGISTER_NUMBER;			\
-	}								\
-	if(result == PCIBIOS_SUCCESSFUL)				\
-		return macrisc_##rw##_config_##size(dev, off, val);	\
-	return result;							\
-}
-
-CHAOS_PCI_OP(read, byte, u8 *)
-CHAOS_PCI_OP(read, word, u16 *)
-CHAOS_PCI_OP(read, dword, u32 *)
-CHAOS_PCI_OP(write, byte, u8)
-CHAOS_PCI_OP(write, word, u16)
-CHAOS_PCI_OP(write, dword, u32) 
-
-static struct pci_ops chaos_pci_ops =
-{
-	chaos_read_config_byte,
-	chaos_read_config_word,
-	chaos_read_config_dword,
-	chaos_write_config_byte,
-	chaos_write_config_word,
-	chaos_write_config_dword
-};
-
-
-/*
- * For a bandit bridge, turn on cache coherency if necessary.
- * N.B. we could clean this up using the hose ops directly.
- */
-static void __init
-init_bandit(struct pci_controller *bp)
-{
-	unsigned int vendev, magic;
-	int rev;
-
-	/* read the word at offset 0 in config space for device 11 */
-	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
-	udelay(2);
-	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
-	if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + 
-			PCI_VENDOR_ID_APPLE) {
-		/* read the revision id */
-		out_le32(bp->cfg_addr,
-			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
-		udelay(2);
-		rev = in_8(bp->cfg_data);
-		if (rev != BANDIT_REVID)
-			printk(KERN_WARNING
-			       "Unknown revision %d for bandit\n", rev);
-	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
-		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
-		return;
-	}
-
-	/* read the word at offset 0x50 */
-	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
-	udelay(2);
-	magic = in_le32((volatile unsigned int *)bp->cfg_data);
-	if ((magic & BANDIT_COHERENT) != 0)
-		return;
-	magic |= BANDIT_COHERENT;
-	udelay(2);
-	out_le32((volatile unsigned int *)bp->cfg_data, magic);
-	printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
-}
-
-
-/*
- * Tweak the PCI-PCI bridge chip on the blue & white G3s.
- */
-static void __init
-init_p2pbridge(void)
-{
-	struct device_node *p2pbridge;
-	struct pci_controller* hose;
-	u8 bus, devfn;
-	u16 val;
-
-	/* XXX it would be better here to identify the specific
-	   PCI-PCI bridge chip we have. */
-	if ((p2pbridge = find_devices("pci-bridge")) == 0
-	    || p2pbridge->parent == NULL
-	    || strcmp(p2pbridge->parent->name, "pci") != 0)
-		return;
-	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
-#ifdef DEBUG
-		printk("Can't find PCI infos for PCI<->PCI bridge\n");
-#endif		
-		return;
-	}
-	/* Warning: At this point, we have not yet renumbered all busses. 
-	 * So we must use OF walking to find out hose
-	 */
-	hose = pci_find_hose_for_OF_device(p2pbridge);
-	if (!hose) {
-#ifdef DEBUG
-		printk("Can't find hose for PCI<->PCI bridge\n");
-#endif		
-		return;
-	}
-	if (early_read_config_word(hose, bus, devfn,
-				   PCI_BRIDGE_CONTROL, &val) < 0) {
-		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
-		return;
-	}
-	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
-	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
-}
-
-void __init
-pmac_find_bridges(void)
-{
-	add_bridges(find_devices("bandit"));
-	add_bridges(find_devices("chaos"));
-	add_bridges(find_devices("pci"));
-	init_p2pbridge();
-}
-
-#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
-				 | (((o) & ~3) << 24))
-
-#define GRACKLE_PICR1_STG		0x00000040
-#define GRACKLE_PICR1_LOOPSNOOP		0x00000010
-
-/* N.B. this is called before bridges is initialized, so we can't
-   use grackle_pcibios_{read,write}_config_dword. */
-static inline void grackle_set_stg(struct pci_controller* bp, int enable)
-{
-	unsigned int val;
-
-	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
-	val = in_le32((volatile unsigned int *)bp->cfg_data);
-	val = enable? (val | GRACKLE_PICR1_STG) :
-		(val & ~GRACKLE_PICR1_STG);
-	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
-	out_le32((volatile unsigned int *)bp->cfg_data, val);
-	(void)in_le32((volatile unsigned int *)bp->cfg_data);
-}
-
-static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
-{
-	unsigned int val;
-
-	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
-	val = in_le32((volatile unsigned int *)bp->cfg_data);
-	val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
-		(val & ~GRACKLE_PICR1_LOOPSNOOP);
-	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
-	out_le32((volatile unsigned int *)bp->cfg_data, val);
-	(void)in_le32((volatile unsigned int *)bp->cfg_data);
-}
-
-static int __init
-setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
-{
-	pci_assign_all_busses = 1;
-	has_uninorth = 1;
-	hose->ops = &macrisc_pci_ops;
-	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
-	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
-	/* We "know" that the bridge at f2000000 has the PCI slots. */
-	return addr->address == 0xf2000000;
-}
-
-static void __init
-setup_bandit(struct pci_controller* hose, struct reg_property* addr)
-{
-	hose->ops = &macrisc_pci_ops;
-	hose->cfg_addr = (volatile unsigned int *)
-		ioremap(addr->address + 0x800000, 0x1000);
-	hose->cfg_data = (volatile unsigned char *)
-		ioremap(addr->address + 0xc00000, 0x1000);
-	init_bandit(hose);
-}
-
-static void __init
-setup_chaos(struct pci_controller* hose, struct reg_property* addr)
-{
-	/* assume a `chaos' bridge */
-	hose->ops = &chaos_pci_ops;
-	hose->cfg_addr = (volatile unsigned int *)
-		ioremap(addr->address + 0x800000, 0x1000);
-	hose->cfg_data = (volatile unsigned char *)
-		ioremap(addr->address + 0xc00000, 0x1000);
-}
-
-void __init
-setup_grackle(struct pci_controller *hose)
-{
-	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
-	if (machine_is_compatible("AAPL,PowerBook1998"))
-		grackle_set_loop_snoop(hose, 1);
-#if 0	/* Disabled for now, HW problems ??? */
-	grackle_set_stg(hose, 1);
-#endif
-}
-
-/*
- * We assume that if we have a G3 powermac, we have one bridge called
- * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
- * if we have one or more bandit or chaos bridges, we don't have a MPC106.
- */
-static void __init
-add_bridges(struct device_node *dev)
-{
-	int len;
-	struct pci_controller *hose;
-	struct reg_property *addr;
-	char* disp_name;
-	int *bus_range;
-	int first = 1, primary;
-	
-	for (; dev != NULL; dev = dev->next) {
-		addr = (struct reg_property *) get_property(dev, "reg", &len);
-		if (addr == NULL || len < sizeof(*addr)) {
-			printk(KERN_WARNING "Can't use %s: no address\n",
-			       dev->full_name);
-			continue;
-		}
-		bus_range = (int *) get_property(dev, "bus-range", &len);
-		if (bus_range == NULL || len < 2 * sizeof(int)) {
-			printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
-				       dev->full_name);
-		}
-		
-		hose = pcibios_alloc_controller();
-		if (!hose)
-			continue;
-		hose->arch_data = dev;
-		hose->first_busno = bus_range ? bus_range[0] : 0;
-		hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
-		disp_name = NULL;
-		primary = first;
-		if (device_is_compatible(dev, "uni-north")) {
-			primary = setup_uninorth(hose, addr);
-			disp_name = "UniNorth";
-		} else if (strcmp(dev->name, "pci") == 0) {
-			/* XXX assume this is a mpc106 (grackle) */
-			setup_grackle(hose);
-			disp_name = "Grackle (MPC106)";
-		} else if (strcmp(dev->name, "bandit") == 0) {
-			setup_bandit(hose, addr);
-			disp_name = "Bandit";
-		} else if (strcmp(dev->name, "chaos") == 0) {
-			setup_chaos(hose, addr);
-			disp_name = "Chaos";
-			primary = 0;
-		}
-		printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
-			disp_name, addr->address, hose->first_busno, hose->last_busno);
-#ifdef DEBUG
-		printk(" ->Hose at 0x%08lx, cfg_addr=0x%08lx,cfg_data=0x%08lx\n",
-			hose, hose->cfg_addr, hose->cfg_data);
-#endif		
-		
-		/* Interpret the "ranges" property */
-		/* This also maps the I/O region and sets isa_io/mem_base */
-		pci_process_bridge_OF_ranges(hose, dev, primary);
-
-		/* Fixup "bus-range" OF property */
-		fixup_bus_range(dev);
-
-		first &= !primary;
-	}
-}
-
-static void __init
-pcibios_fixup_OF_interrupts(void)
-{	
-	struct pci_dev* dev;
-	
-	/*
-	 * Open Firmware often doesn't initialize the
-	 * PCI_INTERRUPT_LINE config register properly, so we
-	 * should find the device node and apply the interrupt
-	 * obtained from the OF device-tree
-	 */
-	pci_for_each_dev(dev) {
-		struct device_node* node = pci_device_to_OF_node(dev);
-		/* this is the node, see if it has interrupts */
-		if (node && node->n_intrs > 0)
-			dev->irq = node->intrs[0].line;
-		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-	}
-}
-
-void __init
-pmac_pcibios_fixup(void)
-{
-	/* Fixup interrupts according to OF tree */
-	pcibios_fixup_OF_interrupts();
-}
-
-int __pmac
-pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
-{
-	struct device_node* node;
-	int updatecfg = 0;
-	int uninorth_child;
-	
-	node = pci_device_to_OF_node(dev);
-	
-	/* We don't want to enable USB controllers absent from the OF tree
-	 * (iBook second controller)
-	 */
-	if (dev->vendor == PCI_VENDOR_ID_APPLE
-	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node)
-		return -EINVAL;
-
-	if (!node)
-		return 0;
-		
-	uninorth_child = node->parent &&
-		device_is_compatible(node->parent, "uni-north");
-		
-	/* Firewire & GMAC were disabled after PCI probe, the driver is
-	 * claiming them, we must re-enable them now.
-	 */
-	if (uninorth_child && !strcmp(node->name, "firewire") && 
-	    (device_is_compatible(node, "pci106b,18") || 
-	     device_is_compatible(node, "pci106b,30") ||
-	     device_is_compatible(node, "pci11c1,5811"))) {
-		pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
-		pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
-		updatecfg = 1;
-	}
-	if (uninorth_child && !strcmp(node->name, "ethernet") && 
-	    device_is_compatible(node, "gmac")) {
-		pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
-		updatecfg = 1;
-	}
-
-	if (updatecfg) {
-		u16 cmd;
-		
-		/*
-		 * Make sure PCI is correctly configured
-		 *
-		 * We use old pci_bios versions of the function since, by
-		 * default, gmac is not powered up, and so will be absent
-		 * from the kernel initial PCI lookup. 
-		 * 
-		 * Should be replaced by 2.4 new PCI mecanisms and really
-		 * regiser the device.
-		 */
-		pci_read_config_word(dev, PCI_COMMAND, &cmd);
-		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
-    		pci_write_config_word(dev, PCI_COMMAND, cmd);
-    		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
-    		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
-	}
-	
-	return 0;
-}
-
-/* We power down some devices after they have been probed. They'll
- * be powered back on later on
- */
-void __init
-pmac_pcibios_after_init(void)
-{
-	struct device_node* nd;
-
-#ifdef CONFIG_BLK_DEV_IDE
-	struct pci_dev *dev;
-
-	/* OF fails to initialize IDE controllers on macs
-	 * (and maybe other machines)
-	 * 
-	 * Ideally, this should be moved to the IDE layer, but we need
-	 * to check specifically with Andre Hedrick how to do it cleanly
-	 * since the common IDE code seem to care about the fact that the
-	 * BIOS may have disabled a controller.
-	 * 
-	 * -- BenH
-	 */
-	pci_for_each_dev(dev) {
-		if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
-			pci_enable_device(dev);
-	}
-#endif /* CONFIG_BLK_DEV_IDE */
-
-	nd = find_devices("firewire");
-	while (nd) {
-		if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
-				   device_is_compatible(nd, "pci106b,30") ||
-				   device_is_compatible(nd, "pci11c1,5811"))
-		    && device_is_compatible(nd->parent, "uni-north")) {
-			pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
-			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
-		}
-		nd = nd->next;
-	}
-	nd = find_devices("ethernet");
-	while (nd) {
-		if (nd->parent && device_is_compatible(nd, "gmac")
-		    && device_is_compatible(nd->parent, "uni-north"))
-			pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
-		nd = nd->next;
-	}
-}
-
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- linux.orig/arch/ppc/kernel/pmac_pic.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_pic.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,528 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_pic.c 1.24 12/19/01 10:53:01 paulus
- */
-#include <linux/config.h>
-#include <linux/stddef.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/pci.h>
-
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/smp.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/time.h>
-
-#include "pmac_pic.h"
-#include "open_pic.h"
-
-struct pmac_irq_hw {
-        unsigned int    event;
-        unsigned int    enable;
-        unsigned int    ack;
-        unsigned int    level;
-};
-
-/* Default addresses */
-static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = {
-        (struct pmac_irq_hw *) 0xf3000020,
-        (struct pmac_irq_hw *) 0xf3000010,
-        (struct pmac_irq_hw *) 0xf4000020,
-        (struct pmac_irq_hw *) 0xf4000010,
-};
-
-#define GC_LEVEL_MASK		0x3ff00000
-#define OHARE_LEVEL_MASK	0x1ff00000
-#define HEATHROW_LEVEL_MASK	0x1ff00000
-
-static int max_irqs __pmacdata;
-static int max_real_irqs __pmacdata;
-static u32 level_mask[4] __pmacdata;
-
-static spinlock_t pmac_pic_lock __pmacdata = SPIN_LOCK_UNLOCKED;
-
-
-#define GATWICK_IRQ_POOL_SIZE        10
-static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata;
-
-/*
- * Mark an irq as "lost".  This is only used on the pmac
- * since it can lose interrupts (see pmac_set_irq_mask).
- * -- Cort
- */
-void __pmac
-__set_lost(unsigned long irq_nr, int nokick)
-{
-	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
-		atomic_inc(&ppc_n_lost_interrupts);
-		if (!nokick)
-			set_dec(1);
-	}
-}
-
-static void __pmac
-pmac_mask_and_ack_irq(unsigned int irq_nr)
-{
-        unsigned long bit = 1UL << (irq_nr & 0x1f);
-        int i = irq_nr >> 5;
-        unsigned long flags;
-
-        if ((unsigned)irq_nr >= max_irqs)
-                return;
-
-        clear_bit(irq_nr, ppc_cached_irq_mask);
-        if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
-                atomic_dec(&ppc_n_lost_interrupts);
-	spin_lock_irqsave(&pmac_pic_lock, flags);
-        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
-        out_le32(&pmac_irq_hw[i]->ack, bit);
-        do {
-                /* make sure ack gets to controller before we enable
-                   interrupts */
-                mb();
-        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
-                != (ppc_cached_irq_mask[i] & bit));
-	spin_unlock_irqrestore(&pmac_pic_lock, flags);
-}
-
-static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
-{
-        unsigned long bit = 1UL << (irq_nr & 0x1f);
-        int i = irq_nr >> 5;
-        unsigned long flags;
-
-        if ((unsigned)irq_nr >= max_irqs)
-                return;
-
-	spin_lock_irqsave(&pmac_pic_lock, flags);
-        /* enable unmasked interrupts */
-        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
-
-        do {
-                /* make sure mask gets to controller before we
-                   return to user */
-                mb();
-        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
-                != (ppc_cached_irq_mask[i] & bit));
-
-        /*
-         * Unfortunately, setting the bit in the enable register
-         * when the device interrupt is already on *doesn't* set
-         * the bit in the flag register or request another interrupt.
-         */
-        if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
-		__set_lost((ulong)irq_nr, nokicklost);
-	spin_unlock_irqrestore(&pmac_pic_lock, flags);
-}
-
-static void __pmac pmac_mask_irq(unsigned int irq_nr)
-{
-        clear_bit(irq_nr, ppc_cached_irq_mask);
-        pmac_set_irq_mask(irq_nr, 0);
-        mb();
-}
-
-static void __pmac pmac_unmask_irq(unsigned int irq_nr)
-{
-        set_bit(irq_nr, ppc_cached_irq_mask);
-        pmac_set_irq_mask(irq_nr, 0);
-}
-
-static void __pmac pmac_end_irq(unsigned int irq_nr)
-{
-	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
-        	set_bit(irq_nr, ppc_cached_irq_mask);
-	        pmac_set_irq_mask(irq_nr, 1);
-	}
-}
-
-
-struct hw_interrupt_type pmac_pic = {
-        " PMAC-PIC ",
-        NULL,
-        NULL,
-        pmac_unmask_irq,
-        pmac_mask_irq,
-        pmac_mask_and_ack_irq,
-        pmac_end_irq,
-        NULL
-};
-
-struct hw_interrupt_type gatwick_pic = {
-	" GATWICK  ",
-	NULL,
-	NULL,
-	pmac_unmask_irq,
-	pmac_mask_irq,
-	pmac_mask_and_ack_irq,
-	pmac_end_irq,
-	NULL
-};
-
-static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
-{
-	int irq, bits;
-	
-	for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
-		int i = irq >> 5;
-		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
-		/* We must read level interrupts from the level register */
-		bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
-		bits &= ppc_cached_irq_mask[i];
-		if (bits == 0)
-			continue;
-		irq += __ilog2(bits);
-		break;
-	}
-	/* The previous version of this code allowed for this case, we
-	 * don't.  Put this here to check for it.
-	 * -- Cort
-	 */
-	if ( irq_desc[irq].handler != &gatwick_pic )
-		printk("gatwick irq not from gatwick pic\n");
-	else
-		ppc_irq_dispatch_handler( regs, irq );
-}
-
-int
-pmac_get_irq(struct pt_regs *regs)
-{
-	int irq;
-	unsigned long bits = 0;
-
-#ifdef CONFIG_SMP
-	void psurge_smp_message_recv(struct pt_regs *);
-	
-       	/* IPI's are a hack on the powersurge -- Cort */
-       	if ( smp_processor_id() != 0 ) {
-		psurge_smp_message_recv(regs);
-		return -2;	/* ignore, already handled */
-        }
-#endif /* CONFIG_SMP */
-	for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
-		int i = irq >> 5;
-		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
-		/* We must read level interrupts from the level register */
-		bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
-		bits &= ppc_cached_irq_mask[i];
-		if (bits == 0)
-			continue;
-		irq += __ilog2(bits);
-		break;
-	}
-
-	return irq;
-}
-
-/* This routine will fix some missing interrupt values in the device tree
- * on the gatwick mac-io controller used by some PowerBooks
- */
-static void __init
-pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
-{
-	struct device_node *node;
-	int count;
-	
-	memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
-	node = gw->child;
-	count = 0;
-	while(node)
-	{
-		/* Fix SCC */
-		if (strcasecmp(node->name, "escc") == 0)
-			if (node->child) {
-				if (node->child->n_intrs < 3) {
-					node->child->intrs = &gatwick_int_pool[count];
-					count += 3;
-				}
-				node->child->n_intrs = 3;				
-				node->child->intrs[0].line = 15+irq_base;
-				node->child->intrs[1].line =  4+irq_base;
-				node->child->intrs[2].line =  5+irq_base;
-				printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
-					node->child->intrs[0].line,
-					node->child->intrs[1].line,
-					node->child->intrs[2].line);
-			}
-		/* Fix media-bay & left SWIM */
-		if (strcasecmp(node->name, "media-bay") == 0) {
-			struct device_node* ya_node;
-
-			if (node->n_intrs == 0)
-				node->intrs = &gatwick_int_pool[count++];
-			node->n_intrs = 1;
-			node->intrs[0].line = 29+irq_base;
-			printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
-					node->intrs[0].line);
-			
-			ya_node = node->child;
-			while(ya_node)
-			{
-				if (strcasecmp(ya_node->name, "floppy") == 0) {
-					if (ya_node->n_intrs < 2) {
-						ya_node->intrs = &gatwick_int_pool[count];
-						count += 2;
-					}
-					ya_node->n_intrs = 2;
-					ya_node->intrs[0].line = 19+irq_base;
-					ya_node->intrs[1].line =  1+irq_base;
-					printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
-						ya_node->intrs[0].line, ya_node->intrs[1].line);
-				} 
-				if (strcasecmp(ya_node->name, "ata4") == 0) {
-					if (ya_node->n_intrs < 2) {
-						ya_node->intrs = &gatwick_int_pool[count];
-						count += 2;
-					}
-					ya_node->n_intrs = 2;
-					ya_node->intrs[0].line = 14+irq_base;
-					ya_node->intrs[1].line =  3+irq_base;
-					printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
-						ya_node->intrs[0].line, ya_node->intrs[1].line);
-				} 
-				ya_node = ya_node->sibling;
-			}
-		}
-		node = node->sibling;
-	}
-	if (count > 10) {
-		printk("WARNING !! Gatwick interrupt pool overflow\n");
-		printk("  GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
-		printk("              requested = %d\n", count);
-	}
-}
-
-/*
- * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
- * card which includes an ohare chip that acts as a second interrupt
- * controller.  If we find this second ohare, set it up and fix the
- * interrupt value in the device tree for the ethernet chip.
- */
-static int __init enable_second_ohare(void)
-{
-	unsigned char bus, devfn;
-	unsigned short cmd;
-        unsigned long addr;
-	struct device_node *irqctrler = find_devices("pci106b,7");
-	struct device_node *ether;
-
-	if (irqctrler == NULL || irqctrler->n_addrs <= 0)
-		return -1;
-	addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
-	pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
-	max_irqs = 64;
-	if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
-		struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
-		if (!hose)
-		    printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
-		else {
-		    early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
-		    cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
-	  	    cmd &= ~PCI_COMMAND_IO;
-		    early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
-		}
-	}
-
-	/* Fix interrupt for the modem/ethernet combo controller. The number
-	   in the device tree (27) is bogus (correct for the ethernet-only
-	   board but not the combo ethernet/modem board).
-	   The real interrupt is 28 on the second controller -> 28+32 = 60.
-	*/
-	ether = find_devices("pci1011,14");
-	if (ether && ether->n_intrs > 0) {
-		ether->intrs[0].line = 60;
-		printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
-		       ether->intrs[0].line);
-	}
-
-	/* Return the interrupt number of the cascade */
-	return irqctrler->intrs[0].line;
-}
-
-void __init
-pmac_pic_init(void)
-{
-        int i;
-        struct device_node *irqctrler;
-        unsigned long addr;
-	int irq_cascade = -1;
-	
-	/* We first try to detect Apple's new Core99 chipset, since mac-io
-	 * is quite different on those machines and contains an IBM MPIC2.
-	 */
-	irqctrler = find_type_devices("open-pic");
-	if (irqctrler != NULL)
-	{
-		printk("PowerMac using OpenPIC irq controller\n");
-		if (irqctrler->n_addrs > 0)
-		{
-			int nmi_irq = -1;
-			unsigned char senses[NR_IRQS];
-#ifdef CONFIG_XMON
-			struct device_node* pswitch;
-
-			pswitch = find_devices("programmer-switch");
-			if (pswitch && pswitch->n_intrs)
-				nmi_irq = pswitch->intrs[0].line;
-#endif /* CONFIG_XMON */
-			prom_get_irq_senses(senses, 0, NR_IRQS);
-			OpenPIC_InitSenses = senses;
-			OpenPIC_NumInitSenses = NR_IRQS;
-			ppc_md.get_irq = openpic_get_irq;
-			OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
-					       irqctrler->addrs[0].size);
-			openpic_init(1, 0, 0, nmi_irq);
-#ifdef CONFIG_XMON
-			if (nmi_irq >= 0)
-				request_irq(nmi_irq, xmon_irq, 0,
-					    "NMI - XMON", 0);
-#endif	/* CONFIG_XMON */
-			return;
-		}
-		irqctrler = NULL;
-	}
-
-	/* Get the level/edge settings, assume if it's not
-	 * a Grand Central nor an OHare, then it's an Heathrow
-	 * (or Paddington).
-	 */
-	if (find_devices("gc"))
-		level_mask[0] = GC_LEVEL_MASK;
-	else if (find_devices("ohare")) {
-		level_mask[0] = OHARE_LEVEL_MASK;
-		/* We might have a second cascaded ohare */
-		level_mask[1] = OHARE_LEVEL_MASK;
-	} else {
-		level_mask[0] = HEATHROW_LEVEL_MASK;
-		level_mask[1] = 0;
-		/* We might have a second cascaded heathrow */
-		level_mask[2] = HEATHROW_LEVEL_MASK;
-		level_mask[3] = 0;
-	}
-
-	/*
-	 * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
-	 * 1998 G3 Series PowerBooks have 128, 
-	 * other powermacs have 32.
-	 * The combo ethernet/modem card for the Powerstar powerbooks
-	 * (2400/3400/3500, ohare based) has a second ohare chip
-	 * effectively making a total of 64.
-	 */
-	max_irqs = max_real_irqs = 32;
-	irqctrler = find_devices("mac-io");
-	if (irqctrler)
-	{
-		max_real_irqs = 64;
-		if (irqctrler->next)
-			max_irqs = 128;
-		else
-			max_irqs = 64;
-	}
-	for ( i = 0; i < max_real_irqs ; i++ )
-		irq_desc[i].handler = &pmac_pic;
-
-	/* get addresses of first controller */
-	if (irqctrler) {
-		if  (irqctrler->n_addrs > 0) {
-			addr = (unsigned long) 
-				ioremap(irqctrler->addrs[0].address, 0x40);
-			for (i = 0; i < 2; ++i)
-				pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
-					(addr + (2 - i) * 0x10);
-		}
-		
-		/* get addresses of second controller */
-		irqctrler = irqctrler->next;
-		if (irqctrler && irqctrler->n_addrs > 0) {
-			addr = (unsigned long) 
-				ioremap(irqctrler->addrs[0].address, 0x40);
-			for (i = 2; i < 4; ++i)
-				pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
-					(addr + (4 - i) * 0x10);
-			irq_cascade = irqctrler->intrs[0].line;
-			if (device_is_compatible(irqctrler, "gatwick"))
-				pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
-		}
-	} else {
-		/* older powermacs have a GC (grand central) or ohare at
-		   f3000000, with interrupt control registers at f3000020. */
-		addr = (unsigned long) ioremap(0xf3000000, 0x40);
-		pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
-	}
-
-	/* PowerBooks 3400 and 3500 can have a second controller in a second
-	   ohare chip, on the combo ethernet/modem card */
-	if (machine_is_compatible("AAPL,3400/2400")
-	     || machine_is_compatible("AAPL,3500"))
-		irq_cascade = enable_second_ohare();
-
-	/* disable all interrupts in all controllers */
-	for (i = 0; i * 32 < max_irqs; ++i)
-		out_le32(&pmac_irq_hw[i]->enable, 0);
-	/* mark level interrupts */
-	for (i = 0; i < max_irqs; i++)
-		if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
-			irq_desc[i].status = IRQ_LEVEL;
-	
-	/* get interrupt line of secondary interrupt controller */
-	if (irq_cascade >= 0) {
-		printk(KERN_INFO "irq: secondary controller on irq %d\n",
-			(int)irq_cascade);
-		for ( i = max_real_irqs ; i < max_irqs ; i++ )
-			irq_desc[i].handler = &gatwick_pic;
-		request_irq( irq_cascade, gatwick_action, SA_INTERRUPT,
-			     "cascade", 0 );
-	}
-	printk("System has %d possible interrupts\n", max_irqs);
-	if (max_irqs != max_real_irqs)
-		printk(KERN_DEBUG "%d interrupts on main controller\n",
-			max_real_irqs);
-
-#ifdef CONFIG_XMON
-	request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
-#endif	/* CONFIG_XMON */
-}
-
-#ifdef CONFIG_PMAC_PBOOK
-/*
- * These procedures are used in implementing sleep on the powerbooks.
- * sleep_save_intrs() saves the states of all interrupt enables
- * and disables all interrupts except for the nominated one.
- * sleep_restore_intrs() restores the states of all interrupt enables.
- */
-unsigned int sleep_save_mask[2];
-
-void __pmac
-pmac_sleep_save_intrs(int viaint)
-{
-	sleep_save_mask[0] = ppc_cached_irq_mask[0];
-	sleep_save_mask[1] = ppc_cached_irq_mask[1];
-	ppc_cached_irq_mask[0] = 0;
-	ppc_cached_irq_mask[1] = 0;
-	if (viaint > 0)
-		set_bit(viaint, ppc_cached_irq_mask);
-	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
-	if (max_real_irqs > 32)
-		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
-	(void)in_le32(&pmac_irq_hw[0]->event);
-	/* make sure mask gets to controller before we return to caller */
-	mb();
-        (void)in_le32(&pmac_irq_hw[0]->enable);
-}
-
-void __pmac
-pmac_sleep_restore_intrs(void)
-{
-	int i;
-
-	out_le32(&pmac_irq_hw[0]->enable, 0);
-	if (max_real_irqs > 32)
-		out_le32(&pmac_irq_hw[1]->enable, 0);
-	mb();
-	for (i = 0; i < max_real_irqs; ++i)
-		if (test_bit(i, sleep_save_mask))
-			pmac_unmask_irq(i);
-}
-#endif /* CONFIG_PMAC_PBOOK */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_pic.h linux/arch/ppc/kernel/pmac_pic.h
--- linux.orig/arch/ppc/kernel/pmac_pic.h	2001-08-28 13:58:33.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_pic.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,14 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_pic.h 1.9 08/19/01 22:23:04 paulus
- */
-#ifndef _PPC_KERNEL_PMAC_PIC_H
-#define _PPC_KERNEL_PMAC_PIC_H
-
-#include "local_irq.h"
-
-extern struct hw_interrupt_type pmac_pic;
-
-void pmac_pic_init(void);
-int pmac_get_irq(struct pt_regs *regs);
-
-#endif /* _PPC_KERNEL_PMAC_PIC_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- linux.orig/arch/ppc/kernel/pmac_setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,957 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_setup.c 1.54 04/16/02 20:08:22 paulus
- */
-/*
- *  linux/arch/ppc/kernel/setup.c
- *
- *  PowerPC version 
- *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *
- *  Adapted for Power Macintosh by Paul Mackerras
- *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
- *
- *  Derived from "arch/alpha/kernel/setup.c"
- *    Copyright (C) 1995 Linus Torvalds
- *
- *  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.
- *
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/init.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/slab.h>
-#include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/major.h>
-#include <linux/blk.h>
-#include <linux/vt_kern.h>
-#include <linux/console.h>
-#include <linux/ide.h>
-#include <linux/pci.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-#include <linux/seq_file.h>
-#include <linux/blkdev.h>
-#include <linux/genhd.h>
-
-#include <asm/processor.h>
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/bitops.h>
-#include <asm/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/ohare.h>
-#include <asm/mediabay.h>
-#include <asm/machdep.h>
-#include <asm/keyboard.h>
-#include <asm/dma.h>
-#include <asm/bootx.h>
-#include <asm/cputable.h>
-#include <asm/btext.h>
-#include <asm/pmac_feature.h>
-#include <asm/time.h>
-
-#include "local_irq.h"
-#include "pmac_pic.h"
-#include "mem_pieces.h"
-#include "scsi.h" /* sd_find_target */
-#include "sd.h"
-
-extern long pmac_time_init(void);
-extern unsigned long pmac_get_rtc_time(void);
-extern int pmac_set_rtc_time(unsigned long nowtime);
-extern void pmac_read_rtc_time(void);
-extern void pmac_calibrate_decr(void);
-extern void pmac_pcibios_fixup(void);
-extern void pmac_find_bridges(void);
-extern int pmac_ide_check_base(ide_ioreg_t base);
-extern ide_ioreg_t pmac_ide_get_base(int index);
-extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
-	ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
-
-extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int mackbd_getkeycode(unsigned int scancode);
-extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep,
-		     char raw_mode);
-extern char mackbd_unexpected_up(unsigned char keycode);
-extern void mackbd_leds(unsigned char leds);
-extern void __init mackbd_init_hw(void);
-extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
-				 char raw_mode);
-extern char mac_hid_kbd_unexpected_up(unsigned char keycode);
-extern void mac_hid_init_hw(void);
-extern unsigned char mac_hid_kbd_sysrq_xlate[];
-extern unsigned char pckbd_sysrq_xlate[];
-extern unsigned char mackbd_sysrq_xlate[];
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
-			   char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern int keyboard_sends_linux_keycodes;
-extern void pmac_nvram_update(void);
-
-extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
-extern void pmac_pcibios_after_init(void);
-
-struct device_node *memory_node;
-
-unsigned char drive_info;
-
-int ppc_override_l2cr = 0;
-int ppc_override_l2cr_value;
-int has_l2cache = 0;
-
-static int current_root_goodness = -1;
-
-extern char saved_command_line[];
-
-extern int pmac_newworld;
-
-#define DEFAULT_ROOT_DEVICE 0x0801	/* sda1 - slightly silly choice */
-
-extern void zs_kgdb_hook(int tty_num);
-static void ohare_init(void);
-#ifdef CONFIG_BOOTX_TEXT
-void pmac_progress(char *s, unsigned short hex);
-#endif
-
-sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
-
-#ifdef CONFIG_SMP
-extern struct smp_ops_t psurge_smp_ops;
-extern struct smp_ops_t core99_smp_ops;
-#endif /* CONFIG_SMP */
-
-/*
- * Assume here that all clock rates are the same in a
- * smp system.  -- Cort
- */
-int __openfirmware
-of_show_percpuinfo(struct seq_file *m, int i)
-{
-	struct device_node *cpu_node;
-	int *fp, s;
-			
-	cpu_node = find_type_devices("cpu");
-	if (!cpu_node)
-		return 0;
-	for (s = 0; s < i && cpu_node->next; s++)
-		cpu_node = cpu_node->next;
-	fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
-	if (fp)
-		seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
-	return 0;
-}
-
-int __pmac
-pmac_show_cpuinfo(struct seq_file *m)
-{
-	struct device_node *np;
-	char *pp;
-	int plen;
-	int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
-		NULL, PMAC_MB_INFO_MODEL, 0);
-	unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
-		NULL, PMAC_MB_INFO_FLAGS, 0);
-	char* mbname;
-
-	if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
-		mbname = "Unknown";
-		
-	/* find motherboard type */
-	seq_printf(m, "machine\t\t: ");
-	np = find_devices("device-tree");
-	if (np != NULL) {
-		pp = (char *) get_property(np, "model", NULL);
-		if (pp != NULL)
-			seq_printf(m, "%s\n", pp);
-		else
-			seq_printf(m, "PowerMac\n");
-		pp = (char *) get_property(np, "compatible", &plen);
-		if (pp != NULL) {
-			seq_printf(m, "motherboard\t:");
-			while (plen > 0) {
-				int l = strlen(pp) + 1;
-				seq_printf(m, " %s", pp);
-				plen -= l;
-				pp += l;
-			}
-			seq_printf(m, "\n");
-		}
-	} else
-		seq_printf(m, "PowerMac\n");
-
-	/* print parsed model */
-	seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
-	seq_printf(m, "pmac flags\t: %08x\n", mbflags);
-	
-	/* find l2 cache info */
-	np = find_devices("l2-cache");
-	if (np == 0)
-		np = find_type_devices("cache");
-	if (np != 0) {
-		unsigned int *ic = (unsigned int *)
-			get_property(np, "i-cache-size", NULL);
-		unsigned int *dc = (unsigned int *)
-			get_property(np, "d-cache-size", NULL);
-		seq_printf(m, "L2 cache\t:");
-		has_l2cache = 1;
-		if (get_property(np, "cache-unified", NULL) != 0 && dc) {
-			seq_printf(m, " %dK unified", *dc / 1024);
-		} else {
-			if (ic)
-				seq_printf(m, " %dK instruction", *ic / 1024);
-			if (dc)
-				seq_printf(m, "%s %dK data",
-					   (ic? " +": ""), *dc / 1024);
-		}
-		pp = get_property(np, "ram-type", NULL);
-		if (pp)
-			seq_printf(m, " %s", pp);
-		seq_printf(m, "\n");
-	}
-
-	/* find ram info */
-	np = find_devices("memory");
-	if (np != 0) {
-		int n;
-		struct reg_property *reg = (struct reg_property *)
-			get_property(np, "reg", &n);
-		
-		if (reg != 0) {
-			unsigned long total = 0;
-
-			for (n /= sizeof(struct reg_property); n > 0; --n)
-				total += (reg++)->size;
-			seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
-		}
-	}
-
-	/* Checks "l2cr-value" property in the registry */
-	np = find_devices("cpus");		
-	if (np == 0)
-		np = find_type_devices("cpu");		
-	if (np != 0) {
-		unsigned int *l2cr = (unsigned int *)
-			get_property(np, "l2cr-value", NULL);
-		if (l2cr != 0) {
-			seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
-		}
-	}
-	
-	/* Indicate newworld/oldworld */
-	seq_printf(m, "pmac-generation\t: %s\n",
-		   pmac_newworld ? "NewWorld" : "OldWorld");
-	
-
-	return 0;
-}
-
-#ifdef CONFIG_VT
-/*
- * Dummy mksound function that does nothing.
- * The real one is in the dmasound driver.
- */
-static void __pmac
-pmac_mksound(unsigned int hz, unsigned int ticks)
-{
-}
-#endif /* CONFIG_VT */
-
-static volatile u32 *sysctrl_regs;
-
-void __init
-pmac_setup_arch(void)
-{
-	struct device_node *cpu;
-	int *fp;
-	unsigned long pvr;
-	
-	pvr = PVR_VER(mfspr(PVR));
-
-	/* Set loops_per_jiffy to a half-way reasonable value,
-	   for use until calibrate_delay gets called. */
-	cpu = find_type_devices("cpu");
-	if (cpu != 0) {
-		fp = (int *) get_property(cpu, "clock-frequency", NULL);
-		if (fp != 0) {
-			if (pvr == 4 || pvr >= 8)
-				/* 604, G3, G4 etc. */
-				loops_per_jiffy = *fp / HZ;
-			else
-				/* 601, 603, etc. */
-				loops_per_jiffy = *fp / (2*HZ);
-		} else
-			loops_per_jiffy = 50000000 / HZ;
-	}
-
-	/* this area has the CPU identification register
-	   and some registers used by smp boards */
-	sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
-	ohare_init();
-
-	/* Lookup PCI hosts */
-	pmac_find_bridges();
-	
-	/* Checks "l2cr-value" property in the registry */
-	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
-		struct device_node *np = find_devices("cpus");		
-		if (np == 0)
-			np = find_type_devices("cpu");		
-		if (np != 0) {
-			unsigned int *l2cr = (unsigned int *)
-				get_property(np, "l2cr-value", NULL);
-			if (l2cr != 0) {
-				ppc_override_l2cr = 1;
-				ppc_override_l2cr_value = *l2cr;
-				_set_L2CR(0);
-				_set_L2CR(ppc_override_l2cr_value);
-			}
-		}
-	}
-
-	if (ppc_override_l2cr)
-		printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
-			ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
-				? "enabled" : "disabled");
-	
-#ifdef CONFIG_KGDB
-	zs_kgdb_hook(0);
-#endif
-
-#ifdef CONFIG_ADB_CUDA
-	find_via_cuda();
-#else
-	if (find_devices("via-cuda")) {
-		printk("WARNING ! Your machine is Cuda based but your kernel\n");
-		printk("          wasn't compiled with CONFIG_ADB_CUDA option !\n");
-	}
-#endif	
-#ifdef CONFIG_ADB_PMU
-	find_via_pmu();
-#else
-	if (find_devices("via-pmu")) {
-		printk("WARNING ! Your machine is PMU based but your kernel\n");
-		printk("          wasn't compiled with CONFIG_ADB_PMU option !\n");
-	}
-#endif	
-#ifdef CONFIG_NVRAM
-	pmac_nvram_init();
-#endif
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-#ifdef CONFIG_VT
-	kd_mksound = pmac_mksound;
-#endif
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (initrd_start)
-		ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
-	else
-#endif
-		ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
-
-#ifdef CONFIG_SMP
-	/* Check for Core99 */
-	if (find_devices("uni-n"))
-		ppc_md.smp_ops = &core99_smp_ops;
-	else
-		ppc_md.smp_ops = &psurge_smp_ops;
-#endif /* CONFIG_SMP */
-}
-
-static void __init ohare_init(void)
-{
-	/*
-	 * Turn on the L2 cache.
-	 * We assume that we have a PSX memory controller iff
-	 * we have an ohare I/O controller.
-	 */
-	if (find_devices("ohare") != NULL) {
-		if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
-			if (sysctrl_regs[4] & 0x10)
-				sysctrl_regs[4] |= 0x04000020;
-			else
-				sysctrl_regs[4] |= 0x04000000;
-			if(has_l2cache)
-				printk(KERN_INFO "Level 2 cache enabled\n");
-		}
-	}
-}
-
-extern char *bootpath;
-extern char *bootdevice;
-void *boot_host;
-int boot_target;
-int boot_part;
-extern kdev_t boot_dev;
-
-void __init
-pmac_init2(void)
-{
-#ifdef CONFIG_ADB_PMU
-	via_pmu_start();
-#endif
-#ifdef CONFIG_ADB_CUDA
-	via_cuda_start();
-#endif
-#ifdef CONFIG_PMAC_PBOOK
-	media_bay_init();
-#endif
-	pmac_feature_late_init();
-}
-
-/* That include would have to be in include/linux/ ideally */
-#include "../../../fs/partitions/mac.h"
-
-/* Borrowed from fs/partition/check.c */
-static unsigned char* __init
-read_one_block(struct block_device *bdev, unsigned long n, struct page **v)
-{
-	struct address_space *mapping = bdev->bd_inode->i_mapping;
-	int sect = PAGE_CACHE_SIZE / 512;
-	struct page *page;
-
-	page = read_cache_page(mapping, n/sect,
-			(filler_t *)mapping->a_ops->readpage, NULL);
-	if (!IS_ERR(page)) {
-		wait_on_page(page);
-		if (!Page_Uptodate(page))
-			goto fail;
-		if (PageError(page))
-			goto fail;
-		*v = page;
-		return (unsigned char *)page_address(page) + 512 * (n % sect);
-fail:
-		page_cache_release(page);
-	}
-	*v = NULL;
-	return NULL;
-}
-
-#ifdef CONFIG_SCSI
-void __init
-note_scsi_host(struct device_node *node, void *host)
-{
-	int l;
-	char *p;
-
-	l = strlen(node->full_name);
-	if (bootpath != NULL && bootdevice != NULL
-	    && strncmp(node->full_name, bootdevice, l) == 0
-	    && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
-		boot_host = host;
-		/*
-		 * There's a bug in OF 1.0.5.  (Why am I not surprised.)
-		 * If you pass a path like scsi/sd@1:0 to canon, it returns
-		 * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
-		 * That is, the scsi target number doesn't get preserved.
-		 * So we pick the target number out of bootpath and use that.
-		 */
-		p = strstr(bootpath, "/sd@");
-		if (p != NULL) {
-			p += 4;
-			boot_target = simple_strtoul(p, NULL, 10);
-			p = strchr(p, ':');
-			if (p != NULL)
-				boot_part = simple_strtoul(p + 1, NULL, 10);
-		}
-	}
-}
-#endif /* CONFIG_SCSI */
-
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-kdev_t __init
-find_ide_boot(void)
-{
-	char *p;
-	int n;
-	kdev_t __init pmac_find_ide_boot(char *bootdevice, int n);
-
-	if (bootdevice == NULL)
-		return 0;
-	p = strrchr(bootdevice, '/');
-	if (p == NULL)
-		return 0;
-	n = p - bootdevice;
-
-	return pmac_find_ide_boot(bootdevice, n);
-}
-#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
-
-void __init
-find_boot_device(void)
-{
-#if defined(CONFIG_SCSI) && defined(CONFIG_BLK_DEV_SD)
-	if (boot_host != NULL) {
-		boot_dev = sd_find_target(boot_host, boot_target);
-		if (boot_dev != 0)
-			return;
-	}
-#endif
-#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
-	boot_dev = find_ide_boot();
-#endif
-}
-
-static void __init
-check_bootable_part(kdev_t dev, int blk, struct mac_partition *part)
-{
-	int goodness = 0;
-
-	macpart_fix_string(part->processor, 16);
-	macpart_fix_string(part->name, 32);
-	macpart_fix_string(part->type, 32);					
-    
-	if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
-	    && strcasecmp(part->processor, "powerpc") == 0)
-		goodness++;
-
-	if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
-	    || (strnicmp(part->type, "Linux", 5) == 0
-	    && strcasecmp(part->type, "Linux_swap") != 0)) {
-		int i, l;
-
-		goodness++;
-		l = strlen(part->name);
-		if (strcmp(part->name, "/") == 0)
-			goodness++;
-		for (i = 0; i <= l - 4; ++i) {
-			if (strnicmp(part->name + i, "root",
-				     4) == 0) {
-				goodness += 2;
-				break;
-			}
-		}
-		if (strnicmp(part->name, "swap", 4) == 0)
-			goodness--;
-	}
-
-	if (goodness > current_root_goodness) {
-		ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + blk);
-		current_root_goodness = goodness;
-	}
-}
-
-static void __init
-check_bootable_disk(kdev_t dev, struct block_device *bdev)
-{
-	struct mac_partition *part;
-	struct mac_driver_desc *md;
-	struct page* pg;
-	unsigned secsize, blocks_in_map, blk;
-	unsigned char* data;
-	
-	/* Check driver descriptor */
-	md = (struct mac_driver_desc *) read_one_block(bdev, 0, &pg);
-	if (!md)
-		return;
-	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC)
-		goto fail;
-	secsize = be16_to_cpu(md->block_size);
-	page_cache_release(pg);
-	
-	/* Check if it looks like a mac partition map */
-	data = read_one_block(bdev, secsize/512, &pg);
-	if (!data)
-		goto fail;
-	part = (struct mac_partition *) (data + secsize%512);
-	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
-		goto fail;
-
-	/* Iterate the partition map */
-	blocks_in_map = be32_to_cpu(part->map_count);
-	for (blk = 1; blk <= blocks_in_map; ++blk) {
-		int pos = blk * secsize;
-		page_cache_release(pg);
-		data = read_one_block(bdev, pos/512, &pg);
-		if (!data)
-			break;
-		part = (struct mac_partition *) (data + pos%512);
-		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
-			break;
-		check_bootable_part(dev, blk, part);
-	}
-fail:
-	if (pg)	
-		page_cache_release(pg);
-}
-
-static int __init
-walk_bootable(struct gendisk *hd, void *data)
-{
-	int drive;
-	
-	for (drive=0; drive<hd->nr_real; drive++) {
-		kdev_t dev;
-		struct block_device *bdev;
-		int rc;
-
-		dev = MKDEV(hd->major, drive << hd->minor_shift);
-		if (boot_dev && boot_dev != dev)
-			continue;
-		bdev = bdget(kdev_t_to_nr(dev));
-		if (bdev == NULL)
-			continue;
-		rc = blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW);
-		if (rc == 0) {
-			check_bootable_disk(dev, bdev);
-			blkdev_put(bdev, BDEV_RAW);
-		}
-	}
-
-	return 0;
-}
-
-void __init
-pmac_discover_root(void)
-{
-	char* p;
-
-	/* Check if root devices already got selected by other ways */
-	if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
-		return;
-	p = strstr(saved_command_line, "root=");
-	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
-		return;
-
-	/* Find the device used for booting if we can */
-	find_boot_device();
-
-	/* Try to locate a partition */
-	walk_gendisk(walk_bootable, NULL);
-}
-
-void __pmac
-pmac_restart(char *cmd)
-{
-#ifdef CONFIG_ADB_CUDA
-	struct adb_request req;
-#endif /* CONFIG_ADB_CUDA */
-
-#ifdef CONFIG_NVRAM
-	pmac_nvram_update();
-#endif
-	
-	switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
-	case SYS_CTRLER_CUDA:
-		cuda_request(&req, NULL, 2, CUDA_PACKET,
-			     CUDA_RESET_SYSTEM);
-		for (;;)
-			cuda_poll();
-		break;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU		
-	case SYS_CTRLER_PMU:
-		pmu_restart();
-		break;
-#endif /* CONFIG_ADB_PMU */		
-	default: ;
-	}
-}
-
-void __pmac
-pmac_power_off(void)
-{
-#ifdef CONFIG_ADB_CUDA
-	struct adb_request req;
-#endif /* CONFIG_ADB_CUDA */
-
-#ifdef CONFIG_NVRAM
-	pmac_nvram_update();
-#endif
-	
-	switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
-	case SYS_CTRLER_CUDA:
-		cuda_request(&req, NULL, 2, CUDA_PACKET,
-			     CUDA_POWERDOWN);
-		for (;;)
-			cuda_poll();
-		break;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
-	case SYS_CTRLER_PMU:
-		pmu_shutdown();
-		break;
-#endif /* CONFIG_ADB_PMU */
-	default: ;
-	}
-}
-
-void __pmac
-pmac_halt(void)
-{
-   pmac_power_off();
-}
-
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-static int __pmac
-pmac_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
-	if (pmac_ide_check_base(from) >= 0)
-		return 0;
-#endif
-	return check_region(from, extent);
-}
-
-static void __pmac
-pmac_ide_request_region(ide_ioreg_t from,
-			unsigned int extent,
-			const char *name)
-{
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
-	if (pmac_ide_check_base(from) >= 0)
-		return;
-#endif
-	request_region(from, extent, name);
-}
-
-static void __pmac
-pmac_ide_release_region(ide_ioreg_t from,
-			unsigned int extent)
-{
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
-	if (pmac_ide_check_base(from) >= 0)
-		return;
-#endif
-	release_region(from, extent);
-}
-
-#ifndef CONFIG_BLK_DEV_IDE_PMAC
-/*
- * This is only used if we have a PCI IDE controller, not
- * for the IDE controller in the ohare/paddington/heathrow/keylargo.
- */
-static void __pmac
-pmac_ide_pci_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;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-}
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-
-/*
- * Read in a property describing some pieces of memory.
- */
-
-static int __init
-get_mem_prop(char *name, struct mem_pieces *mp)
-{
-	struct reg_property *rp;
-	int i, s;
-	unsigned int *ip;
-	int nac = prom_n_addr_cells(memory_node);
-	int nsc = prom_n_size_cells(memory_node);
-
-	ip = (unsigned int *) get_property(memory_node, name, &s);
-	if (ip == NULL) {
-		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
-		       name);
-		return 0;
-	}
-	s /= (nsc + nac) * 4;
-	rp = mp->regions;
-	for (i = 0; i < s; ++i, ip += nac+nsc) {
-		if (nac >= 2 && ip[nac-2] != 0)
-			continue;
-		rp->address = ip[nac-1];
-		if (nsc >= 2 && ip[nac+nsc-2] != 0)
-			rp->size = ~0U;
-		else
-			rp->size = ip[nac+nsc-1];
-		++rp;
-	}
-	mp->n_regions = rp - mp->regions;
-
-	/* Make sure the pieces are sorted. */
-	mem_pieces_sort(mp);
-	mem_pieces_coalesce(mp);
-	return 1;
-}
-
-/*
- * On systems with Open Firmware, collect information about
- * physical RAM and which pieces are already in use.
- * At this point, we have (at least) the first 8MB mapped with a BAT.
- * Our text, data, bss use something over 1MB, starting at 0.
- * Open Firmware may be using 1MB at the 4MB point.
- */
-unsigned long __init
-pmac_find_end_of_memory(void)
-{
-	unsigned long a, total;
-	struct mem_pieces phys_mem;
-
-	/*
-	 * Find out where physical memory is, and check that it
-	 * starts at 0 and is contiguous.  It seems that RAM is
-	 * always physically contiguous on Power Macintoshes.
-	 *
-	 * Supporting discontiguous physical memory isn't hard,
-	 * it just makes the virtual <-> physical mapping functions
-	 * more complicated (or else you end up wasting space
-	 * in mem_map).
-	 */
-	memory_node = find_devices("memory");
-	if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
-	    || phys_mem.n_regions == 0)
-		panic("No RAM??");
-	a = phys_mem.regions[0].address;
-	if (a != 0)
-		panic("RAM doesn't start at physical address 0");
-	total = phys_mem.regions[0].size;
-
-	if (phys_mem.n_regions > 1) {
-		printk("RAM starting at 0x%x is not contiguous\n",
-		       phys_mem.regions[1].address);
-		printk("Using RAM from 0 to 0x%lx\n", total-1);
-	}
-
-	return total;
-}
-
-void __init
-select_adb_keyboard(void)
-{
-#ifdef CONFIG_VT
-#ifdef CONFIG_INPUT
-	ppc_md.kbd_init_hw       = mac_hid_init_hw;
-	ppc_md.kbd_translate     = mac_hid_kbd_translate;
-	ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up;
-	ppc_md.kbd_setkeycode    = 0;
-	ppc_md.kbd_getkeycode    = 0;
-	ppc_md.kbd_leds		 = 0;
-#ifdef CONFIG_MAGIC_SYSRQ
-#ifdef CONFIG_MAC_ADBKEYCODES
-	if (!keyboard_sends_linux_keycodes) {
-		ppc_md.ppc_kbd_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
-		SYSRQ_KEY = 0x69;
-	} else
-#endif /* CONFIG_MAC_ADBKEYCODES */
-	{
-		ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
-		SYSRQ_KEY = 0x54;
-	}
-#endif /* CONFIG_MAGIC_SYSRQ */
-#elif defined(CONFIG_ADB_KEYBOARD)
-	ppc_md.kbd_setkeycode       = mackbd_setkeycode;
-	ppc_md.kbd_getkeycode       = mackbd_getkeycode;
-	ppc_md.kbd_translate        = mackbd_translate;
-	ppc_md.kbd_unexpected_up    = mackbd_unexpected_up;
-	ppc_md.kbd_leds             = mackbd_leds;
-	ppc_md.kbd_init_hw          = mackbd_init_hw;
-#ifdef CONFIG_MAGIC_SYSRQ
-	ppc_md.ppc_kbd_sysrq_xlate  = mackbd_sysrq_xlate;
-	SYSRQ_KEY = 0x69;
-#endif /* CONFIG_MAGIC_SYSRQ */
-#endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */
-#endif /* CONFIG_VT */
-}
-
-void __init
-pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
-	  unsigned long r6, unsigned long r7)
-{
-	/* isa_io_base gets set in pmac_find_bridges */
-	isa_mem_base = PMAC_ISA_MEM_BASE;
-	pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
-	ISA_DMA_THRESHOLD = ~0L;
-	DMA_MODE_READ = 1;
-	DMA_MODE_WRITE = 2;
-
-	ppc_md.setup_arch     = pmac_setup_arch;
-	ppc_md.show_cpuinfo   = pmac_show_cpuinfo;
-	ppc_md.show_percpuinfo = of_show_percpuinfo;
-	ppc_md.irq_cannonicalize = NULL;
-	ppc_md.init_IRQ       = pmac_pic_init;
-	ppc_md.get_irq        = pmac_get_irq; /* Changed later on ... */
-	ppc_md.init           = pmac_init2;
-	
-	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
-	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
-	ppc_md.pcibios_after_init = pmac_pcibios_after_init;
-
-	ppc_md.discover_root  = pmac_discover_root;
-
-	ppc_md.restart        = pmac_restart;
-	ppc_md.power_off      = pmac_power_off;
-	ppc_md.halt           = pmac_halt;
-
-	ppc_md.time_init      = pmac_time_init;
-	ppc_md.set_rtc_time   = pmac_set_rtc_time;
-	ppc_md.get_rtc_time   = pmac_get_rtc_time;
-	ppc_md.calibrate_decr = pmac_calibrate_decr;
-
-	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
-
-	ppc_md.feature_call   = pmac_do_feature_call;
-
-	select_adb_keyboard();
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-        ppc_ide_md.ide_check_region	= pmac_ide_check_region;
-        ppc_ide_md.ide_request_region	= pmac_ide_request_region;
-        ppc_ide_md.ide_release_region	= pmac_ide_release_region;
-#ifdef CONFIG_BLK_DEV_IDE_PMAC
-        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
-        ppc_ide_md.default_io_base	= pmac_ide_get_base;
-#else /* CONFIG_BLK_DEV_IDE_PMAC */
-        ppc_ide_md.ide_init_hwif	= pmac_ide_pci_init_hwif_ports;
-#endif /* CONFIG_BLK_DEV_IDE_PMAC */
-#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
-
-#ifdef CONFIG_BOOTX_TEXT
-	ppc_md.progress = pmac_progress;
-#endif /* CONFIG_BOOTX_TEXT */
-
-	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
-	
-}
-
-#ifdef CONFIG_BOOTX_TEXT
-void __init
-pmac_progress(char *s, unsigned short hex)
-{
-	if (boot_text_mapped) {
-		btext_drawstring(s);
-		btext_drawchar('\n');
-	}
-}
-#endif /* CONFIG_BOOTX_TEXT */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_smp.c linux/arch/ppc/kernel/pmac_smp.c
--- linux.orig/arch/ppc/kernel/pmac_smp.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_smp.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,622 +0,0 @@
-/*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
- * SMP support for power macintosh.
- *
- * We support both the old "powersurge" SMP architecture
- * and the current Core99 (G4 PowerMac) machines.
- *
- * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
- * and Ben Herrenschmidt <benh@kernel.crashing.org>.
- *
- * Support for DayStar quad CPU cards
- * Copyright (C) XLR8, Inc. 1994-2000
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- */
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/smp_lock.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/delay.h>
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/hardirq.h>
-#include <asm/softirq.h>
-#include <asm/sections.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/smp.h>
-#include <asm/residual.h>
-#include <asm/machdep.h>
-#include <asm/pmac_feature.h>
-#include <asm/time.h>
-#include <asm/gemini.h>
-#include <asm/processor.h>
-
-#include "open_pic.h"
-
-/*
- * Powersurge (old powermac SMP) support.
- */
-
-extern void __secondary_start_psurge(void);
-extern void __secondary_start_psurge2(void);	/* Temporary horrible hack */
-extern void __secondary_start_psurge3(void);	/* Temporary horrible hack */
-
-/* Addresses for powersurge registers */
-#define HAMMERHEAD_BASE		0xf8000000
-#define HHEAD_CONFIG		0x90
-#define HHEAD_SEC_INTR		0xc0
-
-/* register for interrupting the primary processor on the powersurge */
-/* N.B. this is actually the ethernet ROM! */
-#define PSURGE_PRI_INTR		0xf3019000
-
-/* register for storing the start address for the secondary processor */
-/* N.B. this is the PCI config space address register for the 1st bridge */
-#define PSURGE_START		0xf2800000
-
-/* Daystar/XLR8 4-CPU card */
-#define PSURGE_QUAD_REG_ADDR	0xf8800000
-
-#define PSURGE_QUAD_IRQ_SET	0
-#define PSURGE_QUAD_IRQ_CLR	1
-#define PSURGE_QUAD_IRQ_PRIMARY	2
-#define PSURGE_QUAD_CKSTOP_CTL	3
-#define PSURGE_QUAD_PRIMARY_ARB	4
-#define PSURGE_QUAD_BOARD_ID	6
-#define PSURGE_QUAD_WHICH_CPU	7
-#define PSURGE_QUAD_CKSTOP_RDBK	8
-#define PSURGE_QUAD_RESET_CTL	11
-
-#define PSURGE_QUAD_OUT(r, v)	(out_8(quad_base + ((r) << 4) + 4, (v)))
-#define PSURGE_QUAD_IN(r)	(in_8(quad_base + ((r) << 4) + 4) & 0x0f)
-#define PSURGE_QUAD_BIS(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
-#define PSURGE_QUAD_BIC(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
-
-/* virtual addresses for the above */
-static volatile u8 *hhead_base;
-static volatile u8 *quad_base;
-static volatile u32 *psurge_pri_intr;
-static volatile u8 *psurge_sec_intr;
-static volatile u32 *psurge_start;
-
-/* what sort of powersurge board we have */
-static int psurge_type;
-
-/* values for psurge_type */
-#define PSURGE_DUAL		0
-#define PSURGE_QUAD_OKEE	1
-#define PSURGE_QUAD_COTTON	2
-#define PSURGE_QUAD_ICEGRASS	3
-
-volatile static long int core99_l2_cache;
-volatile static long int core99_l3_cache;
-
-static void __init
-core99_init_caches(void)
-{
-	int cpu = smp_processor_id();
-
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
-		return;
-
-	if (cpu == 0){
-		core99_l2_cache = _get_L2CR();
-		printk("CPU0: L2CR is %lx\n", core99_l2_cache);
-	} else {
-		printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
-		_set_L2CR(0);
-		_set_L2CR(core99_l2_cache);
-		printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
-	}
-
-	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
-		return;
-
-	if (cpu == 0){
-		core99_l3_cache = _get_L3CR();
-		printk("CPU0: L3CR is %lx\n", core99_l3_cache);
-	} else {
-		printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
-		_set_L3CR(0);
-		_set_L3CR(core99_l3_cache);
-		printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
-	}
-}
-
-/* Some CPU registers have to be saved from the first CPU and
- * applied to others. Note that we override what is setup by
- * the cputable intentionally.
- */
-
-#define	reg_hid0	0
-#define	reg_hid1	1
-#define	reg_msscr0	2
-#define	reg_msssr0	3
-#define	reg_ictrl	4
-#define	reg_ldstcr	5
-#define	reg_ldstdb	6
-#define	reg_count	7
-
-static unsigned long cpu_regs[reg_count];
-
-static void __pmac
-cpu_setup_grab(void)
-{
-	unsigned int pvers = mfspr(SPRN_PVR)>>16;
-
-	/* Read cache setting of CPU 0 */
-	core99_init_caches();
-
-	/* 7400/7410/7450 */
-	if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
-		cpu_regs[reg_hid0] = mfspr(SPRN_HID0);
-		cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0);
-		cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0);
-	}
-	/* 7450 only */
-	if (pvers == 0x8000) {
-		cpu_regs[reg_hid1] = mfspr(SPRN_HID1);
-		cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL);
-		cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR);
-		cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB);
-	}
-	flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]);
-}
-
-static void __pmac
-cpu_setup_apply(int cpu_nr)
-{
-	unsigned int pvers = mfspr(SPRN_PVR)>>16;
-
-	/* Apply cache setting from CPU 0 */
-	core99_init_caches();
-
-	/* 7400/7410/7450 */
-	if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
-		unsigned long tmp;
-		__asm__ __volatile__ (
-			"lwz	%0,4*"stringify(reg_hid0)"(%1)\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_HID0)", %0\n"
-			"isync;sync\n"
-			"lwz	%0, 4*"stringify(reg_msscr0)"(%1)\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_MSSCR0)", %0\n"
-			"isync;sync\n"
-//			"lwz	%0, "stringify(reg_msssr0)"(%1)\n"
-//			"sync\n"
-//			"mtspr	"stringify(SPRN_MSSSR0)", %0\n"
-//			"isync;sync\n"
-		: "=&r" (tmp) : "r" (cpu_regs));			
-	}
-	/* 7410 only */
-	if (pvers == 0x800c) {
-		unsigned long tmp;
-		__asm__ __volatile__ (
-			"li	%0, 0\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_L2CR2)", %0\n"
-			"isync;sync\n"
-		: "=&r" (tmp));		
-	}
-	/* 7450 only */
-	if (pvers == 0x8000) {
-		unsigned long tmp;
-		__asm__ __volatile__ (
-			"lwz	%0, 4*"stringify(reg_hid1)"(%1)\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_HID1)", %0\n"
-			"isync;sync\n"
-			"lwz	%0, 4*"stringify(reg_ictrl)"(%1)\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_ICTRL)", %0\n"
-			"isync;sync\n"
-			"lwz	%0, 4*"stringify(reg_ldstcr)"(%1)\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_LDSTCR)", %0\n"
-			"isync;sync\n"
-			"lwz	%0, 4*"stringify(reg_ldstdb)"(%1)\n"
-			"sync\n"
-			"mtspr	"stringify(SPRN_LDSTDB)", %0\n"
-			"isync;sync\n"
-		: "=&r" (tmp) : "r" (cpu_regs));		
-	}
-}
-
-/*
- * Set and clear IPIs for powersurge.
- */
-static inline void psurge_set_ipi(int cpu)
-{
-	if (cpu == 0)
-		in_be32(psurge_pri_intr);
-	else if (psurge_type == PSURGE_DUAL)
-		out_8(psurge_sec_intr, 0);
-	else
-		PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
-}
-
-static inline void psurge_clr_ipi(int cpu)
-{
-	if (cpu > 0) {
-		if (psurge_type == PSURGE_DUAL)
-			out_8(psurge_sec_intr, ~0);
-		else
-			PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
-	}
-}
-
-/*
- * On powersurge (old SMP powermac architecture) we don't have
- * separate IPIs for separate messages like openpic does.  Instead
- * we have a bitmap for each processor, where a 1 bit means that
- * the corresponding message is pending for that processor.
- * Ideally each cpu's entry would be in a different cache line.
- *  -- paulus.
- */
-static unsigned long psurge_smp_message[NR_CPUS];
-
-void __pmac
-psurge_smp_message_recv(struct pt_regs *regs)
-{
-	int cpu = smp_processor_id();
-	int msg;
-
-	/* clear interrupt */
-	psurge_clr_ipi(cpu);
-
-	if (smp_num_cpus < 2)
-		return;
-
-	/* make sure there is a message there */
-	for (msg = 0; msg < 4; msg++)
-		if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
-			smp_message_recv(msg, regs);
-}
-
-void __pmac
-psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
-{
-	psurge_smp_message_recv(regs);
-}
-
-static void __pmac
-smp_psurge_message_pass(int target, int msg, unsigned long data, int wait)
-{
-	int i;
-
-	if (smp_num_cpus < 2)
-		return;
-
-	for (i = 0; i < smp_num_cpus; i++) {
-		if (target == MSG_ALL
-		    || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
-		    || target == i) {
-			set_bit(msg, &psurge_smp_message[i]);
-			psurge_set_ipi(i);
-		}
-	}
-}
-
-/*
- * Determine a quad card presence. We read the board ID register, we
- * force the data bus to change to something else, and we read it again.
- * It it's stable, then the register probably exist (ugh !)
- */
-static int __init psurge_quad_probe(void)
-{
-	int type;
-	unsigned int i;
-
-	type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
-	if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
-	    || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
-		return PSURGE_DUAL;
-
-	/* looks OK, try a slightly more rigorous test */
-	/* bogus is not necessarily cacheline-aligned,
-	   though I don't suppose that really matters.  -- paulus */
-	for (i = 0; i < 100; i++) {
-		volatile u32 bogus[8];
-		bogus[(0+i)%8] = 0x00000000;
-		bogus[(1+i)%8] = 0x55555555;
-		bogus[(2+i)%8] = 0xFFFFFFFF;
-		bogus[(3+i)%8] = 0xAAAAAAAA;
-		bogus[(4+i)%8] = 0x33333333;
-		bogus[(5+i)%8] = 0xCCCCCCCC;
-		bogus[(6+i)%8] = 0xCCCCCCCC;
-		bogus[(7+i)%8] = 0x33333333;
-		wmb();
-		asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
-		mb();
-		if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
-			return PSURGE_DUAL;
-	}
-	return type;
-}
-
-static void __init psurge_quad_init(void)
-{
-	int procbits;
-
-	if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
-	procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
-	if (psurge_type == PSURGE_QUAD_ICEGRASS)
-		PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
-	else
-		PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
-	mdelay(33);
-	out_8(psurge_sec_intr, ~0);
-	PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
-	PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
-	if (psurge_type != PSURGE_QUAD_ICEGRASS)
-		PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
-	PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
-	mdelay(33);
-	PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
-	mdelay(33);
-	PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
-	mdelay(33);
-}
-
-static int __init smp_psurge_probe(void)
-{
-	int i, ncpus;
-
-	/* We don't do SMP on the PPC601 -- paulus */
-	if (PVR_VER(mfspr(PVR)) == 1)
-		return 1;
-
-	/*
-	 * The powersurge cpu board can be used in the generation
-	 * of powermacs that have a socket for an upgradeable cpu card,
-	 * including the 7500, 8500, 9500, 9600.
-	 * The device tree doesn't tell you if you have 2 cpus because
-	 * OF doesn't know anything about the 2nd processor.
-	 * Instead we look for magic bits in magic registers,
-	 * in the hammerhead memory controller in the case of the
-	 * dual-cpu powersurge board.  -- paulus.
-	 */
-	if (find_devices("hammerhead") == NULL)
-		return 1;
-
-	hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
-	quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
-	psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
-
-	psurge_type = psurge_quad_probe();
-	if (psurge_type != PSURGE_DUAL) {
-		psurge_quad_init();
-		/* All released cards using this HW design have 4 CPUs */
-		ncpus = 4;
-	} else {
-		iounmap((void *) quad_base);
-		if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
-			/* not a dual-cpu card */
-			iounmap((void *) hhead_base);
-			return 1;
-		}
-		ncpus = 2;
-	}
-
-	psurge_start = ioremap(PSURGE_START, 4);
-	psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
-
-	/* this is not actually strictly necessary -- paulus. */
-	for (i = 1; i < ncpus; ++i)
-		smp_hw_index[i] = i;
-
-	if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
-
-	return ncpus;
-}
-
-static void __init smp_psurge_kick_cpu(int nr)
-{
-	void (*start)(void) = __secondary_start_psurge;
-	unsigned long a;
-
-	/* may need to flush here if secondary bats aren't setup */
-	for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
-		asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
-	asm volatile("sync");
-
-	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
-
-	/* setup entry point of secondary processor */
-	switch (nr) {
-	case 2:
-		start = __secondary_start_psurge2;
-		break;
-	case 3:
-		start = __secondary_start_psurge3;
-		break;
-	}
-
-	out_be32(psurge_start, __pa(start));
-	mb();
-
-	psurge_set_ipi(nr);
-	udelay(10);
-	psurge_clr_ipi(nr);
-
-	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
-}
-
-/*
- * With the dual-cpu powersurge board, the decrementers and timebases
- * of both cpus are frozen after the secondary cpu is started up,
- * until we give the secondary cpu another interrupt.  This routine
- * uses this to get the timebases synchronized.
- *  -- paulus.
- */
-static void __init psurge_dual_sync_tb(int cpu_nr)
-{
-	static volatile int sec_tb_reset = 0;
-	int t;
-
-	set_dec(tb_ticks_per_jiffy);
-	set_tb(0, 0);
-	last_jiffy_stamp(cpu_nr) = 0;
-
-	if (cpu_nr > 0) {
-		mb();
-		sec_tb_reset = 1;
-		return;
-	}
-
-	/* wait for the secondary to have reset its TB before proceeding */
-	for (t = 10000000; t > 0 && !sec_tb_reset; --t)
-		;
-
-	/* now interrupt the secondary, starting both TBs */
-	psurge_set_ipi(1);
-
-	smp_tb_synchronized = 1;
-}
-
-static void __init
-smp_psurge_setup_cpu(int cpu_nr)
-{
-
-	if (cpu_nr == 0) {
-		if (smp_num_cpus < 2)
-			return;
-		/* reset the entry point so if we get another intr we won't
-		 * try to startup again */
-		out_be32(psurge_start, 0x100);
-		if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
-			printk(KERN_ERR "Couldn't get primary IPI interrupt");
-	}
-
-	if (psurge_type == PSURGE_DUAL)
-		psurge_dual_sync_tb(cpu_nr);
-}
-
-static int __init
-smp_core99_probe(void)
-{
-	struct device_node *cpus;
-	int i, ncpus = 1;
-	extern int powersave_nap;
-
-	if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
-	cpus = find_type_devices("cpu");
-	if (cpus)
-		while ((cpus = cpus->next) != NULL)
-			++ncpus;
-	printk("smp_core99_probe: found %d cpus\n", ncpus);
-	if (ncpus > 1) {
-		openpic_request_IPIs();
-		for (i = 1; i < ncpus; ++i)
-			smp_hw_index[i] = i;
-		powersave_nap = 0;
-		cpu_setup_grab();
-	}
-
-	return ncpus;
-}
-
-static void __init
-smp_core99_kick_cpu(int nr)
-{
-	unsigned long save_vector, new_vector;
-	unsigned long flags;
-
-	volatile unsigned long *vector
-		 = ((volatile unsigned long *)(KERNELBASE+0x100));
-	if (nr < 1 || nr > 3)
-		return;
-	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
-
-	local_irq_save(flags);
-	local_irq_disable();
-	
-	/* Save reset vector */
-	save_vector = *vector;
-	
-	/* Setup fake reset vector that does	  
-	 *   b __secondary_start_psurge - KERNELBASE
-	 */  
-	switch(nr) {
-		case 1:
-			new_vector = (unsigned long)__secondary_start_psurge;
-			break;
-		case 2:
-			new_vector = (unsigned long)__secondary_start_psurge2;
-			break;
-		case 3:
-			new_vector = (unsigned long)__secondary_start_psurge3;
-			break;
-	}
-	*vector = 0x48000002 + new_vector - KERNELBASE;
-	
-	/* flush data cache and inval instruction cache */
-	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
-	
-	/* Put some life in our friend */
-	pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
-	
-	/* FIXME: We wait a bit for the CPU to take the exception, I should
-	 * instead wait for the entry code to set something for me. Well,
-	 * ideally, all that crap will be done in prom.c and the CPU left
-	 * in a RAM-based wait loop like CHRP.
-	 */
-	mdelay(1);
-	
-	/* Restore our exception vector */
-	*vector = save_vector;
-	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
-	
-	local_irq_restore(flags);
-	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
-}
-
-static void __init
-smp_core99_setup_cpu(int cpu_nr)
-{
-	/* Setup some registers */
-	if (cpu_nr != 0)
-		cpu_setup_apply(cpu_nr);
-	
-	/* Setup openpic */
-	do_openpic_setup_cpu();
-
-	/* Setup L2/L3 */
-	if (cpu_nr == 0)
-		if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
-}
-
-/* PowerSurge-style Macs */
-struct smp_ops_t psurge_smp_ops __pmacdata = {
-	smp_psurge_message_pass,
-	smp_psurge_probe,
-	smp_psurge_kick_cpu,
-	smp_psurge_setup_cpu,
-};
-
-/* Core99 Macs (dual G4s) */
-struct smp_ops_t core99_smp_ops __pmacdata = {
-	smp_openpic_message_pass,
-	smp_core99_probe,
-	smp_core99_kick_cpu,
-	smp_core99_setup_cpu,
-};
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/pmac_time.c linux/arch/ppc/kernel/pmac_time.c
--- linux.orig/arch/ppc/kernel/pmac_time.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/pmac_time.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,282 +0,0 @@
-/*
- * BK Id: SCCS/s.pmac_time.c 1.19 12/04/01 01:24:51 benh
- */
-/*
- * Support for periodic interrupts (100 per second) and for getting
- * the current time from the RTC on Power Macintoshes.
- *
- * We use the decrementer register for our periodic interrupts.
- *
- * Paul Mackerras	August 1996.
- * Copyright (C) 1996 Paul Mackerras.
- */
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/init.h>
-#include <linux/adb.h>
-#include <linux/cuda.h>
-#include <linux/pmu.h>
-
-#include <asm/sections.h>
-#include <asm/prom.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/hardirq.h>
-#include <asm/time.h>
-#include <asm/nvram.h>
-
-extern rwlock_t xtime_lock;
-
-/* Apparently the RTC stores seconds since 1 Jan 1904 */
-#define RTC_OFFSET	2082844800
-
-/*
- * Calibrate the decrementer frequency with the VIA timer 1.
- */
-#define VIA_TIMER_FREQ_6	4700000	/* time 1 frequency * 6 */
-
-/* VIA registers */
-#define RS		0x200		/* skip between registers */
-#define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
-#define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
-#define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
-#define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
-#define ACR		(11*RS)		/* Auxiliary control register */
-#define IFR		(13*RS)		/* Interrupt flag register */
-
-/* Bits in ACR */
-#define T1MODE		0xc0		/* Timer 1 mode */
-#define T1MODE_CONT	0x40		/*  continuous interrupts */
-
-/* Bits in IFR and IER */
-#define T1_INT		0x40		/* Timer 1 interrupt */
-
-extern struct timezone sys_tz;
-
-long __init
-pmac_time_init(void)
-{
-#ifdef CONFIG_NVRAM
-	s32 delta = 0;
-	int dst;
-	
-	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
-	delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
-	delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
-	if (delta & 0x00800000UL)
-		delta |= 0xFF000000UL;
-	dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
-	printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
-		dst ? "on" : "off");
-	return delta;
-#else
-	return 0;
-#endif
-}
-
-unsigned long __pmac
-pmac_get_rtc_time(void)
-{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
-	struct adb_request req;
-	unsigned long now;
-#endif
-
-	/* Get the time from the RTC */
-	switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
-	case SYS_CTRLER_CUDA:
-		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
-			return 0;
-		while (!req.complete)
-			cuda_poll();
-		if (req.reply_len != 7)
-			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		now = (req.reply[3] << 24) + (req.reply[4] << 16)
-			+ (req.reply[5] << 8) + req.reply[6];
-		return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
-	case SYS_CTRLER_PMU:
-		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
-			return 0;
-		while (!req.complete)
-			pmu_poll();
-		if (req.reply_len != 4)
-			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		now = (req.reply[0] << 24) + (req.reply[1] << 16)
-			+ (req.reply[2] << 8) + req.reply[3];
-		return now - RTC_OFFSET;
-#endif /* CONFIG_ADB_PMU */
-	default: ;
-	}
-	return 0;
-}
-
-int __pmac
-pmac_set_rtc_time(unsigned long nowtime)
-{
-#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
-	struct adb_request req;
-#endif
-
-	nowtime += RTC_OFFSET;
-
-	switch (sys_ctrler) {
-#ifdef CONFIG_ADB_CUDA
-	case SYS_CTRLER_CUDA:
-		if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
-				 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
-			return 0;
-		while (!req.complete)
-			cuda_poll();
-		if ((req.reply_len != 3) && (req.reply_len != 7))
-			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		return 1;
-#endif /* CONFIG_ADB_CUDA */
-#ifdef CONFIG_ADB_PMU
-	case SYS_CTRLER_PMU:
-		if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
-				nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
-			return 0;
-		while (!req.complete)
-			pmu_poll();
-		if (req.reply_len != 0)
-			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
-			       req.reply_len);
-		return 1;
-#endif /* CONFIG_ADB_PMU */
-	default:
-		return 0;
-	}
-}
-
-/*
- * Calibrate the decrementer register using VIA timer 1.
- * This is used both on powermacs and CHRP machines.
- */
-int __init
-via_calibrate_decr(void)
-{
-	struct device_node *vias;
-	volatile unsigned char *via;
-	int count = VIA_TIMER_FREQ_6 / HZ;
-	unsigned int dstart, dend;
-
-	vias = find_devices("via-cuda");
-	if (vias == 0)
-		vias = find_devices("via-pmu");
-	if (vias == 0)
-		vias = find_devices("via");
-	if (vias == 0 || vias->n_addrs == 0)
-		return 0;
-	via = (volatile unsigned char *)
-		ioremap(vias->addrs[0].address, vias->addrs[0].size);
-
-	/* set timer 1 for continuous interrupts */
-	out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
-	/* set the counter to a small value */
-	out_8(&via[T1CH], 2);
-	/* set the latch to `count' */
-	out_8(&via[T1LL], count);
-	out_8(&via[T1LH], count >> 8);
-	/* wait until it hits 0 */
-	while ((in_8(&via[IFR]) & T1_INT) == 0)
-		;
-	dstart = get_dec();
-	/* clear the interrupt & wait until it hits 0 again */
-	in_8(&via[T1CL]);
-	while ((in_8(&via[IFR]) & T1_INT) == 0)
-		;
-	dend = get_dec();
-
-	tb_ticks_per_jiffy = (dstart - dend) / 6;
-	tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
-
-	printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
-	       tb_ticks_per_jiffy, dstart - dend);
-
-	return 1;
-}
-
-#ifdef CONFIG_PMAC_PBOOK
-/*
- * Reset the time after a sleep.
- */
-static int __pmac
-time_sleep_notify(struct pmu_sleep_notifier *self, int when)
-{
-	static unsigned long time_diff;
-	unsigned long flags;
-
-	switch (when) {
-	case PBOOK_SLEEP_NOW:
-		read_lock_irqsave(&xtime_lock, flags);
-		time_diff = xtime.tv_sec - pmac_get_rtc_time();
-		read_unlock_irqrestore(&xtime_lock, flags);
-		break;
-	case PBOOK_WAKE:
-		write_lock_irqsave(&xtime_lock, flags);
-		xtime.tv_sec = pmac_get_rtc_time() + time_diff;
-		xtime.tv_usec = 0;
-		last_rtc_update = xtime.tv_sec;
-		write_unlock_irqrestore(&xtime_lock, flags);
-		break;
-	}
-	return PBOOK_SLEEP_OK;
-}
-
-static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
-	time_sleep_notify, SLEEP_LEVEL_MISC,
-};
-#endif /* CONFIG_PMAC_PBOOK */
-
-/*
- * Query the OF and get the decr frequency.
- * This was taken from the pmac time_init() when merging the prep/pmac
- * time functions.
- */
-void __init
-pmac_calibrate_decr(void)
-{
-	struct device_node *cpu;
-	unsigned int freq, *fp;
-
-#ifdef CONFIG_PMAC_PBOOK
-	pmu_register_sleep_notifier(&time_sleep_notifier);
-#endif /* CONFIG_PMAC_PBOOK */
-
-	/* We assume MacRISC2 machines have correct device-tree
-	 * calibration. That's better since the VIA itself seems
-	 * to be slightly off. --BenH
-	 */
-	if (!machine_is_compatible("MacRISC2"))
-		if (via_calibrate_decr())
-			return;
-
-	/*
-	 * The cpu node should have a timebase-frequency property
-	 * to tell us the rate at which the decrementer counts.
-	 */
-	cpu = find_type_devices("cpu");
-	if (cpu == 0)
-		panic("can't find cpu node in time_init");
-	fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
-	if (fp == 0)
-		panic("can't get cpu timebase frequency");
-	freq = *fp;
-	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
-	       freq/1000000, freq%1000000);
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ppc4xx_pic.c linux/arch/ppc/kernel/ppc4xx_pic.c
--- linux.orig/arch/ppc/kernel/ppc4xx_pic.c	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/ppc4xx_pic.c	2002-08-12 22:13:58.000000000 +0000
@@ -33,10 +33,7 @@
 #include <asm/processor.h>
 #include <asm/system.h>
 #include <asm/irq.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-
+#include <asm/ppc4xx_pic.h>
 
 /* Global Variables */
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ppc4xx_pic.h linux/arch/ppc/kernel/ppc4xx_pic.h
--- linux.orig/arch/ppc/kernel/ppc4xx_pic.h	2001-07-02 21:34:57.000000000 +0000
+++ linux/arch/ppc/kernel/ppc4xx_pic.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,30 +0,0 @@
-/*
- * BK Id: SCCS/s.ppc4xx_pic.h 1.8 06/15/01 13:56:56 paulus
- */
-/*
- *
- *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: ppc4xx_pic.h
- *
- *    Description:
- *      Interrupt controller driver for PowerPC 4xx-based processors.
- */
-
-#ifndef	__PPC4XX_PIC_H__
-#define	__PPC4XX_PIC_H__
-
-#include <linux/config.h>
-#include "local_irq.h"
-
-/* External Global Variables */
-
-extern struct hw_interrupt_type *ppc4xx_pic;
-
-
-/* Function Prototypes */
-
-extern void	 ppc4xx_pic_init(void);
-extern int	 ppc4xx_pic_get_irq(struct pt_regs *regs);
-
-#endif /* __PPC4XX_PIC_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ppc8260_pic.h linux/arch/ppc/kernel/ppc8260_pic.h
--- linux.orig/arch/ppc/kernel/ppc8260_pic.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/ppc8260_pic.h	2002-08-12 22:14:16.000000000 +0000
@@ -1,11 +1,11 @@
 /*
- * BK Id: SCCS/s.ppc8260_pic.h 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
  */
 
 #ifndef _PPC_KERNEL_PPC8260_H
 #define _PPC_KERNEL_PPC8260_H
 
-#include "local_irq.h"
+#include <linux/irq.h>
 
 extern struct hw_interrupt_type ppc8260_pic;
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ppc8xx_pic.h linux/arch/ppc/kernel/ppc8xx_pic.h
--- linux.orig/arch/ppc/kernel/ppc8xx_pic.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/ppc8xx_pic.h	2002-08-12 22:14:17.000000000 +0000
@@ -1,11 +1,11 @@
 /*
- * BK Id: SCCS/s.ppc8xx_pic.h 1.7 05/17/01 18:14:21 cort
+ * BK Id: %F% %I% %G% %U% %#%
  */
 #ifndef _PPC_KERNEL_PPC8xx_H
 #define _PPC_KERNEL_PPC8xx_H
 
 #include <linux/config.h>
-#include "local_irq.h"
+#include <linux/irq.h>
 
 extern struct hw_interrupt_type ppc8xx_pic;
 
@@ -15,7 +15,7 @@
 int m8xx_get_irq(struct pt_regs *regs);
 
 #ifdef CONFIG_MBX
-#include "i8259.h"
+#include <asm/i8259.h>
 #include <asm/io.h>
 void mbx_i8259_action(int cpl, void *dev_id, struct pt_regs *regs);
 #endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ppc_asm.h linux/arch/ppc/kernel/ppc_asm.h
--- linux.orig/arch/ppc/kernel/ppc_asm.h	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/ppc_asm.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,159 +0,0 @@
-/*
- * BK Id: SCCS/s.ppc_asm.h 1.20 03/19/02 15:04:39 benh
- */
-/*
- * arch/ppc/kernel/ppc_asm.h
- *
- * Definitions used by various bits of low-level assembly code on PowerPC.
- *
- * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- */
-
-#include <linux/config.h>
-
-#include "ppc_asm.tmpl"
-#include "ppc_defs.h"
-
-/*
- * Macros for storing registers into and loading registers from
- * exception frames.
- */
-#define SAVE_GPR(n, base)	stw	n,GPR0+4*(n)(base)
-#define SAVE_2GPRS(n, base)	SAVE_GPR(n, base); SAVE_GPR(n+1, base)
-#define SAVE_4GPRS(n, base)	SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
-#define SAVE_8GPRS(n, base)	SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
-#define SAVE_10GPRS(n, base)	SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
-#define REST_GPR(n, base)	lwz	n,GPR0+4*(n)(base)
-#define REST_2GPRS(n, base)	REST_GPR(n, base); REST_GPR(n+1, base)
-#define REST_4GPRS(n, base)	REST_2GPRS(n, base); REST_2GPRS(n+2, base)
-#define REST_8GPRS(n, base)	REST_4GPRS(n, base); REST_4GPRS(n+4, base)
-#define REST_10GPRS(n, base)	REST_8GPRS(n, base); REST_2GPRS(n+8, base)
-
-#define SAVE_FPR(n, base)	stfd	n,THREAD_FPR0+8*(n)(base)
-#define SAVE_2FPRS(n, base)	SAVE_FPR(n, base); SAVE_FPR(n+1, base)
-#define SAVE_4FPRS(n, base)	SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base)
-#define SAVE_8FPRS(n, base)	SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base)
-#define SAVE_16FPRS(n, base)	SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base)
-#define SAVE_32FPRS(n, base)	SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base)
-#define REST_FPR(n, base)	lfd	n,THREAD_FPR0+8*(n)(base)
-#define REST_2FPRS(n, base)	REST_FPR(n, base); REST_FPR(n+1, base)
-#define REST_4FPRS(n, base)	REST_2FPRS(n, base); REST_2FPRS(n+2, base)
-#define REST_8FPRS(n, base)	REST_4FPRS(n, base); REST_4FPRS(n+4, base)
-#define REST_16FPRS(n, base)	REST_8FPRS(n, base); REST_8FPRS(n+8, base)
-#define REST_32FPRS(n, base)	REST_16FPRS(n, base); REST_16FPRS(n+16, base)
-
-/*
- * Once a version of gas that understands the AltiVec instructions
- * is freely available, we can do this the normal way...  - paulus
- */
-#define LVX(r,a,b)	.long	(31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(103<<1)
-#define STVX(r,a,b)	.long	(31<<26)+((r)<<21)+((a)<<16)+((b)<<11)+(231<<1)
-#define MFVSCR(r)	.long	(4<<26)+((r)<<21)+(770<<1)
-#define MTVSCR(r)	.long	(4<<26)+((r)<<11)+(802<<1)
-#define DSSALL		.long	(0x1f<<26)+(0x10<<21)+(0x336<<1)
-
-#define SAVE_VR(n,b,base)	li b,THREAD_VR0+(16*(n)); STVX(n,b,base)
-#define SAVE_2VR(n,b,base)	SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) 
-#define SAVE_4VR(n,b,base)	SAVE_2VR(n,b,base); SAVE_2VR(n+2,b,base) 
-#define SAVE_8VR(n,b,base)	SAVE_4VR(n,b,base); SAVE_4VR(n+4,b,base) 
-#define SAVE_16VR(n,b,base)	SAVE_8VR(n,b,base); SAVE_8VR(n+8,b,base)
-#define SAVE_32VR(n,b,base)	SAVE_16VR(n,b,base); SAVE_16VR(n+16,b,base)
-#define REST_VR(n,b,base)	li b,THREAD_VR0+(16*(n)); LVX(n,b,base)
-#define REST_2VR(n,b,base)	REST_VR(n,b,base); REST_VR(n+1,b,base) 
-#define REST_4VR(n,b,base)	REST_2VR(n,b,base); REST_2VR(n+2,b,base) 
-#define REST_8VR(n,b,base)	REST_4VR(n,b,base); REST_4VR(n+4,b,base) 
-#define REST_16VR(n,b,base)	REST_8VR(n,b,base); REST_8VR(n+8,b,base) 
-#define REST_32VR(n,b,base)	REST_16VR(n,b,base); REST_16VR(n+16,b,base)
-
-#ifdef CONFIG_PPC601_SYNC_FIX
-#define SYNC				\
-BEGIN_FTR_SECTION			\
-	sync;				\
-	isync;				\
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-#define SYNC_601			\
-BEGIN_FTR_SECTION			\
-	sync;				\
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-#define ISYNC_601			\
-BEGIN_FTR_SECTION			\
-	isync;				\
-END_FTR_SECTION_IFSET(CPU_FTR_601)
-#else
-#define	SYNC
-#define SYNC_601
-#define ISYNC_601
-#endif
-
-#ifndef CONFIG_SMP
-#define TLBSYNC
-#else /* CONFIG_SMP */
-/* tlbsync is not implemented on 601 */
-#define TLBSYNC				\
-BEGIN_FTR_SECTION			\
-	tlbsync;			\
-	sync;				\
-END_FTR_SECTION_IFCLR(CPU_FTR_601)
-#endif
-
-/*
- * This instruction is not implemented on the PPC 603 or 601; however, on
- * the 403GCX and 405GP tlbia IS defined and tlbie is not.
- * All of these instructions exist in the 8xx, they have magical powers,
- * and they must be used.
- */
-
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-#define tlbia					\
-	li	r4,1024;			\
-	mtctr	r4;				\
-	lis	r4,KERNELBASE@h;		\
-0:	tlbie	r4;				\
-	addi	r4,r4,0x1000;			\
-	bdnz	0b
-#endif
-
-/*
- * On APUS (Amiga PowerPC cpu upgrade board), we don't know the
- * physical base address of RAM at compile time.
- */
-#define tophys(rd,rs)				\
-0:	addis	rd,rs,-KERNELBASE@h;		\
-	.section ".vtop_fixup","aw";		\
-	.align  1;				\
-	.long   0b;				\
-	.previous
-
-#define tovirt(rd,rs)				\
-0:	addis	rd,rs,KERNELBASE@h;		\
-	.section ".ptov_fixup","aw";		\
-	.align  1;				\
-	.long   0b;				\
-	.previous
-
-/*
- * On 64-bit cpus, we use the rfid instruction instead of rfi, but
- * we then have to make sure we preserve the top 32 bits except for
- * the 64-bit mode bit, which we clear.
- */
-#ifdef CONFIG_PPC64BRIDGE
-#define	FIX_SRR1(ra, rb)	\
-	mr	rb,ra;		\
-	mfmsr	ra;		\
-	clrldi	ra,ra,1;		/* turn off 64-bit mode */ \
-	rldimi	ra,rb,0,32
-#define	RFI		.long	0x4c000024	/* rfid instruction */
-#define MTMSRD(r)	.long	(0x7c000164 + ((r) << 21))	/* mtmsrd */
-#define CLR_TOP32(r)	rlwinm	(r),(r),0,0,31	/* clear top 32 bits */
-
-#else
-#define FIX_SRR1(ra, rb)
-#define	RFI		rfi
-#define MTMSRD(r)	mtmsr	r
-#define CLR_TOP32(r)
-#endif /* CONFIG_PPC64BRIDGE */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ppc_asm.tmpl linux/arch/ppc/kernel/ppc_asm.tmpl
--- linux.orig/arch/ppc/kernel/ppc_asm.tmpl	2000-02-13 18:47:01.000000000 +0000
+++ linux/arch/ppc/kernel/ppc_asm.tmpl	1970-01-01 00:00:00.000000000 +0000
@@ -1,115 +0,0 @@
-/* Condition Register Bit Fields */
-
-#define	cr0	0
-#define	cr1	1
-#define	cr2	2
-#define	cr3	3
-#define	cr4	4
-#define	cr5	5
-#define	cr6	6
-#define	cr7	7
-
-
-/* General Purpose Registers (GPRs) */
-
-#define	r0	0
-#define	r1	1
-#define	r2	2
-#define	r3	3
-#define	r4	4
-#define	r5	5
-#define	r6	6
-#define	r7	7
-#define	r8	8
-#define	r9	9
-#define	r10	10
-#define	r11	11
-#define	r12	12
-#define	r13	13
-#define	r14	14
-#define	r15	15
-#define	r16	16
-#define	r17	17
-#define	r18	18
-#define	r19	19
-#define	r20	20
-#define	r21	21
-#define	r22	22
-#define	r23	23
-#define	r24	24
-#define	r25	25
-#define	r26	26
-#define	r27	27
-#define	r28	28
-#define	r29	29
-#define	r30	30
-#define	r31	31
-
-
-/* Floating Point Registers (FPRs) */
-
-#define	fr0	0
-#define	fr1	1
-#define	fr2	2
-#define	fr3	3
-#define	fr4	4
-#define	fr5	5
-#define	fr6	6
-#define	fr7	7
-#define	fr8	8
-#define	fr9	9
-#define	fr10	10
-#define	fr11	11
-#define	fr12	12
-#define	fr13	13
-#define	fr14	14
-#define	fr15	15
-#define	fr16	16
-#define	fr17	17
-#define	fr18	18
-#define	fr19	19
-#define	fr20	20
-#define	fr21	21
-#define	fr22	22
-#define	fr23	23
-#define	fr24	24
-#define	fr25	25
-#define	fr26	26
-#define	fr27	27
-#define	fr28	28
-#define	fr29	29
-#define	fr30	30
-#define	fr31	31
-
-#define	vr0	0
-#define	vr1	1
-#define	vr2	2
-#define	vr3	3
-#define	vr4	4
-#define	vr5	5
-#define	vr6	6
-#define	vr7	7
-#define	vr8	8
-#define	vr9	9
-#define	vr10	10
-#define	vr11	11
-#define	vr12	12
-#define	vr13	13
-#define	vr14	14
-#define	vr15	15
-#define	vr16	16
-#define	vr17	17
-#define	vr18	18
-#define	vr19	19
-#define	vr20	20
-#define	vr21	21
-#define	vr22	22
-#define	vr23	23
-#define	vr24	24
-#define	vr25	25
-#define	vr26	26
-#define	vr27	27
-#define	vr28	28
-#define	vr29	29
-#define	vr30	30
-#define	vr31	31
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c
--- linux.orig/arch/ppc/kernel/prep_nvram.c	2001-09-08 19:38:42.000000000 +0000
+++ linux/arch/ppc/kernel/prep_nvram.c	2002-08-12 22:14:19.000000000 +0000
@@ -1,8 +1,8 @@
 /*
- * BK Id: SCCS/s.prep_nvram.c 1.12 09/08/01 15:47:42 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
- *  linux/arch/ppc/kernel/prep_nvram.c
+ *  arch/ppc/platforms/prep_nvram.c
  *
  *  Copyright (C) 1998  Corey Minyard
  *
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- linux.orig/arch/ppc/kernel/prep_pci.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/prep_pci.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,1271 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_pci.c 1.33 12/20/01 15:36:12 trini
- */
-/*
- * PReP pci functions.
- * Originally by Gary Thomas
- * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
- *
- * The motherboard routes/maps will disappear shortly. -- Cort
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-#include <asm/sections.h>
-#include <asm/byteorder.h>
-#include <asm/io.h>
-#include <asm/ptrace.h>
-#include <asm/prom.h>
-#include <asm/pci-bridge.h>
-#include <asm/residual.h>
-#include <asm/processor.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-
-#include "pci.h"
-#include "open_pic.h"
-
-#define MAX_DEVNR 22
-
-/* Which PCI interrupt line does a given device [slot] use? */
-/* Note: This really should be two dimensional based in slot/pin used */
-static unsigned char *Motherboard_map;
-unsigned char *Motherboard_map_name;
-
-/* How is the 82378 PIRQ mapping setup? */
-static unsigned char *Motherboard_routes;
-
-static void (*Motherboard_non0)(struct pci_dev *);
-
-static void Powerplus_Map_Non0(struct pci_dev *);
-
-/* Used for Motorola to store system config register */
-static unsigned long	*ProcInfo;
-
-/* Tables for known hardware */   
-
-/* Motorola PowerStackII - Utah */
-static char Utah_pci_IRQ_map[23] __prepdata =
-{
-        0,   /* Slot 0  - unused */
-        0,   /* Slot 1  - unused */
-        5,   /* Slot 2  - SCSI - NCR825A  */
-        0,   /* Slot 3  - unused */
-        1,   /* Slot 4  - Ethernet - DEC2114x */
-        0,   /* Slot 5  - unused */
-        3,   /* Slot 6  - PCI Card slot #1 */
-        4,   /* Slot 7  - PCI Card slot #2 */
-        5,   /* Slot 8  - PCI Card slot #3 */
-        5,   /* Slot 9  - PCI Bridge */
-             /* added here in case we ever support PCI bridges */
-             /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
-        0,   /* Slot 10 - unused */
-        0,   /* Slot 11 - unused */
-        5,   /* Slot 12 - SCSI - NCR825A */
-        0,   /* Slot 13 - unused */
-        3,   /* Slot 14 - enet */
-        0,   /* Slot 15 - unused */
-        2,   /* Slot 16 - unused */
-        3,   /* Slot 17 - unused */
-        5,   /* Slot 18 - unused */
-        0,   /* Slot 19 - unused */
-        0,   /* Slot 20 - unused */
-        0,   /* Slot 21 - unused */
-        0,   /* Slot 22 - unused */
-};
-
-static char Utah_pci_IRQ_routes[] __prepdata =
-{
-        0,   /* Line 0 - Unused */
-        9,   /* Line 1 */
-	10,  /* Line 2 */
-        11,  /* Line 3 */
-        14,  /* Line 4 */
-        15,  /* Line 5 */
-};
-
-/* Motorola PowerStackII - Omaha */
-/* no integrated SCSI or ethernet */
-static char Omaha_pci_IRQ_map[23] __prepdata =
-{
-        0,   /* Slot 0  - unused */
-        0,   /* Slot 1  - unused */
-        3,   /* Slot 2  - Winbond EIDE */
-        0,   /* Slot 3  - unused */
-        0,   /* Slot 4  - unused */
-        0,   /* Slot 5  - unused */
-        1,   /* Slot 6  - PCI slot 1 */
-        2,   /* Slot 7  - PCI slot 2  */
-        3,   /* Slot 8  - PCI slot 3 */
-        4,   /* Slot 9  - PCI slot 4 */ /* needs indirect access */
-        0,   /* Slot 10 - unused */
-        0,   /* Slot 11 - unused */
-        0,   /* Slot 12 - unused */
-        0,   /* Slot 13 - unused */
-        0,   /* Slot 14 - unused */
-        0,   /* Slot 15 - unused */
-        1,   /* Slot 16  - PCI slot 1 */
-        2,   /* Slot 17  - PCI slot 2  */
-        3,   /* Slot 18  - PCI slot 3 */
-        4,   /* Slot 19  - PCI slot 4 */ /* needs indirect access */
-        0,
-        0,
-        0,
-};
-
-static char Omaha_pci_IRQ_routes[] __prepdata =
-{
-        0,   /* Line 0 - Unused */
-        9,   /* Line 1 */
-        11,  /* Line 2 */
-        14,  /* Line 3 */
-        15   /* Line 4 */
-};
-
-/* Motorola PowerStack */
-static char Blackhawk_pci_IRQ_map[19] __prepdata =
-{
-  	0,	/* Slot 0  - unused */
-  	0,	/* Slot 1  - unused */
-  	0,	/* Slot 2  - unused */
-  	0,	/* Slot 3  - unused */
-  	0,	/* Slot 4  - unused */
-  	0,	/* Slot 5  - unused */
-  	0,	/* Slot 6  - unused */
-  	0,	/* Slot 7  - unused */
-  	0,	/* Slot 8  - unused */
-  	0,	/* Slot 9  - unused */
-  	0,	/* Slot 10 - unused */
-  	0,	/* Slot 11 - unused */
-  	3,	/* Slot 12 - SCSI */
-  	0,	/* Slot 13 - unused */
-  	1,	/* Slot 14 - Ethernet */
-  	0,	/* Slot 15 - unused */
- 	1,	/* Slot P7 */
- 	2,	/* Slot P6 */
- 	3,	/* Slot P5 */
-};
-
-static char Blackhawk_pci_IRQ_routes[] __prepdata =
-{
-   	0,	/* Line 0 - Unused */
-   	9,	/* Line 1 */
-   	11,	/* Line 2 */
-   	15,	/* Line 3 */
-   	15	/* Line 4 */
-};
-   
-/* Motorola Mesquite */
-static char Mesquite_pci_IRQ_map[23] __prepdata =
-{
-	0,	/* Slot 0  - unused */
-	0,	/* Slot 1  - unused */
-	0,	/* Slot 2  - unused */
-	0,	/* Slot 3  - unused */
-	0,	/* Slot 4  - unused */
-	0,	/* Slot 5  - unused */
-	0,	/* Slot 6  - unused */
-	0,	/* Slot 7  - unused */
-	0,	/* Slot 8  - unused */
-	0,	/* Slot 9  - unused */
-	0,	/* Slot 10 - unused */
-	0,	/* Slot 11 - unused */
-	0,	/* Slot 12 - unused */
-	0,	/* Slot 13 - unused */
-	2,	/* Slot 14 - Ethernet */
-	0,	/* Slot 15 - unused */
-	3,	/* Slot 16 - PMC */
-	0,	/* Slot 17 - unused */
-	0,	/* Slot 18 - unused */
-	0,	/* Slot 19 - unused */
-	0,	/* Slot 20 - unused */
-	0,	/* Slot 21 - unused */
-	0,	/* Slot 22 - unused */
-};
-
-/* Motorola Sitka */
-static char Sitka_pci_IRQ_map[21] __prepdata =
-{
-	0,      /* Slot 0  - unused */
-	0,      /* Slot 1  - unused */
-	0,      /* Slot 2  - unused */
-	0,      /* Slot 3  - unused */
-	0,      /* Slot 4  - unused */
-	0,      /* Slot 5  - unused */
-	0,      /* Slot 6  - unused */
-	0,      /* Slot 7  - unused */
-	0,      /* Slot 8  - unused */
-	0,      /* Slot 9  - unused */
-	0,      /* Slot 10 - unused */
-	0,      /* Slot 11 - unused */
-	0,      /* Slot 12 - unused */
-	0,      /* Slot 13 - unused */
-	2,      /* Slot 14 - Ethernet */
-	0,      /* Slot 15 - unused */
-	9,      /* Slot 16 - PMC 1  */
-	12,     /* Slot 17 - PMC 2  */
-	0,      /* Slot 18 - unused */
-	0,      /* Slot 19 - unused */
-	4,      /* Slot 20 - NT P2P bridge */
-};
-
-/* Motorola MTX */
-static char MTX_pci_IRQ_map[23] __prepdata =
-{
-	0,	/* Slot 0  - unused */
-	0,	/* Slot 1  - unused */
-	0,	/* Slot 2  - unused */
-	0,	/* Slot 3  - unused */
-	0,	/* Slot 4  - unused */
-	0,	/* Slot 5  - unused */
-	0,	/* Slot 6  - unused */
-	0,	/* Slot 7  - unused */
-	0,	/* Slot 8  - unused */
-	0,	/* Slot 9  - unused */
-	0,	/* Slot 10 - unused */
-	0,	/* Slot 11 - unused */
-	3,	/* Slot 12 - SCSI */
-	0,	/* Slot 13 - unused */
-	2,	/* Slot 14 - Ethernet */
-	0,	/* Slot 15 - unused */
-	9,      /* Slot 16 - PCI/PMC slot 1 */
-	10,     /* Slot 17 - PCI/PMC slot 2 */
-	11,     /* Slot 18 - PCI slot 3 */
-	0,	/* Slot 19 - unused */
-	0,	/* Slot 20 - unused */
-	0,	/* Slot 21 - unused */
-	0,	/* Slot 22 - unused */
-};
-
-/* Motorola MTX Plus */
-/* Secondary bus interrupt routing is not supported yet */
-static char MTXplus_pci_IRQ_map[23] __prepdata =
-{
-        0,      /* Slot 0  - unused */
-        0,      /* Slot 1  - unused */
-        0,      /* Slot 2  - unused */
-        0,      /* Slot 3  - unused */
-        0,      /* Slot 4  - unused */
-        0,      /* Slot 5  - unused */
-        0,      /* Slot 6  - unused */
-        0,      /* Slot 7  - unused */
-        0,      /* Slot 8  - unused */
-        0,      /* Slot 9  - unused */
-        0,      /* Slot 10 - unused */
-        0,      /* Slot 11 - unused */
-        3,      /* Slot 12 - SCSI */
-        0,      /* Slot 13 - unused */
-        2,      /* Slot 14 - Ethernet 1 */
-        0,      /* Slot 15 - unused */
-        9,      /* Slot 16 - PCI slot 1P */
-        10,     /* Slot 17 - PCI slot 2P */
-        11,     /* Slot 18 - PCI slot 3P */
-        10,     /* Slot 19 - Ethernet 2 */
-        0,      /* Slot 20 - P2P Bridge */
-        0,      /* Slot 21 - unused */
-        0,      /* Slot 22 - unused */
-};
-
-static char Raven_pci_IRQ_routes[] __prepdata =
-{
-   	0,	/* This is a dummy structure */
-};
-   
-/* Motorola MVME16xx */
-static char Genesis_pci_IRQ_map[16] __prepdata =
-{
-  	0,	/* Slot 0  - unused */
-  	0,	/* Slot 1  - unused */
-  	0,	/* Slot 2  - unused */
-  	0,	/* Slot 3  - unused */
-  	0,	/* Slot 4  - unused */
-  	0,	/* Slot 5  - unused */
-  	0,	/* Slot 6  - unused */
-  	0,	/* Slot 7  - unused */
-  	0,	/* Slot 8  - unused */
-  	0,	/* Slot 9  - unused */
-  	0,	/* Slot 10 - unused */
-  	0,	/* Slot 11 - unused */
-  	3,	/* Slot 12 - SCSI */
-  	0,	/* Slot 13 - unused */
-  	1,	/* Slot 14 - Ethernet */
-  	0,	/* Slot 15 - unused */
-};
-
-static char Genesis_pci_IRQ_routes[] __prepdata =
-{
-   	0,	/* Line 0 - Unused */
-   	10,	/* Line 1 */
-   	11,	/* Line 2 */
-   	14,	/* Line 3 */
-   	15	/* Line 4 */
-};
-   
-static char Genesis2_pci_IRQ_map[23] __prepdata =
-{
-	0,	/* Slot 0  - unused */
-	0,	/* Slot 1  - unused */
-	0,	/* Slot 2  - unused */
-	0,	/* Slot 3  - unused */
-	0,	/* Slot 4  - unused */
-	0,	/* Slot 5  - unused */
-	0,	/* Slot 6  - unused */
-	0,	/* Slot 7  - unused */
-	0,	/* Slot 8  - unused */
-	0,	/* Slot 9  - unused */
-	0,	/* Slot 10 - Ethernet */
-	0,	/* Slot 11 - Universe PCI - VME Bridge */
-	3,	/* Slot 12 - unused */
-	0,	/* Slot 13 - unused */
-	2,	/* Slot 14 - SCSI */
-	0,	/* Slot 15 - unused */
-	9,	/* Slot 16 - PMC 1 */
-	12,	/* Slot 17 - pci */
-	11,	/* Slot 18 - pci */
-	10,	/* Slot 19 - pci */
-	0,	/* Slot 20 - pci */
-	0,	/* Slot 21 - unused */
-	0,	/* Slot 22 - unused */
-};
-
-/* Motorola Series-E */
-static char Comet_pci_IRQ_map[23] __prepdata =
-{
-  	0,	/* Slot 0  - unused */
-  	0,	/* Slot 1  - unused */
-  	0,	/* Slot 2  - unused */
-  	0,	/* Slot 3  - unused */
-  	0,	/* Slot 4  - unused */
-  	0,	/* Slot 5  - unused */
-  	0,	/* Slot 6  - unused */
-  	0,	/* Slot 7  - unused */
-  	0,	/* Slot 8  - unused */
-  	0,	/* Slot 9  - unused */
-  	0,	/* Slot 10 - unused */
-  	0,	/* Slot 11 - unused */
-  	3,	/* Slot 12 - SCSI */
-  	0,	/* Slot 13 - unused */
-  	1,	/* Slot 14 - Ethernet */
-  	0,	/* Slot 15 - unused */
-	1,	/* Slot 16 - PCI slot 1 */
-	2,	/* Slot 17 - PCI slot 2 */
-	3,	/* Slot 18 - PCI slot 3 */
-	4,	/* Slot 19 - PCI bridge */
-	0,
-	0,
-	0,
-};
-
-static char Comet_pci_IRQ_routes[] __prepdata =
-{
-   	0,	/* Line 0 - Unused */
-   	10,	/* Line 1 */
-   	11,	/* Line 2 */
-   	14,	/* Line 3 */
-   	15	/* Line 4 */
-};
-
-/* Motorola Series-EX */
-static char Comet2_pci_IRQ_map[23] __prepdata =
-{
-	0,	/* Slot 0  - unused */
-	0,	/* Slot 1  - unused */
-	3,	/* Slot 2  - SCSI - NCR825A */
-	0,	/* Slot 3  - unused */
-	1,	/* Slot 4  - Ethernet - DEC2104X */
-	0,	/* Slot 5  - unused */
-	1,	/* Slot 6  - PCI slot 1 */
-	2,	/* Slot 7  - PCI slot 2 */
-	3,	/* Slot 8  - PCI slot 3 */
-	4,	/* Slot 9  - PCI bridge  */
-	0,	/* Slot 10 - unused */
-	0,	/* Slot 11 - unused */
-	3,	/* Slot 12 - SCSI - NCR825A */
-	0,	/* Slot 13 - unused */
-	1,	/* Slot 14 - Ethernet - DEC2104X */
-	0,	/* Slot 15 - unused */
-	1,	/* Slot 16 - PCI slot 1 */
-	2,	/* Slot 17 - PCI slot 2 */
-	3,	/* Slot 18 - PCI slot 3 */
-	4,	/* Slot 19 - PCI bridge */
-	0,
-	0,
-	0,
-};
-
-static char Comet2_pci_IRQ_routes[] __prepdata =
-{
-	0,	/* Line 0 - Unused */
-	10,	/* Line 1 */
-	11,	/* Line 2 */
-	14,	/* Line 3 */
-	15,	/* Line 4 */
-};
-
-/*
- * ibm 830 (and 850?).
- * This is actually based on the Carolina motherboard
- * -- Cort
- */
-static char ibm8xx_pci_IRQ_map[23] __prepdata = {
-        0, /* Slot 0  - unused */
-        0, /* Slot 1  - unused */
-        0, /* Slot 2  - unused */
-        0, /* Slot 3  - unused */
-        0, /* Slot 4  - unused */
-        0, /* Slot 5  - unused */
-        0, /* Slot 6  - unused */
-        0, /* Slot 7  - unused */
-        0, /* Slot 8  - unused */
-        0, /* Slot 9  - unused */
-        0, /* Slot 10 - unused */
-        0, /* Slot 11 - FireCoral */
-        4, /* Slot 12 - Ethernet  PCIINTD# */
-        2, /* Slot 13 - PCI Slot #2 */
-        2, /* Slot 14 - S3 Video PCIINTD# */
-        0, /* Slot 15 - onboard SCSI (INDI) [1] */
-        3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */
-        0, /* Slot 17 - unused */
-        2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
-        0, /* Slot 19 - unused */
-        0, /* Slot 20 - unused */
-        0, /* Slot 21 - unused */
-        2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
-};
-
-static char ibm8xx_pci_IRQ_routes[] __prepdata = {
-        0,      /* Line 0 - unused */
-        15,     /* Line 1 */
-        15,     /* Line 2 */
-        15,     /* Line 3 */
-        15,     /* Line 4 */
-};
-
-/*
- * a 6015 ibm board
- * -- Cort
- */
-static char ibm6015_pci_IRQ_map[23] __prepdata = {
-        0, /* Slot 0  - unused */
-        0, /* Slot 1  - unused */
-        0, /* Slot 2  - unused */
-        0, /* Slot 3  - unused */
-        0, /* Slot 4  - unused */
-        0, /* Slot 5  - unused */
-        0, /* Slot 6  - unused */
-        0, /* Slot 7  - unused */
-        0, /* Slot 8  - unused */
-        0, /* Slot 9  - unused */
-        0, /* Slot 10 - unused */
-        0, /* Slot 11 -  */
-        1, /* Slot 12 - SCSI */
-        2, /* Slot 13 -  */
-        2, /* Slot 14 -  */
-        1, /* Slot 15 -  */
-        1, /* Slot 16 -  */
-        0, /* Slot 17 -  */
-        2, /* Slot 18 -  */
-        0, /* Slot 19 -  */
-        0, /* Slot 20 -  */
-        0, /* Slot 21 -  */
-        2, /* Slot 22 -  */
-};
-
-static char ibm6015_pci_IRQ_routes[] __prepdata = {
-        0,      /* Line 0 - unused */
-        13,     /* Line 1 */
-        15,     /* Line 2 */
-        15,     /* Line 3 */
-        15,     /* Line 4 */
-};
-
-
-/* IBM Nobis and Thinkpad 850 */
-static char Nobis_pci_IRQ_map[23] __prepdata ={
-        0, /* Slot 0  - unused */
-        0, /* Slot 1  - unused */
-        0, /* Slot 2  - unused */
-        0, /* Slot 3  - unused */
-        0, /* Slot 4  - unused */
-        0, /* Slot 5  - unused */
-        0, /* Slot 6  - unused */
-        0, /* Slot 7  - unused */
-        0, /* Slot 8  - unused */
-        0, /* Slot 9  - unused */
-        0, /* Slot 10 - unused */
-        0, /* Slot 11 - unused */
-        3, /* Slot 12 - SCSI */
-        0, /* Slot 13 - unused */
-        0, /* Slot 14 - unused */
-        0, /* Slot 15 - unused */
-};
-
-static char Nobis_pci_IRQ_routes[] __prepdata = {
-        0, /* Line 0 - Unused */
-        13, /* Line 1 */
-        13, /* Line 2 */
-        13, /* Line 3 */
-        13      /* Line 4 */
-};
-
-/*
- * IBM RS/6000 43p/140  -- paulus
- * XXX we should get all this from the residual data
- */
-static char ibm43p_pci_IRQ_map[23] __prepdata = {
-        0, /* Slot 0  - unused */
-        0, /* Slot 1  - unused */
-        0, /* Slot 2  - unused */
-        0, /* Slot 3  - unused */
-        0, /* Slot 4  - unused */
-        0, /* Slot 5  - unused */
-        0, /* Slot 6  - unused */
-        0, /* Slot 7  - unused */
-        0, /* Slot 8  - unused */
-        0, /* Slot 9  - unused */
-        0, /* Slot 10 - unused */
-        0, /* Slot 11 - FireCoral ISA bridge */
-        6, /* Slot 12 - Ethernet  */
-        0, /* Slot 13 - openpic */
-        0, /* Slot 14 - unused */
-        0, /* Slot 15 - unused */
-        7, /* Slot 16 - NCR58C825a onboard scsi */
-        0, /* Slot 17 - unused */
-        2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
-        0, /* Slot 19 - unused */
-        0, /* Slot 20 - unused */
-        0, /* Slot 21 - unused */
-        1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
-};
-
-static char ibm43p_pci_IRQ_routes[] __prepdata = {
-        0,      /* Line 0 - unused */
-        15,     /* Line 1 */
-        15,     /* Line 2 */
-        15,     /* Line 3 */
-        15,     /* Line 4 */
-};
-
-/* Motorola PowerPlus architecture PCI IRQ tables */
-/* Interrupt line values for INTA-D on primary/secondary MPIC inputs */
-
-struct powerplus_irq_list
-{
-	unsigned char primary[4];       /* INT A-D */
-	unsigned char secondary[4];     /* INT A-D */
-};
-
-/*
- * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to
- * OpenPIC inputs 9-12.  PCI INTs A-D from the on board P2P bridge
- * are routed to OpenPIC inputs 5-8.  These values are offset by
- * 16 in the table to reflect the Linux kernel interrupt value.
- */
-struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
-{
-	{25, 26, 27, 28},
-	{21, 22, 23, 24}
-};
-
-/*
- * For the MCP750 (system slot board), cPCI INTs A-D are routed to
- * OpenPIC inputs 8-11 and the PMC INTs A-D are routed to OpenPIC
- * input 3.  On a hot swap MCP750, the companion card PCI INTs A-D
- * are routed to OpenPIC inputs 12-15. These values are offset by
- * 16 in the table to reflect the Linux kernel interrupt value.
- */
-struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
-{
-	{24, 25, 26, 27},
-	{28, 29, 30, 31}
-};
-
-/*
- * This table represents the standard PCI swizzle defined in the
- * PCI bus specification.
- */
-static unsigned char prep_pci_intpins[4][4] __prepdata =
-{
-	{ 1, 2, 3, 4},  /* Buses 0, 4, 8, ... */
-	{ 2, 3, 4, 1},  /* Buses 1, 5, 9, ... */
-	{ 3, 4, 1, 2},  /* Buses 2, 6, 10 ... */
-	{ 4, 1, 2, 3},  /* Buses 3, 7, 11 ... */
-};
-
-/* We have to turn on LEVEL mode for changed IRQ's */
-/* All PCI IRQ's need to be level mode, so this should be something
- * other than hard-coded as well... IRQ's are individually mappable
- * to either edge or level.
- */
-
-/*
- * 8259 edge/level control definitions
- */
-#define ISA8259_M_ELCR 0x4d0
-#define ISA8259_S_ELCR 0x4d1
-
-#define ELCRS_INT15_LVL         0x80
-#define ELCRS_INT14_LVL         0x40
-#define ELCRS_INT12_LVL         0x10
-#define ELCRS_INT11_LVL         0x08
-#define ELCRS_INT10_LVL         0x04
-#define ELCRS_INT9_LVL          0x02
-#define ELCRS_INT8_LVL          0x01
-#define ELCRM_INT7_LVL          0x80
-#define ELCRM_INT5_LVL          0x20
-
-#define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset)
-#define DEVNO(dev)  (dev>>3)                                  
-
-#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
-#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
-
-#define cfg_read_bad(val, size)		*val = bad_##size;
-#define cfg_write_bad(val, size)
-
-#define bad_byte	0xff
-#define bad_word	0xffff
-#define bad_dword	0xffffffffU
-
-#define PREP_PCI_OP(rw, size, type, op)					\
-static int __prep							\
-prep_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
-{									\
-	if ((dev->bus->number != 0) || (DEVNO(dev->devfn) > MAX_DEVNR))	\
-	{                   						\
-		cfg_##rw##_bad(val, size)				\
-		return PCIBIOS_DEVICE_NOT_FOUND;    			\
-	}								\
-	cfg_##rw(val, CFGPTR(dev->devfn), type, op);			\
-	return PCIBIOS_SUCCESSFUL;					\
-}
-
-PREP_PCI_OP(read, byte, u8 *, in_8)
-PREP_PCI_OP(read, word, u16 *, in_le16)
-PREP_PCI_OP(read, dword, u32 *, in_le32)
-PREP_PCI_OP(write, byte, u8, out_8)
-PREP_PCI_OP(write, word, u16, out_le16)
-PREP_PCI_OP(write, dword, u32, out_le32)
-
-static struct pci_ops prep_pci_ops =
-{
-	prep_read_config_byte,
-	prep_read_config_word,
-	prep_read_config_dword,
-	prep_write_config_byte,
-	prep_write_config_word,
-	prep_write_config_dword
-};
-
-#define MOTOROLA_CPUTYPE_REG	0x800
-#define MOTOROLA_BASETYPE_REG	0x803
-#define MPIC_RAVEN_ID		0x48010000
-#define	MPIC_HAWK_ID		0x48030000
-#define	MOT_PROC2_BIT		0x800
-
-static u_char mvme2600_openpic_initsenses[] __initdata = {
-    1,	/* MVME2600_INT_SIO */
-    0,	/* MVME2600_INT_FALCN_ECC_ERR */
-    1,	/* MVME2600_INT_PCI_ETHERNET */
-    1,	/* MVME2600_INT_PCI_SCSI */
-    1,	/* MVME2600_INT_PCI_GRAPHICS */
-    1,	/* MVME2600_INT_PCI_VME0 */
-    1,	/* MVME2600_INT_PCI_VME1 */
-    1,	/* MVME2600_INT_PCI_VME2 */
-    1,	/* MVME2600_INT_PCI_VME3 */
-    1,	/* MVME2600_INT_PCI_INTA */
-    1,	/* MVME2600_INT_PCI_INTB */
-    1,	/* MVME2600_INT_PCI_INTC */
-    1,	/* MVME2600_INT_PCI_INTD */
-    1,	/* MVME2600_INT_LM_SIG0 */
-    1,	/* MVME2600_INT_LM_SIG1 */
-};
-
-#define MOT_RAVEN_PRESENT	0x1
-#define MOT_HAWK_PRESENT	0x2
-
-int mot_entry = -1;
-int prep_keybd_present = 1;
-int MotMPIC;
-int mot_multi;
-
-int __init
-raven_init(void)
-{
-	unsigned int	devid;
-	unsigned int	pci_membase;
-	unsigned char	base_mod;
-
-	/* Check to see if the Raven chip exists. */
-	if ( _prep_type != _PREP_Motorola) {
-		OpenPIC_Addr = NULL;
-		return 0;
-	}
-
-	/* Check to see if this board is a type that might have a Raven. */
-	if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
-		OpenPIC_Addr = NULL;
-		return 0;
-	}
-
-	/* Check the first PCI device to see if it is a Raven. */
-	early_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &devid);
-
-	switch (devid & 0xffff0000) {
-	case MPIC_RAVEN_ID:
-		MotMPIC = MOT_RAVEN_PRESENT;
-		break;
-	case MPIC_HAWK_ID:
-		MotMPIC = MOT_HAWK_PRESENT;
-		break;
-	default:
-		OpenPIC_Addr = NULL;
-		return 0;
-	}
-
-
-	/* Read the memory base register. */
-	early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
-
-	if (pci_membase == 0) {
-		OpenPIC_Addr = NULL;
-		return 0;
-	}
-
-	/* Map the Raven MPIC registers to virtual memory. */
-	OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000);
-
-	OpenPIC_InitSenses = mvme2600_openpic_initsenses;
-	OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
-
-	ppc_md.get_irq = openpic_get_irq;
-	
-	/* If raven is present on Motorola store the system config register
-	 * for later use.
-	 */
-	ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
-
-	/* Indicate to system if this is a multiprocessor board */
-	if (!(*ProcInfo & MOT_PROC2_BIT)) {
-		mot_multi = 1;
-	}
-
-	/* This is a hack.  If this is a 2300 or 2400 mot board then there is
-	 * no keyboard controller and we have to indicate that.
-	 */
-	base_mod = inb(MOTOROLA_BASETYPE_REG);
-	if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
-	    (base_mod == 0xFA) || (base_mod == 0xE1))
-		prep_keybd_present = 0;
-
-	return 1;
-}
-
-struct mot_info {
-	int		cpu_type;	/* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
-					/* 0x200 if this board has a Hawk chip. */
-	int		base_type;
-	int		max_cpu;	/* ored with 0x80 if this board should be checked for multi CPU */
-	const char	*name;
-	unsigned char	*map;
-	unsigned char	*routes;
-	void            (*map_non0_bus)(struct pci_dev *);      /* For boards with more than bus 0 devices. */
-	struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
-	unsigned char   secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
-} mot_info[] __prepdata = {
-	{0x300, 0x00, 0x00, "MVME 2400",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x010, 0x00, 0x00, "Genesis",				Genesis_pci_IRQ_map,	Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
-	{0x020, 0x00, 0x00, "Powerstack (Series E)",		Comet_pci_IRQ_map,	Comet_pci_IRQ_routes, NULL, NULL, 0x00},
-	{0x040, 0x00, 0x00, "Blackhawk (Powerstack)",		Blackhawk_pci_IRQ_map,	Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00},
-	{0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)",	Omaha_pci_IRQ_map,	Omaha_pci_IRQ_routes, NULL, NULL, 0x00},
-	{0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)",	Utah_pci_IRQ_map,	Utah_pci_IRQ_routes, NULL, NULL, 0x00},
-	{0x0A0, 0x00, 0x00, "Powerstack (Series EX)",		Comet2_pci_IRQ_map,	Comet2_pci_IRQ_routes, NULL, NULL, 0x00},
-	{0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)",		Mesquite_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)",		Sitka_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC",	Mesquite_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0},
-	{0x1E0, 0xF6, 0x80, "MTX Plus",				MTXplus_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
-	{0x1E0, 0xF6, 0x81, "Dual MTX Plus",			MTXplus_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
-	{0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port",		MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
-	{0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port",	MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
-	{0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port",		MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
-	{0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port",	MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
-	{0x1E0, 0xF9, 0x00, "MVME 2300",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFA, 0x00, "MVME 2300SC/2600",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761",	Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
-	{0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011",	Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
-	{0x000, 0x00, 0x00, "",					NULL,			NULL, NULL, NULL, 0x00}
-};
-
-void __init
-ibm_prep_init(void)
-{
-	u32 addr;
-#ifdef CONFIG_PREP_RESIDUAL
-	PPC_DEVICE *mpic;
-#endif
-
-	if (inb(0x0852) == 0xd5) {
-		/* This is for the 43p-140 */
-		early_read_config_dword(0, 0, PCI_DEVFN(13, 0),
-					PCI_BASE_ADDRESS_0, &addr);
-		if (addr != 0xffffffff
-		    && !(addr & PCI_BASE_ADDRESS_SPACE_IO)
-		    && (addr &= PCI_BASE_ADDRESS_MEM_MASK) != 0) {
-			addr += PREP_ISA_MEM_BASE;
-			OpenPIC_Addr = ioremap(addr, 0x40000);
-			ppc_md.get_irq = openpic_get_irq;
-		}
-	}
-
-#ifdef CONFIG_PREP_RESIDUAL
-	mpic = residual_find_device(-1, NULL, SystemPeripheral,
-				    ProgrammableInterruptController, MPIC, 0);
-	if (mpic != NULL)
-		printk("mpic = %p\n", mpic);
-#endif
-}
-
-static void __init
-ibm43p_pci_map_non0(struct pci_dev *dev)
-{
-	unsigned char intpin;
-	static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 };
-
-	if (dev == NULL)
-		return;
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
-	if (intpin < 1 || intpin > 4)
-		return;
-	intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3;
-	dev->irq = openpic_to_irq(bridge_intrs[intpin]);
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-}
-
-void __init
-prep_route_pci_interrupts(void)
-{
-	unsigned char *ibc_pirq = (unsigned char *)0x80800860;
-	unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
-	int i;
-	
-	if ( _prep_type == _PREP_Motorola)
-	{
-		unsigned short irq_mode;
-		unsigned char  cpu_type;
-		unsigned char  base_mod;
-		int	       entry;
-
-		cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
-		base_mod = inb(MOTOROLA_BASETYPE_REG);
-
-		for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
-			if (mot_info[entry].cpu_type & 0x200) {		 	/* Check for Hawk chip */
-				if (!(MotMPIC & MOT_HAWK_PRESENT))
-					continue;
-			} else {						/* Check non hawk boards */
-				if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
-					continue;
-
-				if (mot_info[entry].base_type == 0) {
-					mot_entry = entry;
-					break;
-				}
-
-				if (mot_info[entry].base_type != base_mod)
-					continue;
-			}
-
-			if (!(mot_info[entry].max_cpu & 0x80)) {
-				mot_entry = entry;
-				break;
-			}
-
-			/* processor 1 not present and max processor zero indicated */
-			if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
-				mot_entry = entry;
-				break;
-			}
-
-			/* processor 1 present and max processor zero indicated */
-			if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
-				mot_entry = entry;
-				break;
-			}
-		}
-
-		if (mot_entry == -1) 	/* No particular cpu type found - assume Blackhawk */
-			mot_entry = 3;
-
-		Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
-		Motherboard_map = mot_info[mot_entry].map;
-		Motherboard_routes = mot_info[mot_entry].routes;
-		Motherboard_non0 = mot_info[mot_entry].map_non0_bus;
-
-		if (!(mot_info[entry].cpu_type & 0x100)) {
-			/* AJF adjust level/edge control according to routes */
-			irq_mode = 0;
-			for (i = 1;  i <= 4;  i++)
-				irq_mode |= ( 1 << Motherboard_routes[i] );
-			outb( irq_mode & 0xff, 0x4d0 );
-			outb( (irq_mode >> 8) & 0xff, 0x4d1 );
-		}
-	} else if ( _prep_type == _PREP_IBM ) {
-		unsigned char planar_id = inb(0x0852);
-		unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
-
-		printk("IBM ID: %08x\n", planar_id);
-		switch(planar_id) {
-		case 0xff:
-			Motherboard_map_name = "IBM Thinkpad 850/860";
-			Motherboard_map = Nobis_pci_IRQ_map;
-			Motherboard_routes = Nobis_pci_IRQ_routes;
-			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
-			irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
-			break;
-		case 0xfc:
-			Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
-			Motherboard_map = ibm6015_pci_IRQ_map;
-			Motherboard_routes = ibm6015_pci_IRQ_routes;
-			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
-			irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
-			break;
-		case 0xd5:
-			Motherboard_map_name = "IBM 43P-140 (Tiger1)";
-			Motherboard_map = ibm43p_pci_IRQ_map;
-			Motherboard_routes = ibm43p_pci_IRQ_routes;
-			Motherboard_non0 = ibm43p_pci_map_non0;
-			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
-			irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
-			break;
-		default:
-			printk(KERN_ERR "Unknown IBM motherboard! Defaulting to Carolina.\n");
-		case 0xf0: /* PowerSeries 830/850 */
-		case 0xf1: /* PowerSeries 830/850 */
-		case 0xf2: /* PowerSeries 830/850 */
-		case 0xf4: /* 7248-43P */
-		case 0xf5: /* 7248-43P */
-		case 0xf6: /* 7248-43P */
-		case 0xf7: /* 7248-43P (missing from Carolina Tech Spec) */
-			Motherboard_map_name = "IBM PS830/PS850/7248 (Carolina)";
-			Motherboard_map = ibm8xx_pci_IRQ_map;
-			Motherboard_routes = ibm8xx_pci_IRQ_routes;
-			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
-			irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
-			break;
-		}
-
-		outb(inb(0x04d0)|irq_edge_mask_lo, 0x04d0); /* primary 8259 */
-		outb(inb(0x04d1)|irq_edge_mask_hi, 0x04d1); /* cascaded 8259 */
-	} else {
-		printk("No known machine pci routing!\n");
-		return;
-	}
-	
-	/* Set up mapping from slots */
-	for (i = 1;  i <= 4;  i++)
-		ibc_pirq[i-1] = Motherboard_routes[i];
-	/* Enable PCI interrupts */
-	*ibc_pcicon |= 0x20;
-}
-
-void __init
-prep_pib_init(void)
-{
-	unsigned char   reg;
-	unsigned short  short_reg;
-
-	struct pci_dev *dev = NULL;
-
-	if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) {
-		/*
-		 * Perform specific configuration for the Via Tech or
-		 * or Winbond PCI-ISA-Bridge part.
-		 */
-		if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, 
-					PCI_DEVICE_ID_VIA_82C586_1, dev))) {
-			/*
-			 * PPCBUG does not set the enable bits
-			 * for the IDE device. Force them on here.
-			 */
-			pci_read_config_byte(dev, 0x40, &reg);
-
-			reg |= 0x03; /* IDE: Chip Enable Bits */
-			pci_write_config_byte(dev, 0x40, reg);
-		}
-		if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
-						PCI_DEVICE_ID_VIA_82C586_2,
-						dev)) && (dev->devfn = 0x5a)) {
-			/* Force correct USB interrupt */
-			dev->irq = 11;
-			pci_write_config_byte(dev,
-					PCI_INTERRUPT_LINE,
-					dev->irq);
-		}
-		if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
-					PCI_DEVICE_ID_WINBOND_83C553, dev))) {
-			 /* Clear PCI Interrupt Routing Control Register. */
-			short_reg = 0x0000;
-			pci_write_config_word(dev, 0x44, short_reg);
-			if (OpenPIC_Addr){
-				/* Route IDE interrupts to IRQ 14 */
-				reg = 0xEE;
-				pci_write_config_byte(dev, 0x43, reg);
-			}
-		}
-	}
-
-	if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
-				   PCI_DEVICE_ID_WINBOND_82C105, dev))){
-		if (OpenPIC_Addr){
-			/*
-			 * Disable LEGIRQ mode so PCI INTS are routed
-			 * directly to the 8259 and enable both channels
-			 */
-			pci_write_config_dword(dev, 0x40, 0x10ff0033);
-
-			/* Force correct IDE interrupt */
-			dev->irq = 14;
-			pci_write_config_byte(dev,
-					PCI_INTERRUPT_LINE,
-					dev->irq);
-		} else {
-			/* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */
-			pci_write_config_dword(dev, 0x40, 0x10ff08a1);
-		}
-	}
-}
-
-static void __init
-Powerplus_Map_Non0(struct pci_dev *dev)
-{
-	struct pci_bus  *pbus;          /* Parent bus structure pointer */
-	struct pci_dev  *tdev = dev;    /* Temporary device structure */
-	unsigned int    devnum;         /* Accumulated device number */
-	unsigned char   intline;        /* Linux interrupt value */
-	unsigned char   intpin;         /* PCI interrupt pin */
-
-	/* Check for valid PCI dev pointer */
-	if (dev == NULL) return;
-
-	/* Initialize bridge IDSEL variable */
-	devnum = PCI_SLOT(tdev->devfn);
-
-	/* Read the interrupt pin of the device and adjust for indexing */
-	pcibios_read_config_byte(dev->bus->number, dev->devfn,
-			PCI_INTERRUPT_PIN, &intpin);
-
-	/* If device doesn't request an interrupt, return */
-	if ( (intpin < 1) || (intpin > 4) )
-		return;
-
-	intpin--;
-
-	/*
-	 * Walk up to bus 0, adjusting the interrupt pin for the standard
-	 * PCI bus swizzle.
-	 */
-	do {
-		intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
-		pbus = tdev->bus;        /* up one level */
-		tdev = pbus->self;
-		devnum = PCI_SLOT(tdev->devfn);
-	} while(tdev->bus->number);
-
-	/* Use the primary interrupt inputs by default */
-	intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
-
-	/*
-	 * If the board has secondary interrupt inputs, walk the bus and
-	 * note the devfn of the bridge from bus 0.  If it is the same as
-	 * the devfn of the bus bridge with secondary inputs, use those.
-	 * Otherwise, assume it's a PMC site and get the interrupt line
-	 * value from the interrupt routing table.
-	 */ 
-	if (mot_info[mot_entry].secondary_bridge_devfn) {
-		pbus = dev->bus;
-
-		while (pbus->primary != 0)
-			pbus = pbus->parent;
-
-		if ((pbus->self)->devfn != 0xA0) {
-			if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn)
-				intline = mot_info[mot_entry].pci_irq_list->secondary[intpin];
-			else {
-				if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map)
-					intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16;
-				else {
-					int i;
-					for (i=0;i<3;i++)
-						intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
-					intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
-				}
-			}
-		}
-	}
-
-	/* Write calculated interrupt value to header and device list */
-	dev->irq = intline;
-	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq);
-}
-
-void __init
-prep_pcibios_fixup(void)
-{
-        struct pci_dev *dev;
-        extern unsigned char *Motherboard_map;
-        extern unsigned char *Motherboard_routes;
-        unsigned char i;
-
-	prep_route_pci_interrupts();
-
-	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
-	if (OpenPIC_Addr) {
-		/* PCI interrupts are controlled by the OpenPIC */
-		pci_for_each_dev(dev) {
-			if (dev->bus->number == 0) {
-                       		dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
-				pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq);
-			} else {
-				if (Motherboard_non0 != NULL)
-					Motherboard_non0(dev);
-			}
-		}
-
-		/* Setup the Winbond or Via PIB */
-		prep_pib_init();
-
-		return;
-	}
-
-	pci_for_each_dev(dev) {
-		/*
-		 * Use our old hard-coded kludge to figure out what
-		 * irq this device uses.  This is necessary on things
-		 * without residual data. -- Cort
-		 */
-		unsigned char d = PCI_SLOT(dev->devfn);
-		dev->irq = Motherboard_routes[Motherboard_map[d]];
-
-		for ( i = 0 ; i <= 5 ; i++ ) {
-			/*
-			 * Relocate PCI I/O resources if necessary so the
-			 * standard 256MB BAT covers them.
-			 */
-			if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) &&
-				      (dev->resource[i].start > 0x10000000))  {
-				printk("Relocating PCI address %lx -> %lx\n",
-						dev->resource[i].start,
-						(dev->resource[i].start & 
-						 0x00FFFFFF)| 0x01000000);
-				dev->resource[i].start =
-					(dev->resource[i].start & 0x00FFFFFF)
-					| 0x01000000;
-		                pci_write_config_dword(dev,
-						PCI_BASE_ADDRESS_0 + (i*0x4),
-						dev->resource[i].start);
-				dev->resource[i].end = 
-					(dev->resource[i].end & 0x00FFFFFF)
-					| 0x01000000;
-		        }
-		}
-#if 0
-		/*
-		 * If we have residual data and if it knows about this
-		 * device ask it what the irq is.
-		 *  -- Cort
-		 */
-		ppcd = residual_find_device_id( ~0L, dev->device,
-		                                -1,-1,-1, 0);
-#endif
-	}
-}
-
-static void __init
-prep_pcibios_after_init(void)
-{
-	struct pci_dev *dev;
-	
-	/* If there is a WD 90C, reset the IO BAR to 0x0 (it started that 
-	 * way, but the PCI layer relocated it because it thought 0x0 was
-	 * invalid for a BAR).
-	 * If you don't do this, the card's VGA base will be <IO BAR>+0xc0000
-	 * instead of 0xc0000. vgacon.c (for example) is completely unaware of
-	 * this little quirk.
-	 */
-	dev = pci_find_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL);
-	if (dev) {
-		dev->resource[1].end -= dev->resource[1].start;
-		dev->resource[1].start = 0;
-		/* tell the hardware */
-		pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0);
-	}
-}
-
-static void __init
-prep_init_resource(struct resource *res, unsigned long start,
-		   unsigned long end, int flags)
-{
-	res->flags = flags;
-	res->start = start;
-	res->end = end;
-	res->name = "PCI host bridge";
-	res->parent = NULL;
-	res->sibling = NULL;
-	res->child = NULL;
-}
-
-void __init
-prep_find_bridges(void)
-{
-	struct pci_controller* hose;
-
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-	hose->pci_mem_offset = PREP_ISA_MEM_BASE;
-	hose->io_base_phys = PREP_ISA_IO_BASE;
-	hose->io_base_virt = (void *)0x80000000; /* see prep_map_io() */
-	prep_init_resource(&hose->io_resource, 0, 0x0fffffff, IORESOURCE_IO);
-	prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff,
-			   IORESOURCE_MEM);
-	
-	printk("PReP architecture\n");
-	{
-#ifdef CONFIG_PREP_RESIDUAL	  
-		PPC_DEVICE *hostbridge;
-
-		hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
-			BridgeController, PCIBridge, -1, 0);
-		if (hostbridge &&
-			hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
-			PnP_TAG_PACKET * pkt;
-			pkt = PnP_find_large_vendor_packet(
-				res->DevicePnPHeap+hostbridge->AllocatedOffset,
-				3, 0);
-			if(pkt) {
-#define p pkt->L4_Pack.L4_Data.L4_PPCPack
-				setup_indirect_pci(hose, 
-					ld_le32((unsigned *) (p.PPCData)),
-					ld_le32((unsigned *) (p.PPCData+8)));
-			} else
-				setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
-		} else
-#endif /* CONFIG_PREP_RESIDUAL */
-			hose->ops = &prep_pci_ops;
-	}
-
-	ppc_md.pcibios_fixup = prep_pcibios_fixup;
-	ppc_md.pcibios_after_init = prep_pcibios_after_init;
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- linux.orig/arch/ppc/kernel/prep_setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/prep_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,906 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_setup.c 1.52 04/05/02 10:17:22 trini
- */
-/*
- *  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)
- *
- * Support for PReP (Motorola MTX/MVME)
- * by Troy Benjegerdes (hozer@drgw.net)
- */
-
-/*
- * bootup setup stuff..
- */
-
-#include <linux/config.h>
-#include <linux/delay.h>
-#include <linux/module.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/slab.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/ioport.h>
-#include <linux/console.h>
-#include <linux/timex.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-#include <linux/seq_file.h>
-
-#include <asm/sections.h>
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/residual.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/cache.h>
-#include <asm/dma.h>
-#include <asm/machdep.h>
-#include <asm/mk48t59.h>
-#include <asm/prep_nvram.h>
-#include <asm/raven.h>
-#include <asm/keyboard.h>
-#include <asm/vga.h>
-#include <asm/time.h>
-
-#include "local_irq.h"
-#include "i8259.h"
-#include "open_pic.h"
-
-#if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
-#include <../drivers/sound/sound_config.h>
-#include <../drivers/sound/dev_table.h>
-#endif
-
-unsigned char ucSystemType;
-unsigned char ucBoardRev;
-unsigned char ucBoardRevMaj, ucBoardRevMin;
-
-extern unsigned long mc146818_get_rtc_time(void);
-extern int mc146818_set_rtc_time(unsigned long nowtime);
-extern unsigned long mk48t59_get_rtc_time(void);
-extern int mk48t59_set_rtc_time(unsigned long nowtime);
-
-extern unsigned char prep_nvram_read_val(int addr);
-extern void prep_nvram_write_val(int addr,
-				 unsigned char val);
-extern unsigned char rs_nvram_read_val(int addr);
-extern void rs_nvram_write_val(int addr,
-				 unsigned char val);
-extern void ibm_prep_init(void);
-
-extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
-extern int pckbd_getkeycode(unsigned int scancode);
-extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
-		char raw_mode);
-extern char pckbd_unexpected_up(unsigned char keycode);
-extern void pckbd_leds(unsigned char leds);
-extern void pckbd_init_hw(void);
-extern unsigned char pckbd_sysrq_xlate[];
-
-extern void prep_find_bridges(void);
-extern char saved_command_line[];
-
-int _prep_type;
-
-#define cached_21	(((char *)(ppc_cached_irq_mask))[3])
-#define cached_A1	(((char *)(ppc_cached_irq_mask))[2])
-
-/* for the mac fs */
-kdev_t boot_dev;
-/* used in nasty hack for sound - see prep_setup_arch() -- Cort */
-long ppc_cs4232_dma, ppc_cs4232_dma2;
-
-extern PTE *Hash, *Hash_end;
-extern unsigned long Hash_size, Hash_mask;
-extern int probingmem;
-extern unsigned long loops_per_jiffy;
-
-#ifdef CONFIG_SOUND_MODULE
-EXPORT_SYMBOL(ppc_cs4232_dma);
-EXPORT_SYMBOL(ppc_cs4232_dma2);
-#endif
-
-static int __prep
-prep_show_cpuinfo(struct seq_file *m)
-{
-	extern char *Motherboard_map_name;
-	int cachew;
-#ifdef CONFIG_PREP_RESIDUAL
-	int i;
-#endif
-
-	seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
-
-	switch ( _prep_type ) {
-	case _PREP_IBM:
-		cachew = inw(0x80c);
-		if (cachew & (1<<6))
-			seq_printf(m, "Upgrade CPU\n");
-		seq_printf(m, "L2\t\t: ");
-		if (cachew & (1<<7)) {
-			seq_printf(m, "not present\n");
-			goto no_l2;
-		}
-		seq_printf(m, "%sKb,", (cachew & (1 << 10))? "512" : "256");
-		seq_printf(m, "%ssync\n", (cachew & (1 << 15))? "" : "a");
-		break;
-	case _PREP_Motorola:
-		cachew = *((unsigned char *)CACHECRBA);
-		seq_printf(m, "L2\t\t: ");
-		switch (cachew & L2CACHE_MASK) {
-		case L2CACHE_512KB:
-			seq_printf(m, "512Kb");
-			break;
-		case L2CACHE_256KB:
-			seq_printf(m, "256Kb");
-			break;
-		case L2CACHE_1MB:
-			seq_printf(m, "1MB");
-			break;
-		case L2CACHE_NONE:
-			seq_printf(m, "none\n");
-			goto no_l2;
-			break;
-		default:
-			seq_printf(m, "%x\n", cachew);
-		}
-		
-		seq_printf(m, ", parity %s",
-			   (cachew & L2CACHE_PARITY)? "enabled" : "disabled");
-
-		seq_printf(m, " SRAM:");
-		
-		switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
-		case 1: seq_printf(m, "synchronous,parity,flow-through\n");
-			break;
-		case 2: seq_printf(m, "asynchronous,no parity\n");
-			break;
-		case 3: seq_printf(m, "asynchronous,parity\n");
-			break;
-		default:seq_printf(m, "synchronous,pipelined,no parity\n");
-			break;
-		}
-		break;
-	default:
-		break;
-	}
-
-no_l2:
-#ifdef CONFIG_PREP_RESIDUAL
-	if (res->ResidualLength != 0) {
-		/* print info about SIMMs */
-		seq_printf(m, "simms\t\t: ");
-		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
-			if (res->Memories[i].SIMMSize != 0)
-				seq_printf(m, "%d:%ldM ", i,
-					(res->Memories[i].SIMMSize > 1024) ? 
-					res->Memories[i].SIMMSize>>20 : 
-					res->Memories[i].SIMMSize);
-		}
-		seq_printf(m, "\n");
-	}
-#endif
-
-	return 0;
-}
-
-static int __prep
-prep_show_percpuinfo(struct seq_file *m, int i)
-{
-	/* PREP's without residual data will give incorrect values here */
-	seq_printf(m, "clock\t\t: ");
-#ifdef CONFIG_PREP_RESIDUAL	
-	if (res->ResidualLength)
-		seq_printf(m, "%ldMHz\n",
-			   (res->VitalProductData.ProcessorHz > 1024) ?
-			   res->VitalProductData.ProcessorHz / 1000000 :
-			   res->VitalProductData.ProcessorHz);
-	else
-#endif /* CONFIG_PREP_RESIDUAL */
-		seq_printf(m, "???\n");
-
-	return 0;
-}
-
-static void __init
-prep_setup_arch(void)
-{
-	unsigned char reg;
-#if 0 /* unused?? */
-	unsigned char ucMothMemType;
-	unsigned char ucEquipPres1;
-#endif
-
-	/* init to some ~sane value until calibrate_delay() runs */
-	loops_per_jiffy = 50000000;
-	
-	/* Lookup PCI host bridges */
-	prep_find_bridges();
-	
-	/* Set up floppy in PS/2 mode */
-	outb(0x09, SIO_CONFIG_RA);
-	reg = inb(SIO_CONFIG_RD);
-	reg = (reg & 0x3F) | 0x40;
-	outb(reg, SIO_CONFIG_RD);
-	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
-
-	/* we should determine this according to what we find! -- Cort */
-	switch ( _prep_type )
-	{
-	case _PREP_IBM:
-		/* Enable L2.  Assume we don't need to flush -- Cort*/
-		*(unsigned char *)(0x8000081c) |= 3;
-		ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
-		break;
-	case _PREP_Motorola:
-		/* Enable L2.  Assume we don't need to flush -- Cort*/
-		*(unsigned char *)(0x8000081c) |= 3;
-#ifdef CONFIG_BLK_DEV_INITRD
-		if (initrd_start)
-			ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
-		else
-#endif
-#ifdef CONFIG_ROOT_NFS
-			ROOT_DEV = to_kdev_t(0x00ff); /* /dev/nfs */
-#else
-			ROOT_DEV = to_kdev_t(0x0802); /* /dev/sda2 */
-#endif
-		break;
-	}
-
-	/* Read in NVRAM data */ 
-	init_prep_nvram();
-
-	/* if no bootargs, look in NVRAM */
-	if ( cmd_line[0] == '\0' ) {
-		char *bootargs;
-		 bootargs = prep_nvram_get_var("bootargs");
-		 if (bootargs != NULL) {
-			 strcpy(cmd_line, bootargs);
-			 /* again.. */
-			 strcpy(saved_command_line, cmd_line);
-		}
-	}
-
-#ifdef CONFIG_SOUND_CS4232
-	/*
-	 * setup proper values for the cs4232 driver so we don't have
-	 * to recompile for the motorola or ibm workstations sound systems.
-	 * This is a really nasty hack, but unless we change the driver
-	 * it's the only way to support both addrs from one binary.
-	 * -- Cort
-	 */
-	if ( _machine == _MACH_prep )
-	{
-		extern struct card_info snd_installed_cards[];
-		struct card_info *snd_ptr;
-
-		for ( snd_ptr = snd_installed_cards; 
-			snd_ptr < &snd_installed_cards[num_sound_cards];
-			snd_ptr++ )
-		{
-			if ( snd_ptr->card_type == SNDCARD_CS4232 )
-			{
-				if ( _prep_type == _PREP_Motorola )
-				{
-					snd_ptr->config.io_base = 0x830;
-					snd_ptr->config.irq = 10;
-					snd_ptr->config.dma = ppc_cs4232_dma = 6;
-					snd_ptr->config.dma2 = ppc_cs4232_dma2 = 7;
-				}
-				if ( _prep_type == _PREP_IBM )
-				{
-					snd_ptr->config.io_base = 0x530;
-					snd_ptr->config.irq = 5;
-					snd_ptr->config.dma = ppc_cs4232_dma = 1;
-					/* this is wrong - but leave it for now */
-					snd_ptr->config.dma2 = ppc_cs4232_dma2 = 7;
-				}
-			}
-		}
-	}
-#endif /* CONFIG_SOUND_CS4232 */	
-
-	/*print_residual_device_info();*/
-
-	switch (_prep_type) {
-	case _PREP_Motorola:
-		raven_init();
-		break;
-	case _PREP_IBM:
-		ibm_prep_init();
-		break;
-	}
-
-#ifdef CONFIG_VGA_CONSOLE
-	/* remap the VGA memory */
-	vgacon_remap_base = 0xf0000000;
-	/*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
-	conswitchp = &vga_con;
-#elif defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
-#endif
-}
-
-/*
- * Determine the decrementer frequency from the residual data
- * This allows for a faster boot as we do not need to calibrate the
- * decrementer against another clock. This is important for embedded systems.
- */
-static int __init
-prep_res_calibrate_decr(void)
-{
-#ifdef CONFIG_PREP_RESIDUAL
-	unsigned long freq, divisor = 4;
-
-	if ( res->VitalProductData.ProcessorBusHz ) {
-		freq = res->VitalProductData.ProcessorBusHz;
-		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-				(freq/divisor)/1000000,
-				(freq/divisor)%1000000);
-		tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
-		tb_ticks_per_jiffy = freq / HZ / divisor;
-		return 0;
-	} else
-#endif	
-		return 1;
-}
-
-/*
- * Uses the on-board timer to calibrate the on-chip decrementer register
- * for prep systems.  On the pmac the OF tells us what the frequency is
- * but on prep we have to figure it out.
- * -- Cort
- */
-/* Done with 3 interrupts: the first one primes the cache and the
- * 2 following ones measure the interval. The precision of the method
- * is still doubtful due to the short interval sampled.
- */
-static volatile int calibrate_steps __initdata = 3;
-static unsigned tbstamp __initdata = 0;
-
-static void __init
-prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs)
-{
-	unsigned long t, freq;
-	int step=--calibrate_steps;
-
-	t = get_tbl();
-	if (step > 0) {
-		tbstamp = t;
-	} else {
-		freq = (t - tbstamp)*HZ;
-		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-			 freq/1000000, freq%1000000);
-		tb_ticks_per_jiffy = freq / HZ;
-		tb_to_us = mulhwu_scale_factor(freq, 1000000);
-	}
-}
-
-static void __init
-prep_calibrate_decr(void)
-{
-	int res;
-
-	/* Try and get this from the residual data. */
-	res = prep_res_calibrate_decr();
-
-	/* If we didn't get it from the residual data, try this. */
-	if ( res ) {
-		unsigned long flags;
-
-		save_flags(flags);
-
-#define TIMER0_COUNT 0x40
-#define TIMER_CONTROL 0x43
-		/* set timer to periodic mode */
-		outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
-		/* set the clock to ~100 Hz */
-		outb_p(LATCH & 0xff , TIMER0_COUNT);	/* LSB */
-		outb(LATCH >> 8 , TIMER0_COUNT);	/* MSB */
-
-		if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
-			panic("Could not allocate timer IRQ!");
-		__sti();
-		/* wait for calibrate */
-		while ( calibrate_steps )
-			;
-		restore_flags(flags);
-		free_irq( 0, NULL);
-	}
-}
-
-static long __init
-mk48t59_init(void) {
-	unsigned char tmp;
-
-	tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
-	if (tmp & MK48T59_RTC_CB_STOP) {
-		printk("Warning: RTC was stopped, date will be wrong.\n");
-		ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, 
-					 tmp & ~MK48T59_RTC_CB_STOP);
-		/* Low frequency crystal oscillators may take a very long
-		 * time to startup and stabilize. For now just ignore the
-		 * the issue, but attempting to calibrate the decrementer
-		 * from the RTC just after this wakeup is likely to be very 
-		 * inaccurate. Firmware should not allow to load
-		 * the OS with the clock stopped anyway...
-		 */
-	}
-	/* Ensure that the clock registers are updated */
-	tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
-	tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE);
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp);
-	return 0;
-}
-
-/* We use the NVRAM RTC to time a second to calibrate the decrementer,
- * the RTC registers have just been set up in the right state by the
- * preceding routine.
- */
-static void __init
-mk48t59_calibrate_decr(void)
-{
-	unsigned long freq;
-	unsigned long t1;
-	unsigned char save_control;
-	long i;
-	unsigned char sec;
- 
-		
-	/* Make sure the time is not stopped. */
-	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
-	
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
-			(save_control & (~MK48T59_RTC_CB_STOP)));
-
-	/* Now make sure the read bit is off so the value will change. */
-	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
-	save_control &= ~MK48T59_RTC_CA_READ;
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-
-
-	/* Read the seconds value to see when it changes. */
-	sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
-	/* Actually this is bad for precision, we should have a loop in
-	 * which we only read the seconds counter. nvram_read_val writes
-	 * the address bytes on every call and this takes a lot of time.
-	 * Perhaps an nvram_wait_change method returning a time
-	 * stamp with a loop count as parameter would be the  solution.
-	 */
-	for (i = 0 ; i < 1000000 ; i++)	{ /* may take up to 1 second... */
-		t1 = get_tbl();
-		if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
-			break;
-		}
-	}
-
-	sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
-	for (i = 0 ; i < 1000000 ; i++)	{ /* Should take up 1 second... */
-		freq = get_tbl()-t1;
-		if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec)
-			break;
-	}
-
-	printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
-		 freq/1000000, freq%1000000);
-	tb_ticks_per_jiffy = freq / HZ;
-	tb_to_us = mulhwu_scale_factor(freq, 1000000);
-}
-
-static void __prep
-prep_restart(char *cmd)
-{
-	unsigned long i = 10000;
-
-	__cli();
-
-	/* set exception prefix high - to the prom */
-	_nmask_and_or_msr(0, MSR_IP);
-
-	/* make sure bit 0 (reset) is a 0 */
-	outb( inb(0x92) & ~1L , 0x92 );
-	/* signal a reset to system control port A - soft reset */
-	outb( inb(0x92) | 1 , 0x92 );
-
-	while ( i != 0 ) i++;
-	panic("restart failed\n");
-}
-
-static void __prep
-prep_halt(void)
-{
-	unsigned long flags;
-	__cli();
-	/* set exception prefix high - to the prom */
-	save_flags( flags );
-	restore_flags( flags|MSR_IP );
-
-	/* make sure bit 0 (reset) is a 0 */
-	outb( inb(0x92) & ~1L , 0x92 );
-	/* signal a reset to system control port A - soft reset */
-	outb( inb(0x92) | 1 , 0x92 );
-
-	while ( 1 ) ;
-	/*
-	 * Not reached
-	 */
-}
-
-/*
- * On IBM PReP's, power management is handled by a Signetics 87c750 behind the
- * Utah component on the ISA bus. To access the 750 you must write a series of
- * nibbles to port 0x82a (decoded by the Utah). This is described somewhat in
- * the IBM Carolina Technical Specification.
- * -Hollis
- */
-static void __prep
-utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
-{
-	/*
-	 * byte1: 0 0 0 1 0  d  a5 a4
-	 * byte2: 0 0 0 1 a3 a2 a1 a0
-	 *
-	 * d = the bit's value, enabled or disabled
-	 * (a5 a4 a3) = the byte number, minus 20
-	 * (a2 a1 a0) = the bit number
-	 *
-	 * example: set the 5th bit of byte 21 (21.5)
-	 *     a5 a4 a3 = 001 (byte 1)
-	 *     a2 a1 a0 = 101 (bit 5)
-	 *
-	 *     byte1 = 0001 0100 (0x14)
-	 *     byte2 = 0001 1101 (0x1d)
-	 */
-	unsigned char byte1=0x10, byte2=0x10;
-	const unsigned int pm_reg_1=0x82a; /* ISA address */
-
-	/* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
-	bytenum -= 20;
-
-	byte1 |= (!!value) << 2;		/* set d */
-	byte1 |= (bytenum >> 1) & 0x3;	/* set a5, a4 */
-
-	byte2 |= (bytenum & 0x1) << 3;	/* set a3 */
-	byte2 |= bitnum & 0x7;			/* set a2, a1, a0 */
-
-	outb(byte1, pm_reg_1);		/* first nibble */
-	mb();
-	udelay(100);				/* important: let controller recover */
-
-	outb(byte2, pm_reg_1);		/* second nibble */
-	mb();
-	udelay(100);				/* important: let controller recover */
-}
-
-static void __prep
-prep_power_off(void)
-{
-	if ( _prep_type == _PREP_IBM) {
-		/* tested on:
-		 * 		Carolina's: 7248-43P, 6070 (PowerSeries 850)
-		 * should work on:
-		 * 		Carolina: 6050 (PowerSeries 830)
-		 * 		7043-140 (Tiger 1)
-		 */
-		unsigned long flags;
-		__cli();
-		/* set exception prefix high - to the prom */
-		save_flags( flags );
-		restore_flags( flags|MSR_IP );
-
-		utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
-
-		while ( 1 ) ;
-		/* not reached */
-	} else {
-		prep_halt();
-	}
-}
-
-static unsigned int __prep
-prep_irq_cannonicalize(u_int irq)
-{
-	if (irq == 2)
-	{
-		return 9;
-	}
-	else
-	{
-		return irq;
-	}
-}
-
-static int __prep
-prep_get_irq(struct pt_regs *regs)
-{
-	return i8259_irq();
-}		
-
-static void __init
-prep_init_IRQ(void)
-{
-	int i;
-
-	if (OpenPIC_Addr != NULL)
-		openpic_init(1, NUM_8259_INTERRUPTS, 0, -1);
-	for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
-		irq_desc[i].handler = &i8259_pic;
-	i8259_init(0xbffffff0); /* PCI interrupt ack address for MPC105 and 106 */
-}
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-/*
- * IDE stuff.
- */
-static int __prep
-prep_ide_default_irq(ide_ioreg_t base)
-{
-	switch (base) {
-		case 0x1f0: return 13;
-		case 0x170: return 13;
-		case 0x1e8: return 11;
-		case 0x168: return 10;
-		case 0xfff0: return 14;		/* MCP(N)750 ide0 */
-		case 0xffe0: return 15;		/* MCP(N)750 ide1 */
-		default: return 0;
-	}
-}
-
-static ide_ioreg_t __prep
-prep_ide_default_io_base(int index)
-{
-	switch (index) {
-		case 0: return 0x1f0;
-		case 1: return 0x170;
-		case 2: return 0x1e8;
-		case 3: return 0x168;
-		default:
-			return 0;
-	}
-}
-
-static int __prep
-prep_ide_check_region(ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static void __prep
-prep_ide_request_region(ide_ioreg_t from,
-			unsigned int extent,
-			const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static void __prep
-prep_ide_release_region(ide_ioreg_t from,
-			unsigned int extent)
-{
-	release_region(from, extent);
-}
-
-static void __init
-prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
-{
-	ide_ioreg_t reg = data_port;
-	int i;
-
-	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
-		hw->io_ports[i] = reg;
-		reg += 1;
-	}
-	if (ctrl_port) {
-		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
-	} else {
-		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
-	}
-	if (irq != NULL)
-		*irq = 0;
-}
-#endif
-
-#ifdef CONFIG_SMP
-/* PReP (MTX) support */
-static int __init
-smp_prep_probe(void)
-{
-	extern int mot_multi;
-
-	if (mot_multi) {
-		openpic_request_IPIs();
-		smp_hw_index[1] = 1;
-		return 2;
-	}
-
-	return 1;
-}
-
-static void __init
-smp_prep_kick_cpu(int nr)
-{
-	*(unsigned long *)KERNELBASE = nr;
-	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
-	printk("CPU1 reset, waiting\n");
-}
-
-static void __init
-smp_prep_setup_cpu(int cpu_nr)
-{
-	if (OpenPIC_Addr)
-		do_openpic_setup_cpu();
-}
-
-static struct smp_ops_t prep_smp_ops __prepdata = {
-	smp_openpic_message_pass,
-	smp_prep_probe,
-	smp_prep_kick_cpu,
-	smp_prep_setup_cpu,
-};
-#endif /* CONFIG_SMP */
-
-/*
- * This finds the amount of physical ram and does necessary
- * setup for prep.  This is pretty architecture specific so
- * this will likely stay separate from the pmac.
- * -- Cort
- */
-static unsigned long __init
-prep_find_end_of_memory(void)
-{
-	unsigned long total = 0;
-	extern unsigned int boot_mem_size;
-
-#ifdef CONFIG_PREP_RESIDUAL	
-	total = res->TotalMemory;
-#endif	
-
-	if (total == 0 && boot_mem_size != 0)
-		total = boot_mem_size;
-	else if (total == 0) {
-		/*
-		 * I need a way to probe the amount of memory if the residual
-		 * data doesn't contain it. -- Cort
-		 */
-		total = 0x02000000;
-		printk(KERN_INFO "Ramsize from residual data was 0"
-			 " -- defaulting to %ldM\n", total>>20);
-	}
-
-	return (total);
-}
-
-/*
- * Setup the bat mappings we're going to load that cover
- * the io areas.  RAM was mapped by mapin_ram().
- * -- Cort
- */
-static void __init
-prep_map_io(void)
-{
-	io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO);
-	io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO);
-}
-
-static void __init
-prep_init2(void)
-{
-#ifdef CONFIG_NVRAM
-	request_region(PREP_NVRAM_AS0, 0x8, "nvram");
-#endif
-	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");
-}
-
-void __init
-prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
-		unsigned long r6, unsigned long r7)
-{
-#ifdef CONFIG_PREP_RESIDUAL	
-	/* make a copy of residual data */
-	if ( r3 ) {
-		memcpy((void *)res,(void *)(r3+KERNELBASE),
-			 sizeof(RESIDUAL));
-	}
-#endif
-
-	isa_io_base = PREP_ISA_IO_BASE;
-	isa_mem_base = PREP_ISA_MEM_BASE;
-	pci_dram_offset = PREP_PCI_DRAM_OFFSET;
-	ISA_DMA_THRESHOLD = 0x00ffffff;
-	DMA_MODE_READ = 0x44;
-	DMA_MODE_WRITE = 0x48;
-
-	/* figure out what kind of prep workstation we are */
-#ifdef CONFIG_PREP_RESIDUAL	
-	if ( res->ResidualLength != 0 )
-	{
-		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
-			_prep_type = _PREP_IBM;
-		else
-			_prep_type = _PREP_Motorola;
-	}
-	else /* assume motorola if no residual (netboot?) */
-#endif
-	{
-		_prep_type = _PREP_Motorola;
-	}
-
-	ppc_md.setup_arch     = prep_setup_arch;
-	ppc_md.show_percpuinfo = prep_show_percpuinfo;
-	ppc_md.show_cpuinfo   = prep_show_cpuinfo;
-	ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
-	ppc_md.init_IRQ       = prep_init_IRQ;
-	/* this gets changed later on if we have an OpenPIC -- Cort */
-	ppc_md.get_irq        = prep_get_irq;
-	ppc_md.init           = prep_init2;
-
-	ppc_md.restart        = prep_restart;
-	ppc_md.power_off      = prep_power_off;
-	ppc_md.halt           = prep_halt;
-
-	ppc_md.nvram_read_val = prep_nvram_read_val;
-	ppc_md.nvram_write_val = prep_nvram_write_val;
-
-	ppc_md.time_init      = NULL;
-	if (_prep_type == _PREP_IBM) {
-		ppc_md.set_rtc_time   = mc146818_set_rtc_time;
-		ppc_md.get_rtc_time   = mc146818_get_rtc_time;
-		ppc_md.calibrate_decr = prep_calibrate_decr;
-	} else {
-		ppc_md.set_rtc_time   = mk48t59_set_rtc_time;
-		ppc_md.get_rtc_time   = mk48t59_get_rtc_time;
-		ppc_md.calibrate_decr = mk48t59_calibrate_decr;
-		ppc_md.time_init      = mk48t59_init;
-	}
-
-	ppc_md.find_end_of_memory = prep_find_end_of_memory;
-	ppc_md.setup_io_mappings = prep_map_io;
-
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
-	ppc_ide_md.default_irq = prep_ide_default_irq;
-	ppc_ide_md.default_io_base = prep_ide_default_io_base;
-	ppc_ide_md.ide_check_region = prep_ide_check_region;
-	ppc_ide_md.ide_request_region = prep_ide_request_region;
-	ppc_ide_md.ide_release_region = prep_ide_release_region;
-	ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
-#endif
-
-#ifdef CONFIG_VT
-	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.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
-	SYSRQ_KEY = 0x54;
-#endif
-#endif
-
-#ifdef CONFIG_SMP
-	ppc_md.smp_ops		 = &prep_smp_ops;
-#endif /* CONFIG_SMP */
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/prep_time.c linux/arch/ppc/kernel/prep_time.c
--- linux.orig/arch/ppc/kernel/prep_time.c	2001-09-08 19:38:42.000000000 +0000
+++ linux/arch/ppc/kernel/prep_time.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,228 +0,0 @@
-/*
- * BK Id: SCCS/s.prep_time.c 1.10 09/08/01 15:47:42 paulus
- */
-/*
- *  linux/arch/i386/kernel/time.c
- *
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * Adapted for PowerPC (PreP) by Gary Thomas
- * Modified by Cort Dougan (cort@cs.nmt.edu)
- *  copied and modified from intel version
- *
- */
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-
-#include <asm/sections.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/processor.h>
-#include <asm/machdep.h>
-#include <asm/prep_nvram.h>
-#include <asm/mk48t59.h>
-
-#include <asm/time.h>
-
-extern spinlock_t rtc_lock;
-
-/*
- * The motorola uses the m48t18 rtc (includes DS1643) whose registers
- * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
- * rtc (ds1386) which has regs at addr 0-d).  The intel gets
- * past this because the bios emulates the mc146818.
- *
- * Why in the world did they have to use different clocks?
- *
- * Right now things are hacked to check which machine we're on then
- * use the appropriate macro.  This is very very ugly and I should
- * probably have a function that checks which machine we're on then
- * does things correctly transparently or a function pointer which
- * is setup at boot time to use the correct addresses.
- * -- Cort
- */
-
-/*
- * Set the hardware clock. -- Cort
- */
-__prep
-int mc146818_set_rtc_time(unsigned long nowtime)
-{
-	unsigned char save_control, save_freq_select;
-	struct rtc_time tm;
-
-	spin_lock(&rtc_lock);
-	to_tm(nowtime, &tm);
-
-	/* tell the clock it's being set */
-	save_control = CMOS_READ(RTC_CONTROL);
-	
-	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
-	
-	/* stop and reset prescaler */
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-	
-	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
-	
-        tm.tm_year = (tm.tm_year - 1900) % 100;
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-		BIN_TO_BCD(tm.tm_sec);
-		BIN_TO_BCD(tm.tm_min);
-		BIN_TO_BCD(tm.tm_hour);
-		BIN_TO_BCD(tm.tm_mon);
-		BIN_TO_BCD(tm.tm_mday);
-		BIN_TO_BCD(tm.tm_year);
-	}
-	CMOS_WRITE(tm.tm_sec,  RTC_SECONDS);
-	CMOS_WRITE(tm.tm_min,  RTC_MINUTES);
-	CMOS_WRITE(tm.tm_hour, RTC_HOURS);
-	CMOS_WRITE(tm.tm_mon,  RTC_MONTH);
-	CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
-	CMOS_WRITE(tm.tm_year, RTC_YEAR);
-	
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	CMOS_WRITE(save_control,     RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-	spin_unlock(&rtc_lock);
-
-	return 0;
-}
-
-__prep
-unsigned long mc146818_get_rtc_time(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-	int uip, i;
-
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-
-	/* Since the UIP flag is set for about 2.2 ms and the clock
-	 * is typically written with a precision of 1 jiffy, trying
-	 * to obtain a precision better than a few milliseconds is 
-	 * an illusion. Only consistency is interesting, this also
-	 * allows to use the routine for /dev/rtc without a potential
-	 * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
-	 */
-
-	for ( i = 0; i<1000000; i++) {
-		uip = CMOS_READ(RTC_FREQ_SELECT);
-		sec = CMOS_READ(RTC_SECONDS);
-		min = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
-		uip |= CMOS_READ(RTC_FREQ_SELECT);
-		if ((uip & RTC_UIP)==0) break;
-	}
-
-	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
-	    || RTC_ALWAYS_BCD)
-	{
-		BCD_TO_BIN(sec);
-		BCD_TO_BIN(min);
-		BCD_TO_BIN(hour);
-		BCD_TO_BIN(day);
-		BCD_TO_BIN(mon);
-		BCD_TO_BIN(year);
-	}
-	if ((year += 1900) < 1970)
-		year += 100;
-	return mktime(year, mon, day, hour, min, sec);
-}
-
-__prep
-int mk48t59_set_rtc_time(unsigned long nowtime)
-{
-	unsigned char save_control;
-	struct rtc_time tm;
-
-	spin_lock(&rtc_lock);
-	to_tm(nowtime, &tm);
-
-	/* tell the clock it's being written */
-	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
-	
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
-			     (save_control | MK48T59_RTC_CA_WRITE));
-
-        tm.tm_year = (tm.tm_year - 1900) % 100;
-	BIN_TO_BCD(tm.tm_sec);
-	BIN_TO_BCD(tm.tm_min);
-	BIN_TO_BCD(tm.tm_hour);
-	BIN_TO_BCD(tm.tm_mon);
-	BIN_TO_BCD(tm.tm_mday);
-	BIN_TO_BCD(tm.tm_year);
-
-	ppc_md.nvram_write_val(MK48T59_RTC_SECONDS,      tm.tm_sec);
-	ppc_md.nvram_write_val(MK48T59_RTC_MINUTES,      tm.tm_min);
-	ppc_md.nvram_write_val(MK48T59_RTC_HOURS,        tm.tm_hour);
-	ppc_md.nvram_write_val(MK48T59_RTC_MONTH,        tm.tm_mon);
-	ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
-	ppc_md.nvram_write_val(MK48T59_RTC_YEAR,         tm.tm_year);
-	
-	/* Turn off the write bit. */
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-	spin_unlock(&rtc_lock);
-
-	return 0;
-}
-
-__prep
-unsigned long mk48t59_get_rtc_time(void)
-{
-	unsigned char save_control;
-	unsigned int year, mon, day, hour, min, sec;
-
-	/* Simple: freeze the clock, read it and allow updates again */
-	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
-	save_control &= ~MK48T59_RTC_CA_READ;
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-
-	/* Set the register to read the value. */
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
-			     (save_control | MK48T59_RTC_CA_READ));
-
-	sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
-	min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
-	hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
-	day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
-	mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
-	year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
-
-	/* Let the time values change again. */
-	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
-
-	BCD_TO_BIN(sec);
-	BCD_TO_BIN(min);
-	BCD_TO_BIN(hour);
-	BCD_TO_BIN(day);
-	BCD_TO_BIN(mon);
-	BCD_TO_BIN(year);
-
-	year = year + 1900;
-	if (year < 1970) {
-		year += 100;
-	}
-
-	return mktime(year, mon, day, hour, min, sec);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/proc_rtas.c linux/arch/ppc/kernel/proc_rtas.c
--- linux.orig/arch/ppc/kernel/proc_rtas.c	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/proc_rtas.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,787 +0,0 @@
-/*
- * BK Id: SCCS/s.proc_rtas.c 1.5 05/17/01 18:14:22 cort
- */
-/*
- *   arch/ppc/kernel/proc_rtas.c
- *   Copyright (C) 2000 Tilmann Bitterberg
- *   (tilmann@bitterberg.de)
- *
- *   RTAS (Runtime Abstraction Services) stuff
- *   Intention is to provide a clean user interface
- *   to use the RTAS.
- *
- *   TODO:
- *   Split off a header file and maybe move it to a different
- *   location. Write Documentation on what the /proc/rtas/ entries
- *   actually do.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/ctype.h>
-#include <linux/time.h>
-#include <linux/string.h>
-
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/prom.h>
-#include <asm/machdep.h> /* for ppc_md */
-#include <asm/time.h>
-
-/* Token for Sensors */
-#define KEY_SWITCH		0x0001
-#define ENCLOSURE_SWITCH	0x0002
-#define THERMAL_SENSOR		0x0003
-#define LID_STATUS		0x0004
-#define POWER_SOURCE		0x0005
-#define BATTERY_VOLTAGE		0x0006
-#define BATTERY_REMAINING	0x0007
-#define BATTERY_PERCENTAGE	0x0008
-#define EPOW_SENSOR		0x0009
-#define BATTERY_CYCLESTATE	0x000a
-#define BATTERY_CHARGING	0x000b
-
-/* IBM specific sensors */
-#define IBM_SURVEILLANCE	0x2328 /* 9000 */
-#define IBM_FANRPM		0x2329 /* 9001 */
-#define IBM_VOLTAGE		0x232a /* 9002 */
-#define IBM_DRCONNECTOR		0x232b /* 9003 */
-#define IBM_POWERSUPPLY		0x232c /* 9004 */
-#define IBM_INTQUEUE		0x232d /* 9005 */
-
-/* Status return values */
-#define SENSOR_CRITICAL_HIGH	13
-#define SENSOR_WARNING_HIGH	12
-#define SENSOR_NORMAL		11
-#define SENSOR_WARNING_LOW	10
-#define SENSOR_CRITICAL_LOW	 9
-#define SENSOR_SUCCESS		 0
-#define SENSOR_HW_ERROR		-1
-#define SENSOR_BUSY		-2
-#define SENSOR_NOT_EXIST	-3
-#define SENSOR_DR_ENTITY	-9000
-
-/* Location Codes */
-#define LOC_SCSI_DEV_ADDR	'A'
-#define LOC_SCSI_DEV_LOC	'B'
-#define LOC_CPU			'C'
-#define LOC_DISKETTE		'D'
-#define LOC_ETHERNET		'E'
-#define LOC_FAN			'F'
-#define LOC_GRAPHICS		'G'
-/* reserved / not used		'H' */
-#define LOC_IO_ADAPTER		'I'
-/* reserved / not used		'J' */
-#define LOC_KEYBOARD		'K'
-#define LOC_LCD			'L'
-#define LOC_MEMORY		'M'
-#define LOC_NV_MEMORY		'N'
-#define LOC_MOUSE		'O'
-#define LOC_PLANAR		'P'
-#define LOC_OTHER_IO		'Q'
-#define LOC_PARALLEL		'R'
-#define LOC_SERIAL		'S'
-#define LOC_DEAD_RING		'T'
-#define LOC_RACKMOUNTED		'U' /* for _u_nit is rack mounted */
-#define LOC_VOLTAGE		'V'
-#define LOC_SWITCH_ADAPTER	'W'
-#define LOC_OTHER		'X'
-#define LOC_FIRMWARE		'Y'
-#define LOC_SCSI		'Z'
-
-/* Tokens for indicators */
-#define TONE_FREQUENCY		0x0001 /* 0 - 1000 (HZ)*/
-#define TONE_VOLUME		0x0002 /* 0 - 100 (%) */
-#define SYSTEM_POWER_STATE	0x0003 
-#define WARNING_LIGHT		0x0004
-#define DISK_ACTIVITY_LIGHT	0x0005
-#define HEX_DISPLAY_UNIT	0x0006
-#define BATTERY_WARNING_TIME	0x0007
-#define CONDITION_CYCLE_REQUEST	0x0008
-#define SURVEILLANCE_INDICATOR	0x2328 /* 9000 */
-#define DR_ACTION		0x2329 /* 9001 */
-#define DR_INDICATOR		0x232a /* 9002 */
-/* 9003 - 9004: Vendor specific */
-#define GLOBAL_INTERRUPT_QUEUE	0x232d /* 9005 */
-/* 9006 - 9999: Vendor specific */
-
-/* other */
-#define MAX_SENSORS		 17  /* I only know of 17 sensors */    
-#define MAX_LINELENGTH          256
-#define SENSOR_PREFIX		"ibm,sensor-"
-#define cel_to_fahr(x)		((x*9/5)+32)
-
-
-/* Globals */
-static struct proc_dir_entry *proc_rtas;
-static struct rtas_sensors sensors;
-static struct device_node *rtas;
-static unsigned long power_on_time = 0; /* Save the time the user set */
-static char progress_led[MAX_LINELENGTH];
-
-static unsigned long rtas_tone_frequency = 1000;
-static unsigned long rtas_tone_volume = 0;
-
-/* ****************STRUCTS******************************************* */
-struct individual_sensor {
-	unsigned int token;
-	unsigned int quant;
-};
-
-struct rtas_sensors {
-        struct individual_sensor sensor[MAX_SENSORS];
-	unsigned int quant;
-};
-
-/* ****************************************************************** */
-/* Declarations */
-static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
-		int count, int *eof, void *data);
-static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, 
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, 
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos);
-
-static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos);
-static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos);
-
-struct file_operations ppc_rtas_poweron_operations = {
-	read:		ppc_rtas_poweron_read,
-	write:		ppc_rtas_poweron_write
-};
-struct file_operations ppc_rtas_progress_operations = {
-	read:		ppc_rtas_progress_read,
-	write:		ppc_rtas_progress_write
-};
-
-struct file_operations ppc_rtas_clock_operations = {
-	read:		ppc_rtas_clock_read,
-	write:		ppc_rtas_clock_write
-};
-
-struct file_operations ppc_rtas_tone_freq_operations = {
-	read:		ppc_rtas_tone_freq_read,
-	write:		ppc_rtas_tone_freq_write
-};
-struct file_operations ppc_rtas_tone_volume_operations = {
-	read:		ppc_rtas_tone_volume_read,
-	write:		ppc_rtas_tone_volume_write
-};
-
-int ppc_rtas_find_all_sensors (void);
-int ppc_rtas_process_sensor(struct individual_sensor s, int state, 
-		int error, char * buf);
-char * ppc_rtas_process_error(int error);
-int get_location_code(struct individual_sensor s, char * buf);
-int check_location_string (char *c, char * buf);
-int check_location (char *c, int idx, char * buf);
-
-/* ****************************************************************** */
-/* MAIN                                                               */
-/* ****************************************************************** */
-void proc_rtas_init(void)
-{
-	struct proc_dir_entry *entry;
-
-	rtas = find_devices("rtas");
-	if ((rtas == 0) || (_machine != _MACH_chrp)) {
-		return;
-	}
-	
-	proc_rtas = proc_mkdir("rtas", 0);
-	if (proc_rtas == 0)
-		return;
-
-	/* /proc/rtas entries */
-
-	entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas);
-	if (entry) entry->proc_fops = &ppc_rtas_progress_operations;
-
-	entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_clock_operations;
-
-	entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_poweron_operations;
-
-	create_proc_read_entry("sensors", S_IRUGO, proc_rtas, 
-			ppc_rtas_sensor_read, NULL);
-	
-	entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations;
-
-	entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); 
-	if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
-}
-
-/* ****************************************************************** */
-/* POWER-ON-TIME                                                      */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos)
-{
-	struct rtc_time tm;
-	unsigned long nowtime;
-	char *dest;
-	int error;
-
-	nowtime = simple_strtoul(buf, &dest, 10);
-	if (*dest != '\0' && *dest != '\n') {
-		printk("ppc_rtas_poweron_write: Invalid time\n");
-		return count;
-	}
-	power_on_time = nowtime; /* save the time */
-
-	to_tm(nowtime, &tm);
-
-	error = call_rtas("set-time-for-power-on", 7, 1, NULL, 
-			tm.tm_year, tm.tm_mon, tm.tm_mday, 
-			tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
-	if (error != 0)
-		printk(KERN_WARNING "error: setting poweron time returned: %s\n", 
-				ppc_rtas_process_error(error));
-	return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos)
-{
-	int n;
-	if (power_on_time == 0)
-		n = sprintf(buf, "Power on time not set\n");
-	else
-		n = sprintf(buf, "%lu\n", power_on_time);
-
-	if (*ppos >= strlen(buf))
-		return 0;
-	if (n > strlen(buf) - *ppos)
-		n = strlen(buf) - *ppos;
-	if (n > count)
-		n = count;
-	*ppos += n;
-	return n;
-}
-
-/* ****************************************************************** */
-/* PROGRESS                                                           */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos)
-{
-	unsigned long hex;
-
-	strcpy(progress_led, buf); /* save the string */
-	/* Lets see if the user passed hexdigits */
-	hex = simple_strtoul(buf, NULL, 10);
-	
-	ppc_md.progress ((char *)buf, hex);
-	return count;
-
-	/* clear the line */ /* ppc_md.progress("                   ", 0xffff);*/
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos)
-{
-	int n = 0;
-	if (progress_led != NULL)
-		n = sprintf (buf, "%s\n", progress_led);
-	if (*ppos >= strlen(buf))
-		return 0;
-	if (n > strlen(buf) - *ppos)
-		n = strlen(buf) - *ppos;
-	if (n > count)
-		n = count;
-	*ppos += n;
-	return n;
-}
-
-/* ****************************************************************** */
-/* CLOCK                                                              */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, 
-		size_t count, loff_t *ppos)
-{
-	struct rtc_time tm;
-	unsigned long nowtime;
-	char *dest;
-	int error;
-
-	nowtime = simple_strtoul(buf, &dest, 10);
-	if (*dest != '\0' && *dest != '\n') {
-		printk("ppc_rtas_clock_write: Invalid time\n");
-		return count;
-	}
-
-	to_tm(nowtime, &tm);
-	error = call_rtas("set-time-of-day", 7, 1, NULL, 
-			tm.tm_year, tm.tm_mon, tm.tm_mday, 
-			tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
-	if (error != 0)
-		printk(KERN_WARNING "error: setting the clock returned: %s\n", 
-				ppc_rtas_process_error(error));
-	return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, 
-		size_t count, loff_t *ppos)
-{
-	unsigned int year, mon, day, hour, min, sec;
-	unsigned long *ret = kmalloc(4*8, GFP_KERNEL);
-	int n, error;
-
-	error = call_rtas("get-time-of-day", 0, 8, ret);
-	
-	year = ret[0]; mon  = ret[1]; day  = ret[2];
-	hour = ret[3]; min  = ret[4]; sec  = ret[5];
-
-	if (error != 0){
-		printk(KERN_WARNING "error: reading the clock returned: %s\n", 
-				ppc_rtas_process_error(error));
-		n = sprintf (buf, "0");
-	} else { 
-		n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec));
-	}
-	kfree(ret);
-
-	if (*ppos >= strlen(buf))
-		return 0;
-	if (n > strlen(buf) - *ppos)
-		n = strlen(buf) - *ppos;
-	if (n > count)
-		n = count;
-	*ppos += n;
-	return n;
-}
-
-/* ****************************************************************** */
-/* SENSOR STUFF                                                       */
-/* ****************************************************************** */
-static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
-		int count, int *eof, void *data)
-{
-	int i,j,n;
-	unsigned long ret;
-	int state, error;
-	char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */
-
-	if (count < 0)
-		return -EINVAL;
-
-	n  = sprintf ( buffer  , "RTAS (RunTime Abstraction Services) Sensor Information\n");
-	n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n");
-	n += sprintf ( buffer+n, "********************************************************\n");
-
-	if (ppc_rtas_find_all_sensors() != 0) {
-		n += sprintf ( buffer+n, "\nNo sensors are available\n");
-		goto return_string;
-	}
-
-	for (i=0; i<sensors.quant; i++) {
-		j = sensors.sensor[i].quant;
-		/* A sensor may have multiple instances */
-		while (j >= 0) {
-			error =	call_rtas("get-sensor-state", 2, 2, &ret, 
-				  sensors.sensor[i].token, sensors.sensor[i].quant-j);
-			state = (int) ret;
-			n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n );
-			n += sprintf (buffer+n, "\n");
-			j--;
-		} /* while */
-	} /* for */
-
-return_string:
-	if (off >= strlen(buffer)) {
-		*eof = 1;
-		return 0;
-	}
-	if (n > strlen(buffer) - off)
-		n = strlen(buffer) - off;
-	if (n > count)
-		n = count;
-	else
-		*eof = 1;
-	memcpy(buf, buffer + off, n);
-	*start = buf;
-	return n;
-}
-
-/* ****************************************************************** */
-
-int ppc_rtas_find_all_sensors (void)
-{
-	unsigned long *utmp;
-	int len, i, j;
-
-	utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len);
-	if (utmp == NULL) {
-		printk (KERN_ERR "error: could not get rtas-sensors\n");
-		return 1;
-	}
-
-	sensors.quant = len / 8;      /* int + int */
-
-	for (i=0, j=0; j<sensors.quant; i+=2, j++) {
-		sensors.sensor[j].token = utmp[i];
-		sensors.sensor[j].quant = utmp[i+1];
-	}
-	return 0;
-}
-
-/* ****************************************************************** */
-/*
- * Builds a string of what rtas returned
- */
-char * ppc_rtas_process_error(int error)
-{
-	switch (error) {
-		case SENSOR_CRITICAL_HIGH:
-			return "(critical high)";
-		case SENSOR_WARNING_HIGH:
-			return "(warning high)";
-		case SENSOR_NORMAL:
-			return "(normal)";
-		case SENSOR_WARNING_LOW:
-			return "(warning low)";
-		case SENSOR_CRITICAL_LOW:
-			return "(critical low)";
-		case SENSOR_SUCCESS:
-			return "(read ok)";
-		case SENSOR_HW_ERROR:
-			return "(hardware error)";
-		case SENSOR_BUSY:
-			return "(busy)";
-		case SENSOR_NOT_EXIST:
-			return "(non existant)";
-		case SENSOR_DR_ENTITY:
-			return "(dr entity removed)";
-		default:
-			return "(UNKNOWN)";
-	}
-}
-
-/* ****************************************************************** */
-/*
- * Builds a string out of what the sensor said
- */
-
-int ppc_rtas_process_sensor(struct individual_sensor s, int state, 
-		int error, char * buf) 
-{
-	/* Defined return vales */
-	const char * key_switch[]        = { "Off\t", "Normal\t", "Secure\t", "Mainenance" };
-	const char * enclosure_switch[]  = { "Closed", "Open" };
-	const char * lid_status[]        = { " ", "Open", "Closed" };
-	const char * power_source[]      = { "AC\t", "Battery", "AC & Battery" };
-	const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
-	const char * epow_sensor[]       = { 
-		"EPOW Reset", "Cooling warning", "Power warning",
-		"System shutdown", "System halt", "EPOW main enclosure",
-		"EPOW power off" };
-	const char * battery_cyclestate[]  = { "None", "In progress", "Requested" };
-	const char * battery_charging[]    = { "Charging", "Discharching", "No current flow" };
-	const char * ibm_drconnector[]     = { "Empty", "Present" };
-	const char * ibm_intqueue[]        = { "Disabled", "Enabled" };
-
-	int have_strings = 0;
-	int temperature = 0;
-	int unknown = 0;
-	int n = 0;
-
-	/* What kind of sensor do we have here? */
-	switch (s.token) {
-		case KEY_SWITCH:
-			n += sprintf(buf+n, "Key switch:\t");
-			n += sprintf(buf+n, "%s\t", key_switch[state]);
-			have_strings = 1;
-			break;
-		case ENCLOSURE_SWITCH:
-			n += sprintf(buf+n, "Enclosure switch:\t");
-			n += sprintf(buf+n, "%s\t", enclosure_switch[state]);
-			have_strings = 1;
-			break;
-		case THERMAL_SENSOR:
-			n += sprintf(buf+n, "Temp. (°C/°F):\t");
-			temperature = 1;
-			break;
-		case LID_STATUS:
-			n += sprintf(buf+n, "Lid status:\t");
-			n += sprintf(buf+n, "%s\t", lid_status[state]);
-			have_strings = 1;
-			break;
-		case POWER_SOURCE:
-			n += sprintf(buf+n, "Power source:\t");
-			n += sprintf(buf+n, "%s\t", power_source[state]);
-			have_strings = 1;
-			break;
-		case BATTERY_VOLTAGE:
-			n += sprintf(buf+n, "Battery voltage:\t");
-			break;
-		case BATTERY_REMAINING:
-			n += sprintf(buf+n, "Battery remaining:\t");
-			n += sprintf(buf+n, "%s\t", battery_remaining[state]);
-			have_strings = 1;
-			break;
-		case BATTERY_PERCENTAGE:
-			n += sprintf(buf+n, "Battery percentage:\t");
-			break;
-		case EPOW_SENSOR:
-			n += sprintf(buf+n, "EPOW Sensor:\t");
-			n += sprintf(buf+n, "%s\t", epow_sensor[state]);
-			have_strings = 1;
-			break;
-		case BATTERY_CYCLESTATE:
-			n += sprintf(buf+n, "Battery cyclestate:\t");
-			n += sprintf(buf+n, "%s\t", battery_cyclestate[state]);
-			have_strings = 1;
-			break;
-		case BATTERY_CHARGING:
-			n += sprintf(buf+n, "Battery Charging:\t");
-			n += sprintf(buf+n, "%s\t", battery_charging[state]);
-			have_strings = 1;
-			break;
-		case IBM_SURVEILLANCE:
-			n += sprintf(buf+n, "Surveillance:\t");
-			break;
-		case IBM_FANRPM:
-			n += sprintf(buf+n, "Fan (rpm):\t");
-			break;
-		case IBM_VOLTAGE:
-			n += sprintf(buf+n, "Voltage (mv):\t");
-			break;
-		case IBM_DRCONNECTOR:
-			n += sprintf(buf+n, "DR connector:\t");
-			n += sprintf(buf+n, "%s\t", ibm_drconnector[state]);
-			have_strings = 1;
-			break;
-		case IBM_POWERSUPPLY:
-			n += sprintf(buf+n, "Powersupply:\t");
-			break;
-		case IBM_INTQUEUE:
-			n += sprintf(buf+n, "Interrupt queue:\t");
-			n += sprintf(buf+n, "%s\t", ibm_intqueue[state]);
-			have_strings = 1;
-			break;
-		default:
-			n += sprintf(buf+n,  "Unkown sensor (type %d), ignoring it\n",
-					s.token);
-			unknown = 1;
-			have_strings = 1;
-			break;
-	}
-	if (have_strings == 0) {
-		if (temperature) {
-			n += sprintf(buf+n, "%4d /%4d\t", state, cel_to_fahr(state));
-		} else
-			n += sprintf(buf+n, "%10d\t", state);
-	}
-	if (unknown == 0) {
-		n += sprintf ( buf+n, "%s\t", ppc_rtas_process_error(error));
-		n += get_location_code(s, buf+n);
-	}
-	return n;
-}
-
-/* ****************************************************************** */
-
-int check_location (char *c, int idx, char * buf)
-{
-	int n = 0;
-
-	switch (*(c+idx)) {
-		case LOC_PLANAR:
-			n += sprintf ( buf, "Planar #%c", *(c+idx+1));
-			break;
-		case LOC_CPU:
-			n += sprintf ( buf, "CPU #%c", *(c+idx+1));
-			break;
-		case LOC_FAN:
-			n += sprintf ( buf, "Fan #%c", *(c+idx+1));
-			break;
-		case LOC_RACKMOUNTED:
-			n += sprintf ( buf, "Rack #%c", *(c+idx+1));
-			break;
-		case LOC_VOLTAGE:
-			n += sprintf ( buf, "Voltage #%c", *(c+idx+1));
-			break;
-		case LOC_LCD:
-			n += sprintf ( buf, "LCD #%c", *(c+idx+1));
-			break;
-		case '.':
-			n += sprintf ( buf, "- %c", *(c+idx+1));
-		default:
-			n += sprintf ( buf, "Unknown location");
-			break;
-	}
-	return n;
-}
-
-
-/* ****************************************************************** */
-/* 
- * Format: 
- * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
- * the '.' may be an abbrevation
- */
-int check_location_string (char *c, char *buf)
-{
-	int n=0,i=0;
-
-	while (c[i]) {
-		if (isalpha(c[i]) || c[i] == '.') {
-			 n += check_location(c, i, buf+n);
-		}
-		else if (c[i] == '/' || c[i] == '-')
-			n += sprintf(buf+n, " at ");
-		i++;
-	}
-	return n;
-}
-
-
-/* ****************************************************************** */
-
-int get_location_code(struct individual_sensor s, char * buffer)
-{
-	char rstr[512], tmp[10], tmp2[10];
-	int n=0, i=0, llen, len;
-	/* char *buf = kmalloc(MAX_LINELENGTH, GFP_KERNEL); */
-	char *ret;
-
-	static int pos = 0; /* remember position where buffer was */
-
-	/* construct the sensor number like 0003 */
-	/* fill with zeros */
-	n = sprintf(tmp, "%d", s.token);
-	len = strlen(tmp);
-	while (strlen(tmp) < 4)
-		n += sprintf (tmp+n, "0");
-	
-	/* invert the string */
-	while (tmp[i]) {
-		if (i<len)
-			tmp2[4-len+i] = tmp[i];
-		else
-			tmp2[3-i] = tmp[i];
-		i++;
-	}
-	tmp2[4] = '\0';
-
-	sprintf (rstr, SENSOR_PREFIX"%s", tmp2);
-
-	ret = (char *) get_property(rtas, rstr, &llen);
-
-	n=0;
-	if (ret[0] == '\0')
-		n += sprintf ( buffer+n, "--- ");/* does not have a location */
-	else {
-		char t[50];
-		ret += pos;
-
-		n += check_location_string(ret, buffer + n);
-		n += sprintf ( buffer+n, " ");
-		/* see how many characters we have printed */
-		sprintf ( t, "%s ", ret);
-
-		pos += strlen(t);
-		if (pos >= llen) pos=0;
-	}
-	return n;
-}
-/* ****************************************************************** */
-/* INDICATORS - Tone Frequency                                        */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos)
-{
-	unsigned long freq;
-	char *dest;
-	int error;
-	freq = simple_strtoul(buf, &dest, 10);
-	if (*dest != '\0' && *dest != '\n') {
-		printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n");
-		return count;
-	}
-	if (freq < 0) freq = 0;
-	rtas_tone_frequency = freq; /* save it for later */
-	error = call_rtas("set-indicator", 3, 1, NULL,
-			TONE_FREQUENCY, 0, freq);
-	if (error != 0)
-		printk(KERN_WARNING "error: setting tone frequency returned: %s\n", 
-				ppc_rtas_process_error(error));
-	return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos)
-{
-	int n;
-	n = sprintf(buf, "%lu\n", rtas_tone_frequency);
-
-	if (*ppos >= strlen(buf))
-		return 0;
-	if (n > strlen(buf) - *ppos)
-		n = strlen(buf) - *ppos;
-	if (n > count)
-		n = count;
-	*ppos += n;
-	return n;
-}
-/* ****************************************************************** */
-/* INDICATORS - Tone Volume                                           */
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
-		size_t count, loff_t *ppos)
-{
-	unsigned long volume;
-	char *dest;
-	int error;
-	volume = simple_strtoul(buf, &dest, 10);
-	if (*dest != '\0' && *dest != '\n') {
-		printk("ppc_rtas_tone_volume_write: Invalid tone volume\n");
-		return count;
-	}
-	if (volume < 0) volume = 0;
-	if (volume > 100) volume = 100;
-	
-        rtas_tone_volume = volume; /* save it for later */
-	error = call_rtas("set-indicator", 3, 1, NULL,
-			TONE_VOLUME, 0, volume);
-	if (error != 0)
-		printk(KERN_WARNING "error: setting tone volume returned: %s\n", 
-				ppc_rtas_process_error(error));
-	return count;
-}
-/* ****************************************************************** */
-static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
-		size_t count, loff_t *ppos)
-{
-	int n;
-	n = sprintf(buf, "%lu\n", rtas_tone_volume);
-
-	if (*ppos >= strlen(buf))
-		return 0;
-	if (n > strlen(buf) - *ppos)
-		n = strlen(buf) - *ppos;
-	if (n > count)
-		n = count;
-	*ppos += n;
-	return n;
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- linux.orig/arch/ppc/kernel/prom.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/prom.c	2002-08-12 22:14:03.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.prom.c 1.52 04/09/02 21:01:58 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * Procedures for interfacing to the Open Firmware PROM on
@@ -26,6 +26,7 @@
 #include <asm/page.h>
 #include <asm/processor.h>
 #include <asm/irq.h>
+#include <asm/open_pic.h>
 #include <asm/system.h>
 #include <asm/btext.h>
 #include <asm/pci-bridge.h>
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/ptrace.c linux/arch/ppc/kernel/ptrace.c
--- linux.orig/arch/ppc/kernel/ptrace.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/ptrace.c	2002-08-12 22:14:10.000000000 +0000
@@ -16,8 +16,7 @@
  * and Paul Mackerras (paulus@linuxcare.com.au).
  *
  * This file is subject to the terms and conditions of the GNU General
- * Public License.  See the file README.legal in the main directory of
- * this archive for more details.
+ * Public License.  Please read the COPYING file for all license details.
  */
 
 #include <linux/kernel.h>
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/qspan_pci.c linux/arch/ppc/kernel/qspan_pci.c
--- linux.orig/arch/ppc/kernel/qspan_pci.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/qspan_pci.c	2002-08-12 22:14:08.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.qspan_pci.c 1.5 05/17/01 18:14:22 cort
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * QSpan pci routines.
@@ -29,8 +29,7 @@
 #include <asm/mpc8xx.h>
 #include <asm/system.h>
 #include <asm/machdep.h>
-
-#include "pci.h"
+#include <asm/pci-bridge.h>
 
 
 /*
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- linux.orig/arch/ppc/kernel/residual.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/residual.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,913 +0,0 @@
-/*
- * BK Id: SCCS/s.residual.c 1.15 02/05/02 18:08:35 trini
- */
-/*
- * Code to deal with the PReP residual data.
- *
- * Written by: Cort Dougan (cort@cs.nmt.edu)
- * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
- *
- *  This file is based on the following documentation:
- *
- *	IBM Power Personal Systems Architecture
- *	Residual Data
- * 	Document Number: PPS-AR-FW0001
- *
- *  This file is subject to the terms and conditions of the GNU General Public
- *  License.  See the file COPYING in the main directory of this archive
- *  for more details.
- *
- */
-
-#include <linux/string.h>
-#include <asm/residual.h>
-#include <asm/pnp.h>
-#include <asm/byteorder.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/slab.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/ioport.h>
-#include <linux/pci.h>
-#include <linux/ide.h>
-
-#include <asm/sections.h>
-#include <asm/mmu.h>
-#include <asm/processor.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/ide.h>
-
-
-unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
-RESIDUAL *res = (RESIDUAL *)&__res;
-
-char * PnP_BASE_TYPES[] __initdata = {
-  "Reserved",
-  "MassStorageDevice",
-  "NetworkInterfaceController",
-  "DisplayController",
-  "MultimediaController",
-  "MemoryController",
-  "BridgeController",
-  "CommunicationsDevice",
-  "SystemPeripheral",
-  "InputDevice",
-  "ServiceProcessor"
-  };
-
-/* Device Sub Type Codes */
-
-unsigned char * PnP_SUB_TYPES[] __initdata = {
-  "\001\000SCSIController",
-  "\001\001IDEController",
-  "\001\002FloppyController",
-  "\001\003IPIController",
-  "\001\200OtherMassStorageController",
-  "\002\000EthernetController",
-  "\002\001TokenRingController",
-  "\002\002FDDIController",
-  "\002\0x80OtherNetworkController",
-  "\003\000VGAController",
-  "\003\001SVGAController",
-  "\003\002XGAController",
-  "\003\200OtherDisplayController",
-  "\004\000VideoController",
-  "\004\001AudioController",
-  "\004\200OtherMultimediaController",
-  "\005\000RAM",
-  "\005\001FLASH",
-  "\005\200OtherMemoryDevice",
-  "\006\000HostProcessorBridge",
-  "\006\001ISABridge",
-  "\006\002EISABridge",
-  "\006\003MicroChannelBridge",
-  "\006\004PCIBridge",
-  "\006\005PCMCIABridge",
-  "\006\006VMEBridge",
-  "\006\200OtherBridgeDevice",
-  "\007\000RS232Device",
-  "\007\001ATCompatibleParallelPort",
-  "\007\200OtherCommunicationsDevice",
-  "\010\000ProgrammableInterruptController",
-  "\010\001DMAController",
-  "\010\002SystemTimer",
-  "\010\003RealTimeClock",
-  "\010\004L2Cache",
-  "\010\005NVRAM",
-  "\010\006PowerManagement",
-  "\010\007CMOS",
-  "\010\010OperatorPanel",
-  "\010\011ServiceProcessorClass1",
-  "\010\012ServiceProcessorClass2",
-  "\010\013ServiceProcessorClass3",
-  "\010\014GraphicAssist",
-  "\010\017SystemPlanar",
-  "\010\200OtherSystemPeripheral",
-  "\011\000KeyboardController",
-  "\011\001Digitizer",
-  "\011\002MouseController",
-  "\011\003TabletController",
-  "\011\0x80OtherInputController",
-  "\012\000GeneralMemoryController",
-  NULL
-};
-
-/* Device Interface Type Codes */
-
-unsigned char * PnP_INTERFACES[] __initdata = {
-  "\000\000\000General",
-  "\001\000\000GeneralSCSI",
-  "\001\001\000GeneralIDE",
-  "\001\001\001ATACompatible",
-
-  "\001\002\000GeneralFloppy",
-  "\001\002\001Compatible765",
-  "\001\002\002NS398_Floppy",         /* NS Super I/O wired to use index
-                                         register at port 398 and data
-                                         register at port 399               */
-  "\001\002\003NS26E_Floppy",         /* Ports 26E and 26F                  */
-  "\001\002\004NS15C_Floppy",         /* Ports 15C and 15D                  */
-  "\001\002\005NS2E_Floppy",          /* Ports 2E and 2F                    */
-  "\001\002\006CHRP_Floppy",          /* CHRP Floppy in PR*P system         */
-
-  "\001\003\000GeneralIPI",
-  
-  "\002\000\000GeneralEther",
-  "\002\001\000GeneralToken",
-  "\002\002\000GeneralFDDI",
-  
-  "\003\000\000GeneralVGA",
-  "\003\001\000GeneralSVGA",
-  "\003\002\000GeneralXGA",
-  
-  "\004\000\000GeneralVideo",
-  "\004\001\000GeneralAudio",
-  "\004\001\001CS4232Audio",            /* CS 4232 Plug 'n Play Configured    */
-
-  "\005\000\000GeneralRAM",
-  /* This one is obviously wrong ! */
-  "\005\000\000PCIMemoryController",    /* PCI Config Method                  */
-  "\005\000\001RS6KMemoryController",   /* RS6K Config Method                 */
-  "\005\001\000GeneralFLASH",
-  
-  "\006\000\000GeneralHostBridge",
-  "\006\001\000GeneralISABridge",
-  "\006\002\000GeneralEISABridge",
-  "\006\003\000GeneralMCABridge",
-  /* GeneralPCIBridge = 0, */
-  "\006\004\000PCIBridgeDirect",
-  "\006\004\001PCIBridgeIndirect",
-  "\006\004\002PCIBridgeRS6K",
-  "\006\005\000GeneralPCMCIABridge",
-  "\006\006\000GeneralVMEBridge",
-  
-  "\007\000\000GeneralRS232",
-  "\007\000\001COMx",
-  "\007\000\002Compatible16450",
-  "\007\000\003Compatible16550",
-  "\007\000\004NS398SerPort",         /* NS Super I/O wired to use index
-                                         register at port 398 and data
-                                         register at port 399               */
-  "\007\000\005NS26ESerPort",         /* Ports 26E and 26F                  */
-  "\007\000\006NS15CSerPort",         /* Ports 15C and 15D                  */
-  "\007\000\007NS2ESerPort",          /* Ports 2E and 2F                    */
-
-  "\007\001\000GeneralParPort",
-  "\007\001\001LPTx",
-  "\007\001\002NS398ParPort",         /* NS Super I/O wired to use index
-                                         register at port 398 and data
-                                         register at port 399               */
-  "\007\001\003NS26EParPort",         /* Ports 26E and 26F                  */
-  "\007\001\004NS15CParPort",         /* Ports 15C and 15D                  */
-  "\007\001\005NS2EParPort",          /* Ports 2E and 2F                    */
-  
-  "\010\000\000GeneralPIC",
-  "\010\000\001ISA_PIC",
-  "\010\000\002EISA_PIC",
-  "\010\000\003MPIC",
-  "\010\000\004RS6K_PIC",
-
-  "\010\001\000GeneralDMA",
-  "\010\001\001ISA_DMA",
-  "\010\001\002EISA_DMA",
-
-  "\010\002\000GeneralTimer",
-  "\010\002\001ISA_Timer",
-  "\010\002\002EISA_Timer",
-  "\010\003\000GeneralRTC",
-  "\010\003\001ISA_RTC",
-  
-  "\010\004\001StoreThruOnly",
-  "\010\004\002StoreInEnabled",
-  "\010\004\003RS6KL2Cache",
-
-  "\010\005\000IndirectNVRAM",        /* Indirectly addressed               */
-  "\010\005\001DirectNVRAM",          /* Memory Mapped                      */
-  "\010\005\002IndirectNVRAM24",      /* Indirectly addressed - 24 bit      */
-
-  "\010\006\000GeneralPowerManagement",
-  "\010\006\001EPOWPowerManagement",
-  "\010\006\002PowerControl",         // d1378
-  
-  "\010\007\000GeneralCMOS",
-
-  "\010\010\000GeneralOPPanel",
-  "\010\010\001HarddiskLight",
-  "\010\010\002CDROMLight",
-  "\010\010\003PowerLight",
-  "\010\010\004KeyLock",
-  "\010\010\005ANDisplay",            /* AlphaNumeric Display               */
-  "\010\010\006SystemStatusLED",      /* 3 digit 7 segment LED              */
-  "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system           */
-
-  "\010\011\000GeneralServiceProcessor",
-  "\010\012\000GeneralServiceProcessor",
-  "\010\013\000GeneralServiceProcessor",
-  
-  "\010\014\001TransferData",
-  "\010\014\002IGMC32",
-  "\010\014\003IGMC64",
-  
-  "\010\017\000GeneralSystemPlanar",   /* 10/5/95                            */
-  NULL
-  };
-
-static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType, 
-					     unsigned char SubType) {
-	unsigned char ** s=PnP_SUB_TYPES;
-	while (*s && !((*s)[0]==BaseType 
-		       && (*s)[1]==SubType)) s++;
-	if (*s) return *s+2;
-	else return("Unknown !");
-};
-
-static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType, 
-					      unsigned char SubType,
-					      unsigned char Interface) {
-	unsigned char ** s=PnP_INTERFACES;
-	while (*s && !((*s)[0]==BaseType 
-		       && (*s)[1]==SubType 
-		       && (*s)[2]==Interface)) s++;
-	if (*s) return *s+3;
-	else return NULL;
-};
-
-static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
-	int i, c;
-	char decomp[4];
-#define p pkt->S14_Pack.S14_Data.S14_PPCPack
-	switch(p.Type) {
-	case 1:
-	  /* Decompress first 3 chars */
-	  c = *(unsigned short *)p.PPCData;
-	  decomp[0]='A'-1+((c>>10)&0x1F);
-	  decomp[1]='A'-1+((c>>5)&0x1F);
-	  decomp[2]='A'-1+(c&0x1F);
-	  decomp[3]=0;
-	  printk("    Chip identification: %s%4.4X\n",
-		 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
-	  break;
-	default:
-	  printk("    Small vendor item type 0x%2.2x, data (hex): ",
-		 p.Type);
-	  for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
-	  printk("\n");
-	  break;
-	}
-#undef p
-}
-
-static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
-	static const unsigned char * intlevel[] = {"high", "low"};
-	static const unsigned char * intsense[] = {"edge", "level"};
-
-	switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
-	case PnPVersion:
-	  printk("    PnPversion 0x%x.%x\n", 
-		 pkt->S1_Pack.Version[0], /* How to interpret version ? */
-		 pkt->S1_Pack.Version[1]);
-	  break;
-//	case Logicaldevice:
-	  break;
-//	case CompatibleDevice:
-	  break;
-	case IRQFormat:
-#define p pkt->S4_Pack
-	  printk("    IRQ Mask 0x%4.4x, %s %s sensitive\n", 
-		 ld_le16((unsigned short *)p.IRQMask),
-		 intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
-		 intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
-#undef p
-	  break;
-	case DMAFormat:
-#define p pkt->S5_Pack
-	  printk("    DMA channel mask 0x%2.2x, info 0x%2.2x\n",
-		 p.DMAMask, p.DMAInfo);
-#undef p
-	  break;
-	case StartDepFunc:
-	  printk("Start dependent function:\n");
-	  break;
-	case EndDepFunc:
-	  printk("End dependent function\n");
-	  break;
-	case IOPort:
-#define p pkt->S8_Pack
-	  printk("    Variable (%d decoded bits) I/O port\n"
-		 "      from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
-		 p.IOInfo&ISAAddr16bit?16:10,
-		 ld_le16((unsigned short *)p.RangeMin),
- 		 ld_le16((unsigned short *)p.RangeMax),
-		 p.IOAlign, p.IONum); 
-#undef p
-	  break;
-	case FixedIOPort:
-#define p pkt->S9_Pack
-	  printk("    Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
-		 (p.Range[1]<<8)|p.Range[0],
-		 ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
-#undef p		 
-	  break;
-	case Res1:
-	case Res2:
-	case Res3:
-	  printk("    Undefined packet type %d!\n", 
-		 tag_small_item_name(pkt->S1_Pack.Tag));
-	  break;
-	case SmallVendorItem:
-	  printsmallvendor(pkt,size);
-	  break;
-	default:
-	  printk("    Type 0x2.2x%d, size=%d\n", 
-		 pkt->S1_Pack.Tag, size);    
-	  break;
-	}
-}
-
-static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
-	static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
-	static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
-	static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
-	static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
-	static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
-	static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
-
-	int i;
-	char tmpstr[30], *t;
-#define p pkt->L4_Pack.L4_Data.L4_PPCPack
-	switch(p.Type) {
-	case 2:
-	  printk("    %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
-		 ld_le32((unsigned int *)p.PPCData),
-		 L2type[p.PPCData[10]-1],
-		 L2assoc[p.PPCData[4]-1],
-		 ld_le16((unsigned short *)p.PPCData+3),
-		 ld_le16((unsigned short *)p.PPCData+4));
-	  break;
-	case 3:
-	  printk("    PCI Bridge parameters\n"
-		 "      ConfigBaseAddress %0x\n"
-		 "      ConfigBaseData %0x\n"
-		 "      Bus number %d\n",
-		 ld_le32((unsigned int *)p.PPCData),
-		 ld_le32((unsigned int *)(p.PPCData+8)),
-		 p.PPCData[16]);
-	  for(i=20; i<size-4; i+=12) {
-	  	int j, first;
-	  	if(p.PPCData[i]) printk("      PCI Slot %d", p.PPCData[i]);
-		else printk ("      Integrated PCI device");
-		for(j=0, first=1, t=tmpstr; j<4; j++) {
-			int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
-			if(line!=0xffff){
-			        if(first) first=0; else *t++='/';
-				*t++='A'+j;
-			}
-		}
-		*t='\0';
-		printk(" DevFunc 0x%x interrupt line(s) %s routed to",
-		       p.PPCData[i+1],tmpstr);
-		sprintf(tmpstr,
-			inttype[p.PPCData[i+2]-1],
-			p.PPCData[i+3]);
-		printk(" %s line(s) ",
-		       tmpstr);
-		for(j=0, first=1, t=tmpstr; j<4; j++) {
-			int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
-			if(line!=0xffff){
-				if(first) first=0; else *t++='/';
-				t+=sprintf(t,"%d(%c)",
-					   line&0x7fff,
-					   line&0x8000?'E':'L');
-			}
-		}
-		printk("%s\n",tmpstr);
-	  }
-	  break;
-	case 5:
-	  printk("    Bridge address translation, %s decoding:\n"
-		 "      Processor  Bus        Size       Conversion Translation\n"
-		 "      0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
-		 p.PPCData[0]&1 ? "positive" : "subtractive",
-		 ld_le32((unsigned int *)p.PPCData+1),
-		 ld_le32((unsigned int *)p.PPCData+3),
-		 ld_le32((unsigned int *)p.PPCData+5),
-		 convtype[p.PPCData[2]-1],
-		 transtype[p.PPCData[1]-1]);
-	  break;
-	case 6:
-	  printk("    Bus speed %d Hz, %d slot(s)\n",
-		 ld_le32((unsigned int *)p.PPCData),
-		 p.PPCData[4]);
-	  break;
-	case 7:
-	  printk("    SCSI buses: %d, id(s):", p.PPCData[0]);
-	  for(i=1; i<=p.PPCData[0]; i++) 
-	    printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
-	  break;
-	case 9:
-	  printk("    %s address (%d bits), at 0x%x size 0x%x bytes\n",
-		 addrtype[p.PPCData[0]-1],
-		 p.PPCData[1],
-		 ld_le32((unsigned int *)(p.PPCData+4)),
-		 ld_le32((unsigned int *)(p.PPCData+12)));
-	  break;
-	case 10:
-	  sprintf(tmpstr,
-		  inttype[p.PPCData[0]-1],
-		  p.PPCData[1]);
-
-	  printk("    ISA interrupts routed to %s\n"
-		 "      lines", 
-		 tmpstr);
-	  for(i=0; i<16; i++) {
-	  	int line=ld_le16((unsigned short *)p.PPCData+i+1);
-		if (line!=0xffff) printk(" %d(IRQ%d)", line, i); 
-	  }
-	  printk("\n");
-	  break;
-	default:
-	  printk("    Large vendor item type 0x%2.2x\n      Data (hex):",
-		 p.Type);
-	  for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
-	  printk("\n");
-#undef p
-	}
-}
-
-static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
-	switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
-	case LargeVendorItem:
-	  printlargevendor(pkt, size);
-	  break;
-	default:
-	  printk("    Type 0x2.2x%d, size=%d\n", 
-		 pkt->S1_Pack.Tag, size);    
-	  break;
-	}
-}
-static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
-	if (pkt->S1_Pack.Tag== END_TAG) {
-		printk("  No packets describing %s resources.\n", cat);
-		return;
-	}
-	printk(  "  Packets describing %s resources:\n",cat);
-	do {
-		int size;
-		if (tag_type(pkt->S1_Pack.Tag)) {
-		  	size= 3 +
-			  pkt->L1_Pack.Count0 + 
-			  pkt->L1_Pack.Count1*256;
-			printlargepacket(pkt, size);
-		} else {
-			size=tag_small_count(pkt->S1_Pack.Tag)+1;
-			printsmallpacket(pkt, size);
-		}
-		(unsigned char *) pkt+=size;
-	} while (pkt->S1_Pack.Tag != END_TAG);
-}
-
-void __init print_residual_device_info(void)
-{
-	int i;
-	PPC_DEVICE *dev;
-#define did dev->DeviceId
-	
-	/* make sure we have residual data first */
-	if ( res->ResidualLength == 0 )
-		return;
-	
-	printk("Residual: %ld devices\n", res->ActualNumDevices);
-	for ( i = 0;
-	      i < res->ActualNumDevices ;
-	      i++)
-	{
-	  	char decomp[4], sn[20];
-		const char * s;
-		dev = &res->Devices[i];
-		s = PnP_INTERFACE_STR(did.BaseType, did.SubType, 
-				      did.Interface);
-		if(!s) {
-			sprintf(sn, "interface %d", did.Interface);
-			s=sn;
-		}
-		if ( did.BusId & PCIDEVICE ) 
-		  printk("PCI Device, Bus %d, DevFunc 0x%x:",
-			 dev->BusAccess.PCIAccess.BusNumber,
-			 dev->BusAccess.PCIAccess.DevFuncNumber);
-	       	if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:");
-		if ( did.BusId & ISADEVICE ) 
-		  printk("ISA Device, Slot %d, LogicalDev %d:",
-			 dev->BusAccess.ISAAccess.SlotNumber,
-			 dev->BusAccess.ISAAccess.LogicalDevNumber);
-		if ( did.BusId & EISADEVICE ) printk("EISA Device:");
-		if ( did.BusId & PROCESSORDEVICE ) 
-		  printk("ProcBus Device, Bus %d, BUID %d: ",
-			 dev->BusAccess.ProcBusAccess.BusNumber,
-			 dev->BusAccess.ProcBusAccess.BUID);
-		if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA ");
-		if ( did.BusId & VMEDEVICE ) printk("VME ");
-		if ( did.BusId & MCADEVICE ) printk("MCA ");
-		if ( did.BusId & MXDEVICE ) printk("MX ");
-		/* Decompress first 3 chars */
-		decomp[0]='A'-1+((did.DevId>>26)&0x1F);
-		decomp[1]='A'-1+((did.DevId>>21)&0x1F);
-		decomp[2]='A'-1+((did.DevId>>16)&0x1F);
-		decomp[3]=0;
-		printk(" %s%4.4lX, %s, %s, %s\n", 
-		       decomp, did.DevId&0xffff,
-		       PnP_BASE_TYPES[did.BaseType],
-		       PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
-		       s);
-		if ( dev->AllocatedOffset )
-			printpackets( (union _PnP_TAG_PACKET *)
-				      &res->DevicePnPHeap[dev->AllocatedOffset],
-				      "allocated");
-		if ( dev->PossibleOffset )
-			printpackets( (union _PnP_TAG_PACKET *)
-				      &res->DevicePnPHeap[dev->PossibleOffset],
-				      "possible");
-		if ( dev->CompatibleOffset )
-			printpackets( (union _PnP_TAG_PACKET *)
-				      &res->DevicePnPHeap[dev->CompatibleOffset],
-				      "compatible");
-	}
-}
-
-
-#if 0
-static void __init printVPD(void) {
-#define vpd res->VitalProductData
-	int ps=vpd.PageSize, i, j;
-	static const char* Usage[]={
-	  "FirmwareStack",  "FirmwareHeap",  "FirmwareCode", "BootImage",
-	  "Free", "Unpopulated", "ISAAddr", "PCIConfig",
-	  "IOMemory", "SystemIO", "SystemRegs", "PCIAddr", 
-	  "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other" 
-	};
-	static const unsigned char *FWMan[]={
-	  "IBM", "Motorola", "FirmWorks", "Bull"
-	};
-	static const unsigned char *FWFlags[]={
-	  "Conventional", "OpenFirmware", "Diagnostics", "LowDebug",
-	  "MultiBoot", "LowClient", "Hex41", "FAT", 
-	  "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path"
-	};
-	static const unsigned char *ESM[]={
-	  "Port92", "PCIConfigA8", "FF001030", "????????"
-	};
-	static const unsigned char *SIOM[]={
-	  "Port850", "????????", "PCIConfigA8", "????????"
-	};
-
-	printk("Model: %s\n",vpd.PrintableModel);
-	printk("Serial: %s\n", vpd.Serial);
-	printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]);
-	printk("FirmwareFlags:");
-	for(j=0; j<12; j++) {
-	  	if (vpd.FirmwareSupports & (1<<j)) {
-			printk(" %s%c", FWFlags[j], 
-			       vpd.FirmwareSupports&(-2<<j) ? ',' : '\n');
-		}
-	}
-	printk("NVRamSize: %ld\n", vpd.NvramSize);
-	printk("SIMMslots: %ld\n", vpd.NumSIMMSlots);
-	printk("EndianSwitchMethod: %s\n", 
-	       ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]);
-	printk("SpreadIOMethod: %s\n", 
-	       SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]);
-	printk("Processor/Bus frequencies (Hz): %ld/%ld\n",
-	       vpd.ProcessorHz, vpd.ProcessorBusHz);
-	printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor);
-	printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps);
-	printk("Cache sector size, Lock granularity: %ld, %ld\n",
-	       vpd.CoherenceBlockSize, vpd.GranuleSize);
-	for (i=0; i<res->ActualNumMemSegs; i++) {
-		int mask=res->Segs[i].Usage, first, j;
-		printk("%8.8lx-%8.8lx ", 
-		       res->Segs[i].BasePage*ps,
-		       (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1);
-		for(j=15, first=1; j>=0; j--) {
-			if (mask&(1<<j)) {
-				if (first) first=0;
-				else printk(", ");
-				printk("%s", Usage[j]);
-			}
-		}
-		printk("\n");
-	}
-}
-
-/*
- * Spit out some info about residual data
- */
-void print_residual_device_info(void)
-{
-	int i;
-	union _PnP_TAG_PACKET *pkt;
-	PPC_DEVICE *dev;
-#define did dev->DeviceId
-	
-	/* make sure we have residual data first */
-	if ( res->ResidualLength == 0 )
-		return;
-	printk("Residual: %ld devices\n", res->ActualNumDevices);
-	for ( i = 0;
-	      i < res->ActualNumDevices ;
-	      i++)
-	{
-		dev = &res->Devices[i];
-		/*
-		 * pci devices
-		 */
-		if ( did.BusId & PCIDEVICE )
-		{
-			printk("PCI Device:");
-			/* unknown vendor */
-			if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
-				printk(" id %08lx types %d/%d", did.DevId,
-				       did.BaseType, did.SubType);
-			/* known vendor */
-			else
-				printk(" %s %s",
-				       pci_strvendor(did.DevId>>16),
-				       pci_strdev(did.DevId>>16,
-						  did.DevId&0xffff)
-					);
-			
-			if ( did.BusId & PNPISADEVICE )
-			{
-				printk(" pnp:");
-				/* get pnp info on the device */
-				pkt = (union _PnP_TAG_PACKET *)
-					&res->DevicePnPHeap[dev->AllocatedOffset];
-				for (; pkt->S1_Pack.Tag != DF_END_TAG;
-				     pkt++ )
-				{
-					if ( (pkt->S1_Pack.Tag == S4_Packet) ||
-					     (pkt->S1_Pack.Tag == S4_Packet_flags) )
-						printk(" irq %02x%02x",
-						       pkt->S4_Pack.IRQMask[0],
-						       pkt->S4_Pack.IRQMask[1]);
-				}
-			}
-			printk("\n");
-			continue;
-		}
-		/*
-		 * isa devices
-		 */
-		if ( did.BusId & ISADEVICE )
-		{
-			printk("ISA Device: basetype: %d subtype: %d",
-			       did.BaseType, did.SubType);
-			printk("\n");
-			continue;
-		}		
-		/*
-		 * eisa devices
-		 */
-		if ( did.BusId & EISADEVICE )
-		{
-			printk("EISA Device: basetype: %d subtype: %d",
-			       did.BaseType, did.SubType);
-			printk("\n");
-			continue;
-		}		
-		/*
-		 * proc bus devices
-		 */
-		if ( did.BusId & PROCESSORDEVICE )
-		{
-			printk("ProcBus Device: basetype: %d subtype: %d",
-			       did.BaseType, did.SubType);
-			printk("\n");
-			continue;
-		}
-		/*
-		 * pcmcia devices
-		 */
-		if ( did.BusId & PCMCIADEVICE )
-		{
-			printk("PCMCIA Device: basetype: %d subtype: %d",
-			       did.BaseType, did.SubType);
-			printk("\n");
-			continue;
-		}		
-		printk("Unknown bus access device: busid %lx\n",
-		       did.BusId);
-	}
-}
-#endif	
-
-/* Returns the device index in the residual data, 
-   any of the search items may be set as -1 for wildcard,
-   DevID number field (second halfword) is big endian ! 
-
-   Examples:
-   - search for the Interrupt controller (8259 type), 2 methods:
-     1) i8259 = residual_find_device(~0, 
-                                     NULL, 
-				     SystemPeripheral, 
-				     ProgrammableInterruptController, 
-				     ISA_PIC, 
-				     0);
-     2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0) 
-
-   - search for the first two serial devices, whatever their type)
-     iserial1 = residual_find_device(~0,NULL,
-                                     CommunicationsDevice,
-				     RS232Device,
-				     -1, 0)
-     iserial2 = residual_find_device(~0,NULL,
-                                     CommunicationsDevice,
-				     RS232Device,
-				     -1, 1)
-   - but search for typical COM1 and COM2 is not easy due to the
-     fact that the interface may be anything and the name "PNP0500" or 
-     "PNP0501". Quite bad. 
-
-*/
-
-/* devid are easier to uncompress than to compress, so to minimize bloat
-in this rarely used area we unencode and compare */
-
-/* in residual data number is big endian in the device table and
-little endian in the heap, so we use two parameters to avoid writing
-two very similar functions */
-
-static int __init same_DevID(unsigned short vendor,
-	       unsigned short Number,
-	       char * str) 
-{
-	static unsigned const char hexdigit[]="0123456789ABCDEF";
-	if (strlen(str)!=7) return 0;
-	if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0])  &&
-	     ( ((vendor>>5)&0x1f)+'A'-1 == str[1])   &&
-	     ( (vendor&0x1f)+'A'-1 == str[2])        &&
-	     (hexdigit[(Number>>12)&0x0f] == str[3]) &&
-	     (hexdigit[(Number>>8)&0x0f] == str[4])  &&
-	     (hexdigit[(Number>>4)&0x0f] == str[5])  &&
-	     (hexdigit[Number&0x0f] == str[6]) ) return 1;
-	return 0;
-}
-
-PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
-			 unsigned char * DevID,
-			 int BaseType,
-			 int SubType,
-			 int Interface,
-			 int n)
-{
-	int i;
-	if ( !res->ResidualLength ) return NULL;
-	for (i=0; i<res->ActualNumDevices; i++) {
-#define Dev res->Devices[i].DeviceId
-		if ( (Dev.BusId&BusMask)                                  &&
-		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
-		     (SubType==-1 || Dev.SubType==SubType)                &&
-		     (Interface==-1 || Dev.Interface==Interface)          &&
-		     (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
-						Dev.DevId&0xffff, DevID)) &&
-		     !(n--) ) return res->Devices+i;
-#undef Dev
-	}
-	return 0;
-}
-
-PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
-			 unsigned short DevID,
-			 int BaseType,
-			 int SubType,
-			 int Interface,
-			 int n)
-{
-	int i;
-	if ( !res->ResidualLength ) return NULL;
-	for (i=0; i<res->ActualNumDevices; i++) {
-#define Dev res->Devices[i].DeviceId
-		if ( (Dev.BusId&BusMask)                                  &&
-		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
-		     (SubType==-1 || Dev.SubType==SubType)                &&
-		     (Interface==-1 || Dev.Interface==Interface)          &&
-		     (DevID==0xffff || (Dev.DevId&0xffff) == DevID)	  &&
-		     !(n--) ) return res->Devices+i;
-#undef Dev
-	}
-	return 0;
-}
-
-PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
-				unsigned packet_tag,
-				int n)
-{
-	unsigned mask, masked_tag, size;
-	if(!p) return 0;
-	if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
-	masked_tag = packet_tag&mask;
-	for(; *p != END_TAG; p+=size) {
-		if ((*p & mask) == masked_tag && !(n--)) 
-			return (PnP_TAG_PACKET *) p;
-		if (tag_type(*p))
-			size=ld_le16((unsigned short *)(p+1))+3;
-		else 
-			size=tag_small_count(*p)+1;
-	}
-	return 0; /* not found */
-}
-
-PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
-					     unsigned packet_type,
-					     int n)
-{
-	int next=0;
-	while (p) {
-		p = (unsigned char *) PnP_find_packet(p, 0x70, next);
-		if (p && p[1]==packet_type && !(n--)) 
-			return (PnP_TAG_PACKET *) p;
-		next = 1;
-	};
-	return 0; /* not found */
-}
-
-PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
-					   unsigned packet_type,
-					   int n)
-{
-	int next=0;
-	while (p) {
-		p = (unsigned char *) PnP_find_packet(p, 0x84, next);
-		if (p && p[3]==packet_type && !(n--)) 
-			return (PnP_TAG_PACKET *) p;
-		next = 1;
-	};
-	return 0; /* not found */
-}
-
-#ifdef CONFIG_PROC_PREPRESIDUAL
-static int proc_prep_residual_read(char * buf, char ** start, off_t off,
-		int count, int *eof, void *data)
-{
-	int n;
-
-	n = res->ResidualLength - off;
-	if (n < 0) {
-		*eof = 1;
-		n = 0;
-	}
-	else {
-		if (n > count)
-			n = count;
-		else
-			*eof = 1;
-
-		memcpy(buf, (char *)res + off, n);
-		*start = buf;
-	}
-
-	return n;
-}
-
-void __init
-proc_prep_residual_init(void)
-{
-	if (res->ResidualLength)
-		create_proc_read_entry("residual", S_IRUGO, NULL,
-					proc_prep_residual_read, NULL);
-}
-
-__initcall(proc_prep_residual_init);
-#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- linux.orig/arch/ppc/kernel/setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/setup.c	2002-08-12 22:14:16.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.setup.c 1.75 04/16/02 20:08:22 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * Common prep/pmac/chrp boot and setup code.
@@ -29,17 +29,6 @@
 #include <asm/smp.h>
 #include <asm/elf.h>
 #include <asm/cputable.h>
-#ifdef CONFIG_8xx
-#include <asm/mpc8xx.h>
-#include <asm/8xx_immap.h>
-#endif
-#ifdef CONFIG_8260
-#include <asm/mpc8260.h>
-#include <asm/immap_8260.h>
-#endif
-#ifdef CONFIG_4xx
-#include <asm/ppc4xx.h>
-#endif
 #include <asm/bootx.h>
 #include <asm/btext.h>
 #include <asm/machdep.h>
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S
--- linux.orig/arch/ppc/kernel/sleep.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/kernel/sleep.S	1970-01-01 00:00:00.000000000 +0000
@@ -1,451 +0,0 @@
-/*
- * BK Id: SCCS/s.sleep.S 1.20 03/19/02 15:04:39 benh
- */
-/*
- * This file contains sleep low-level functions for PowerBook G3.
- *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
- *    and Paul Mackerras (paulus@samba.org).
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- */
-
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <asm/cputable.h>
-#include "ppc_asm.h"
-
-#define MAGIC	0x4c617273	/* 'Lars' */
-
-/*
- * Structure for storing CPU registers on the stack.
- */
-#define SL_SP		0
-#define SL_PC		4
-#define SL_MSR		8
-#define SL_SDR1		0xc
-#define SL_SPRG0	0x10	/* 4 sprg's */
-#define SL_DBAT0	0x20
-#define SL_IBAT0	0x28
-#define SL_DBAT1	0x30
-#define SL_IBAT1	0x38
-#define SL_DBAT2	0x40
-#define SL_IBAT2	0x48
-#define SL_DBAT3	0x50
-#define SL_IBAT3	0x58
-#define SL_TB		0x60
-#define SL_HID0		0x68
-#define SL_HID1		0x6c
-#define SL_MSSCR0	0x70
-#define SL_MSSSR0	0x74
-#define SL_ICTRL	0x78
-#define SL_LDSTCR	0x7c
-#define SL_LDSTDB	0x80
-#define SL_R2		0x84
-#define SL_CR		0x88
-#define SL_R12		0x8c	/* r12 to r31 */
-#define SL_SIZE		(SL_R12 + 80)
-
-	.text
-	.align	5
-
-/* This gets called by via-pmu.c late during the sleep process.
- * The PMU was already send the sleep command and will shut us down
- * soon. We need to save all that is needed and setup the wakeup
- * vector that will be called by the ROM on wakeup
- */
-_GLOBAL(low_sleep_handler)
-	mflr	r0
-	stw	r0,4(r1)
-	stwu	r1,-SL_SIZE(r1)
-	mfcr	r0
-	stw	r0,SL_CR(r1)
-	stw	r2,SL_R2(r1)
-	stmw	r12,SL_R12(r1)
-
-	/* Save MSR & SDR1 */
-	mfmsr	r4
-	stw	r4,SL_MSR(r1)
-	mfsdr1	r4
-	stw	r4,SL_SDR1(r1)
-
-	/* Get a stable timebase and save it */
-1:	mftbu	r4
-	stw	r4,SL_TB(r1)
-	mftb	r5
-	stw	r5,SL_TB+4(r1)
-	mftbu	r3
-	cmpw	r3,r4
-	bne	1b
-	
-	/* Save SPRGs */
-	mfsprg	r4,0
-	stw	r4,SL_SPRG0(r1)
-	mfsprg	r4,1
-	stw	r4,SL_SPRG0+4(r1)
-	mfsprg	r4,2
-	stw	r4,SL_SPRG0+8(r1)
-	mfsprg	r4,3
-	stw	r4,SL_SPRG0+12(r1)
-
-	/* Save BATs */
-	mfdbatu	r4,0
-	stw	r4,SL_DBAT0(r1)
-	mfdbatl	r4,0
-	stw	r4,SL_DBAT0+4(r1)
-	mfdbatu	r4,1
-	stw	r4,SL_DBAT1(r1)
-	mfdbatl	r4,1
-	stw	r4,SL_DBAT1+4(r1)
-	mfdbatu	r4,2
-	stw	r4,SL_DBAT2(r1)
-	mfdbatl	r4,2
-	stw	r4,SL_DBAT2+4(r1)
-	mfdbatu	r4,3
-	stw	r4,SL_DBAT3(r1)
-	mfdbatl	r4,3
-	stw	r4,SL_DBAT3+4(r1)
-	mfibatu	r4,0
-	stw	r4,SL_IBAT0(r1)
-	mfibatl	r4,0
-	stw	r4,SL_IBAT0+4(r1)
-	mfibatu	r4,1
-	stw	r4,SL_IBAT1(r1)
-	mfibatl	r4,1
-	stw	r4,SL_IBAT1+4(r1)
-	mfibatu	r4,2
-	stw	r4,SL_IBAT2(r1)
-	mfibatl	r4,2
-	stw	r4,SL_IBAT2+4(r1)
-	mfibatu	r4,3
-	stw	r4,SL_IBAT3(r1)
-	mfibatl	r4,3
-	stw	r4,SL_IBAT3+4(r1)
-
-	/* Save HID0 */
-	mfspr	r4,HID0
-	stw	r4,SL_HID0(r1)
-
-	/* Save 7400/7410/7450 specific registers */
-	mfspr	r3,PVR
-	srwi	r3,r3,16
-	cmpli	cr0,r3,0x8000
-	cmpli	cr1,r3,0x000c
-	cmpli	cr2,r3,0x800c
-	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
-	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
-	bne	1f
-	mfspr	r4,SPRN_MSSCR0
-	stw	r4,SL_MSSCR0(r1)
-	mfspr	r4,SPRN_MSSSR0
-	stw	r4,SL_MSSSR0(r1)
-	/* Save 7450 specific registers */
-	beq	cr1,1f
-	mfspr	r4,HID1
-	stw	r4,SL_HID1(r1)
-	mfspr	r4,SPRN_ICTRL
-	stw	r4,SL_ICTRL(r1)
-	mfspr	r4,SPRN_LDSTCR
-	stw	r4,SL_LDSTCR(r1)
-	mfspr	r4,SPRN_LDSTDB
-	stw	r4,SL_LDSTDB(r1)
-1:
-	/* The ROM can wake us up via 2 different vectors:
-	 *  - On wallstreet & lombard, we must write a magic
-	 *    value 'Lars' at address 4 and a pointer to a
-	 *    memory location containing the PC to resume from
-	 *    at address 0.
-	 *  - On Core99, we must store the wakeup vector at
-	 *    address 0x80 and eventually it's parameters
-	 *    at address 0x84. I've have some trouble with those
-	 *    parameters however and I no longer use them.
-	 */
-	lis	r5,grackle_wake_up@ha
-	addi	r5,r5,grackle_wake_up@l
-	tophys(r5,r5)
-	stw	r5,SL_PC(r1)
-	lis	r4,KERNELBASE@h
-	tophys(r5,r1)
-	addi	r5,r5,SL_PC
-	lis	r6,MAGIC@ha
-	addi	r6,r6,MAGIC@l
-	stw	r5,0(r4)
-	stw	r6,4(r4)
-	/* Setup stuffs at 0x80-0x84 for Core99 */
-	lis	r3,core99_wake_up@ha
-	addi	r3,r3,core99_wake_up@l
-	tophys(r3,r3)
-	stw	r3,0x80(r4)
-	stw	r5,0x84(r4)
-	/* Store a pointer to our backup storage into
-	 * a kernel global
-	 */
-	lis r3,sleep_storage@ha
-	addi r3,r3,sleep_storage@l
-	stw r5,0(r3)
-
-	BEGIN_FTR_SECTION
-	DSSALL
-	sync
-	END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-
-/*
- * Flush the L1 data cache by reading the first 128kB of RAM
- * and then flushing the same area with the dcbf instruction.
- * The L2 cache has already been disabled.
- */
-	li	r4,0x1000	/* 128kB / 32B */
-	mtctr	r4
-	lis	r4,KERNELBASE@h
-1:
-	lwz	r0,0(r4)
-	addi	r4,r4,0x0020	/* Go to start of next cache line */
-	bdnz	1b
-	sync
-	
-	li	r4,0x1000	/* 128kB / 32B */
-	mtctr	r4
-	lis	r4,KERNELBASE@h
-1:
-	dcbf	r0,r4
-	addi	r4,r4,0x0020	/* Go to start of next cache line */
-	bdnz	1b
-	sync
-
-/*
- * Set the HID0 and MSR for sleep.
- */
-	mfspr	r2,HID0
-	rlwinm	r2,r2,0,10,7	/* clear doze, nap */
-	oris	r2,r2,HID0_SLEEP@h
-	sync
-	mtspr	HID0,r2
-	sync
-
-/* This loop puts us back to sleep in case we have a spurrious
- * wakeup so that the host bridge properly stays asleep. The
- * CPU will be turned off, either after a known time (about 1
- * second) on wallstreet & lombard, or as soon as the CPU enters
- * SLEEP mode on core99
- */
-	mfmsr	r2
-	oris	r2,r2,MSR_POW@h
-1:	sync
-	mtmsr	r2
-	isync
-	b	1b
-
-/* 
- * Here is the resume code.
- */
-
-
-/*
- * Core99 machines resume here
- * r4 has the physical address of SL_PC(sp) (unused)
- */
-_GLOBAL(core99_wake_up)
-	/* Make sure HID0 no longer contains any sleep bit */
-	mfspr	r3,HID0
-	rlwinm	r3,r3,0,11,7		/* clear SLEEP, NAP, DOZE bits */
-	mtspr	HID0,r3
-	sync
-	isync
-
-	/* Won't that cause problems on CPU that doesn't support it ? */
-	lis	r3, 0
-	mtspr	SPRN_MMCR0, r3
-	
-	/* sanitize MSR */
-	mfmsr	r3
-	ori	r3,r3,MSR_EE|MSR_IP
-	xori	r3,r3,MSR_EE|MSR_IP
-	sync
-	isync
-	mtmsr	r3
-	sync
-	isync
-
-	/* Recover sleep storage */
-	lis	r3,sleep_storage@ha
-	addi	r3,r3,sleep_storage@l
-	tophys(r3,r3)
-	lwz	r1,0(r3)
-
-	/* Pass thru to older resume code ... */
-/* 
- * Here is the resume code for older machines.
- * r1 has the physical address of SL_PC(sp).
- */
-	
-grackle_wake_up:
-	/* Enable and then Flash inval the instruction & data cache */
-	mfspr	r3,HID0
-	ori	r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI
-	sync
-	isync
-	mtspr	HID0,r3
-	xori	r3,r3, HID0_ICFI|HID0_DCI
-	mtspr	HID0,r3
-	sync
-	
-	/* Restore the kernel's segment registers before
-	 * we do any r1 memory access as we are not sure they
-	 * are in a sane state above the first 256Mb region
-	 */
-	li	r0,16		/* load up segment register values */
-	mtctr	r0		/* for context 0 */
-	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
-	li	r4,0
-3:	mtsrin	r3,r4
-	addi	r3,r3,0x111	/* increment VSID */
-	addis	r4,r4,0x1000	/* address of next segment */
-	bdnz	3b
-	
-	/* Restore the remaining bits of the HID0 register. */
-	subi	r1,r1,SL_PC
-	lwz	r3,SL_HID0(r1)
-	sync
-	isync
-	mtspr	HID0,r3
-	sync
-	isync
-
-	/* Restore 7400/7410/7450 specific registers */
-	mfspr	r3,PVR
-	srwi	r3,r3,16
-	cmpli	cr0,r3,0x8000
-	cmpli	cr1,r3,0x000c
-	cmpli	cr2,r3,0x800c
-	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
-	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
-	bne	1f
-	lwz	r4,SL_MSSCR0(r1)
-	sync
-	mtspr	SPRN_MSSCR0,r4
-	sync
-	isync
-	lwz	r4,SL_MSSSR0(r1)
-	sync
-	mtspr	SPRN_MSSSR0,r4
-	sync
-	isync
-	bne	cr2,1f
-	li	r4,0
-	mtspr	SPRN_L2CR2,r4
-	/* Restore 7450 specific registers */
-	beq	cr1,1f
-	lwz	r4,SL_HID1(r1)
-	sync
-	mtspr	HID1,r4
-	isync
-	sync
-	lwz	r4,SPRN_ICTRL(r1)
-	sync
-	mtspr	SPRN_ICTRL,r4
-	isync
-	sync
-	lwz	r4,SPRN_LDSTCR(r1)
-	sync
-	mtspr	SPRN_LDSTCR,r4
-	isync
-	sync
-	lwz	r4,SL_LDSTDB(r1)
-	sync
-	mtspr	SPRN_LDSTDB,r4
-	isync
-	sync
-1:
-	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
-	lwz	r4,SL_SDR1(r1)
-	mtsdr1	r4
-	lwz	r4,SL_SPRG0(r1)
-	mtsprg	0,r4
-	lwz	r4,SL_SPRG0+4(r1)
-	mtsprg	1,r4
-	lwz	r4,SL_SPRG0+8(r1)
-	mtsprg	2,r4
-	lwz	r4,SL_SPRG0+12(r1)
-	mtsprg	3,r4
-
-	lwz	r4,SL_DBAT0(r1)
-	mtdbatu	0,r4
-	lwz	r4,SL_DBAT0+4(r1)
-	mtdbatl	0,r4
-	lwz	r4,SL_DBAT1(r1)
-	mtdbatu	1,r4
-	lwz	r4,SL_DBAT1+4(r1)
-	mtdbatl	1,r4
-	lwz	r4,SL_DBAT2(r1)
-	mtdbatu	2,r4
-	lwz	r4,SL_DBAT2+4(r1)
-	mtdbatl	2,r4
-	lwz	r4,SL_DBAT3(r1)
-	mtdbatu	3,r4
-	lwz	r4,SL_DBAT3+4(r1)
-	mtdbatl	3,r4
-	lwz	r4,SL_IBAT0(r1)
-	mtibatu	0,r4
-	lwz	r4,SL_IBAT0+4(r1)
-	mtibatl	0,r4
-	lwz	r4,SL_IBAT1(r1)
-	mtibatu	1,r4
-	lwz	r4,SL_IBAT1+4(r1)
-	mtibatl	1,r4
-	lwz	r4,SL_IBAT2(r1)
-	mtibatu	2,r4
-	lwz	r4,SL_IBAT2+4(r1)
-	mtibatl	2,r4
-	lwz	r4,SL_IBAT3(r1)
-	mtibatu	3,r4
-	lwz	r4,SL_IBAT3+4(r1)
-	mtibatl	3,r4
-
-	/* Flush all TLBs */
-	lis	r4,0x1000
-1:	addic.	r4,r4,-0x1000
-	tlbie	r4
-	blt	1b
-	sync
-
-	/* restore the MSR and turn on the MMU */
-	lwz	r3,SL_MSR(r1)
-	bl	turn_on_mmu	
-
-	/* get back the stack pointer */
-	tovirt(r1,r1)
-
-	/* Restore TB */
-	li	r3,0
-	mttbl	r3
-	lwz	r3,SL_TB(r1)
-	lwz	r4,SL_TB+4(r1)
-	mttbu	r3
-	mttbl	r4
-
-	/* Restore the callee-saved registers and return */
-	lwz	r0,SL_CR(r1)
-	mtcr	r0
-	lwz	r2,SL_R2(r1)
-	lmw	r12,SL_R12(r1)
-	addi	r1,r1,SL_SIZE
-	lwz	r0,4(r1)
-	mtlr	r0
-	blr
-
-turn_on_mmu:
-	mflr	r4
-	tovirt(r4,r4)
-	mtsrr0	r4
-	mtsrr1	r3
-	sync
-	isync
-	rfi
-
-	.data
-	.globl sleep_storage
-sleep_storage:
-	.long 0
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/walnut_setup.c linux/arch/ppc/kernel/walnut_setup.c
--- linux.orig/arch/ppc/kernel/walnut_setup.c	2001-11-16 18:10:08.000000000 +0000
+++ linux/arch/ppc/kernel/walnut_setup.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,292 +0,0 @@
-/*
- * BK Id: SCCS/s.walnut_setup.c 1.10 11/13/01 21:26:07 paulus
- */
-/*
- *
- *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: walnut_setup.c
- *
- *    Description:
- *      Architecture- / platform-specific boot-time initialization code for
- *      the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
- *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
- *      <dan@net4x.com>.
- *
- */
-
-#include <linux/config.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/threads.h>
-#include <linux/interrupt.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/blk.h>
-#include <linux/seq_file.h>
-
-#include <asm/processor.h>
-#include <asm/board.h>
-#include <asm/machdep.h>
-#include <asm/page.h>
-
-#include "local_irq.h"
-#include "ppc4xx_pic.h"
-#include <asm/time.h>
-#include "walnut_setup.h"
-
-
-/* Function Prototypes */
-
-extern void abort(void);
-
-/* Global Variables */
-
-unsigned char __res[sizeof(bd_t)];
-
-
-/*
- * void __init walnut_init()
- *
- * Description:
- *   This routine...
- *
- * Input(s):
- *   r3 - Optional pointer to a board information structure.
- *   r4 - Optional pointer to the physical starting address of the init RAM
- *        disk.
- *   r5 - Optional pointer to the physical ending address of the init RAM
- *        disk.
- *   r6 - Optional pointer to the physical starting address of any kernel
- *        command-line parameters.
- *   r7 - Optional pointer to the physical ending address of any kernel
- *        command-line parameters.
- *
- * Output(s):
- *   N/A
- *
- * Returns:
- *   N/A
- *
- */
-void __init
-walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, 
-	    unsigned long r6, unsigned long r7)
-{
-	/*
-	 * If we were passed in a board information, copy it into the
-	 * residual data area.
-	 */
-	if (r3) {
-		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
-	}
-
-#if defined(CONFIG_BLK_DEV_INITRD)
-	/*
-	 * If the init RAM disk has been configured in, and there's a valid
-	 * starting address for it, set it up.
-	 */
-	if (r4) {
-		initrd_start = r4 + KERNELBASE;
-		initrd_end = r5 + KERNELBASE;
-	}
-#endif /* CONFIG_BLK_DEV_INITRD */
-
-	/* Copy the kernel command line arguments to a safe place. */
-
-	if (r6) {
- 		*(char *)(r7 + KERNELBASE) = 0;
-		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
-	}
-
-	/* Initialize machine-dependency vectors */
-
-	ppc_md.setup_arch	 	= walnut_setup_arch;
-	ppc_md.show_percpuinfo	 	= walnut_show_percpuinfo;
-	ppc_md.irq_cannonicalize 	= NULL;
-	ppc_md.init_IRQ		 	= walnut_init_IRQ;
-	ppc_md.get_irq		 	= walnut_get_irq;
-	ppc_md.init		 	= NULL;
-
-	ppc_md.restart		 	= walnut_restart;
-	ppc_md.power_off	 	= walnut_power_off;
-	ppc_md.halt		 	= walnut_halt;
-
-	ppc_md.time_init	 	= walnut_time_init;
-	ppc_md.set_rtc_time	 	= walnut_set_rtc_time;
-	ppc_md.get_rtc_time	 	= walnut_get_rtc_time;
-	ppc_md.calibrate_decr	 	= walnut_calibrate_decr;
-
-	ppc_md.kbd_setkeycode    	= NULL;
-	ppc_md.kbd_getkeycode    	= NULL;
-	ppc_md.kbd_translate     	= NULL;
-	ppc_md.kbd_unexpected_up 	= NULL;
-	ppc_md.kbd_leds          	= NULL;
-	ppc_md.kbd_init_hw       	= NULL;
-	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_setup_arch(void)
-{
-	/* XXX - Implement me */
-}
-
-/*
- * int walnut_show_percpuinfo()
- *
- * Description:
- *   This routine pretty-prints the platform's internal CPU and bus clock
- *   frequencies into the buffer for usage in /proc/cpuinfo.
- *
- * Input(s):
- *  *buffer - Buffer into which CPU and bus clock frequencies are to be
- *            printed.
- *
- * Output(s):
- *  *buffer - Buffer with the CPU and bus clock frequencies.
- *
- * Returns:
- *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
- *   on error.
- */
-int
-walnut_show_percpuinfo(struct seq_file *m)
-{
-	bd_t *bp = (bd_t *)__res;
-
-	seq_printf(m, "clock\t\t: %dMHz\n"
-		   "bus clock\t\t: %dMHz\n",
-		   bp->bi_intfreq / 1000000,
-		   bp->bi_busfreq / 1000000);
-
-	return 0;
-}
-
-/*
- * Document me.
- */
-void __init
-walnut_init_IRQ(void)
-{
-	int i;
-
-	ppc4xx_pic_init();
-
-	for (i = 0; i < NR_IRQS; i++) {
-		irq_desc[i].handler = ppc4xx_pic;
-	}
-
-	return;
-}
-
-/*
- * Document me.
- */
-int
-walnut_get_irq(struct pt_regs *regs)
-{
-	return (ppc4xx_pic_get_irq(regs));
-}
-
-/*
- * Document me.
- */
-void
-walnut_restart(char *cmd)
-{
-	abort();
-}
-
-/*
- * Document me.
- */
-void
-walnut_power_off(void)
-{
-	walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-void
-walnut_halt(void)
-{
-	walnut_restart(NULL);
-}
-
-/*
- * Document me.
- */
-long __init
-walnut_time_init(void)
-{
-	/* XXX - Implement me */
-	return 0;
-}
-
-/*
- * Document me.
- */
-int __init
-walnut_set_rtc_time(unsigned long time)
-{
-	/* XXX - Implement me */
-
-	return (0);
-}
-
-/*
- * Document me.
- */
-unsigned long __init
-walnut_get_rtc_time(void)
-{
-	/* XXX - Implement me */
-
-	return (0);
-}
-
-/*
- * void __init walnut_calibrate_decr()
- *
- * Description:
- *   This routine retrieves the internal processor frequency from the board
- *   information structure, sets up the kernel timer decrementer based on
- *   that value, enables the 403 programmable interval timer (PIT) and sets
- *   it up for auto-reload.
- *
- * Input(s):
- *   N/A
- *
- * Output(s):
- *   N/A
- *
- * Returns:
- *   N/A
- *
- */
-void __init
-walnut_calibrate_decr(void)
-{
-	unsigned int freq;
-	bd_t *bip = (bd_t *)__res;
-
-	freq = bip->bi_intfreq;
-
-	decrementer_count = freq / HZ;
-	count_period_num = 1;
-	count_period_den = freq;
-
-	/* Enable the PIT and set auto-reload of its value */
-
-	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
-
-	/* Clear any pending timer interrupts */
-
-	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/walnut_setup.h linux/arch/ppc/kernel/walnut_setup.h
--- linux.orig/arch/ppc/kernel/walnut_setup.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/walnut_setup.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,53 +0,0 @@
-/*
- * BK Id: SCCS/s.walnut_setup.h 1.5 05/17/01 18:14:22 cort
- */
-/*
- *
- *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
- *
- *    Module name: walnut_setup.c
- *
- *    Description:
- *      Architecture- / platform-specific boot-time initialization code for
- *      the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
- *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
- *      <dan@netx4.com>.
- *
- */
-
-#ifndef	__WALNUT_SETUP_H__
-#define	__WALNUT_SETUP_H__
-
-#include <asm/ptrace.h>
-#include <asm/board.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern unsigned char	 __res[sizeof(bd_t)];
-
-extern void		 walnut_init(unsigned long r3,
-				  unsigned long ird_start,
-				  unsigned long ird_end,
-				  unsigned long cline_start,
-				  unsigned long cline_end);
-extern void		 walnut_setup_arch(void);
-extern int		 walnut_setup_residual(char *buffer);
-extern void		 walnut_init_IRQ(void);
-extern int		 walnut_get_irq(struct pt_regs *regs);
-extern void		 walnut_restart(char *cmd);
-extern void		 walnut_power_off(void);
-extern void		 walnut_halt(void);
-extern void		 walnut_time_init(void);
-extern int		 walnut_set_rtc_time(unsigned long now);
-extern unsigned long	 walnut_get_rtc_time(void);
-extern void		 walnut_calibrate_decr(void);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __WALNUT_SETUP_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/xics.c linux/arch/ppc/kernel/xics.c
--- linux.orig/arch/ppc/kernel/xics.c	2002-02-25 19:37:55.000000000 +0000
+++ linux/arch/ppc/kernel/xics.c	1970-01-01 00:00:00.000000000 +0000
@@ -1,217 +0,0 @@
-/*
- * BK Id: SCCS/s.xics.c 1.8 12/19/01 09:48:40 trini
- */
-/*
- * arch/ppc/kernel/xics.c
- *
- * Copyright 2000 IBM Corporation.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/threads.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <asm/prom.h>
-#include <asm/io.h>
-#include "i8259.h"
-#include "xics.h"
-
-void xics_enable_irq(u_int irq);
-void xics_disable_irq(u_int irq);
-void xics_mask_and_ack_irq(u_int irq);
-void xics_end_irq(u_int irq);
-
-struct hw_interrupt_type xics_pic = {
-	" XICS     ",
-	NULL,
-	NULL,
-	xics_enable_irq,
-	xics_disable_irq,
-	xics_mask_and_ack_irq,
-	xics_end_irq
-};
-
-struct hw_interrupt_type xics_8259_pic = {
-	" XICS/8259",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	xics_mask_and_ack_irq,
-	NULL
-};
-
-#define XICS_IPI		2
-#define XICS_IRQ_8259_CASCADE	0x2c
-#define XICS_IRQ_OFFSET		16
-#define XICS_IRQ_SPURIOUS	0
-
-#define DEFAULT_SERVER		0
-#define	DEFAULT_PRIORITY	0
-
-struct xics_ipl {
-	union {
-		u32	word;
-		u8	bytes[4];
-	} xirr_poll;
-	union {
-		u32 word;
-		u8	bytes[4];
-	} xirr;
-	u32	dummy;
-	union {
-		u32	word;
-		u8	bytes[4];
-	} qirr;
-};
-
-struct xics_info {
-	volatile struct xics_ipl *	per_cpu[NR_CPUS];
-};
-
-struct xics_info	xics_info;
-
-#define xirr_info(n_cpu)	(xics_info.per_cpu[n_cpu]->xirr.word)
-#define cppr_info(n_cpu)	(xics_info.per_cpu[n_cpu]->xirr.bytes[0])
-#define poll_info(n_cpu)	(xics_info.per_cpu[n_cpu]->xirr_poll.word)
-#define qirr_info(n_cpu)	(xics_info.per_cpu[n_cpu]->qirr.bytes[0])
-
-void
-xics_enable_irq(
-	u_int	irq
-	)
-{
-	int	status;
-	int	call_status;
-
-	irq -= XICS_IRQ_OFFSET;
-	if (irq == XICS_IPI)
-		return;
-	call_status = call_rtas("ibm,set-xive", 3, 1, (ulong*)&status,
-				irq, DEFAULT_SERVER, DEFAULT_PRIORITY);
-	if( call_status != 0 ) {
-		printk("xics_enable_irq: irq=%x: call_rtas failed; retn=%x, status=%x\n",
-		       irq, call_status, status);
-		return;
-	}
-}
-
-void
-xics_disable_irq(
-	u_int	irq
-	)
-{
-	int	status;
-	int	call_status;
-
-	irq -= XICS_IRQ_OFFSET;
-	call_status = call_rtas("ibm,int-off", 1, 1, (ulong*)&status, irq);
-	if( call_status != 0 ) {
-		printk("xics_disable_irq: irq=%x: call_rtas failed, retn=%x\n",
-		       irq, call_status);
-		return;
-	}
-}
-
-void
-xics_end_irq(
-	u_int	irq
-	)
-{
-	int cpu = smp_processor_id();
-
-	cppr_info(cpu) = 0; /* actually the value overwritten by ack */
-	xirr_info(cpu) = (0xff<<24) | (irq-XICS_IRQ_OFFSET);
-}
-
-void
-xics_mask_and_ack_irq(
-	u_int	irq
-	)
-{
-	int cpu = smp_processor_id();
-
-	if( irq < XICS_IRQ_OFFSET ) {
-		i8259_pic.ack(irq);
-		xirr_info(cpu) = (0xff<<24) | XICS_IRQ_8259_CASCADE;
-	}
-	else {
-		cppr_info(cpu) = 0xff;
-	}
-}
-
-int
-xics_get_irq(struct pt_regs *regs)
-{
-	u_int	cpu = smp_processor_id();
-	u_int	vec;
-	int irq;
-  
-	vec = xirr_info(cpu);
-	/*  (vec >> 24) == old priority */
-	vec &= 0x00ffffff;
-	/* for sanity, this had better be < NR_IRQS - 16 */
-	if( vec == XICS_IRQ_8259_CASCADE )
-		irq = i8259_poll();
-	else if( vec == XICS_IRQ_SPURIOUS )
-		irq = -1;
-	else
-		irq = vec + XICS_IRQ_OFFSET;
-	return irq;
-}
-
-#ifdef CONFIG_SMP
-void xics_ipi_action(int irq, void *dev_id, struct pt_regs *regs)
-{
-	qirr_info(smp_processor_id()) = 0xff;
-	smp_message_recv(MSG_RESCHEDULE, regs);
-}
-
-void xics_cause_IPI(int cpu)
-{
-	qirr_info(cpu) = 0;
-}
-
-void xics_setup_cpu(void)
-{
-	int cpu = smp_processor_id();
-
-	cppr_info(cpu) = 0xff;
-}
-#endif /* CONFIG_SMP */
-
-void
-xics_init_IRQ( void )
-{
-	int i;
-	extern unsigned long smp_chrp_cpu_nr;
-
-#ifdef CONFIG_SMP
-	for (i = 0; i < smp_chrp_cpu_nr; ++i)
-		xics_info.per_cpu[i] =
-			ioremap(0xfe000000 + smp_hw_index[i] * 0x1000, 0x20);
-#else
-	xics_info.per_cpu[0] = ioremap(0xfe000000, 0x20);
-#endif /* CONFIG_SMP */
-	xics_8259_pic.enable = i8259_pic.enable;
-	xics_8259_pic.disable = i8259_pic.disable;
-	for (i = 0; i < 16; ++i)
-		irq_desc[i].handler = &xics_8259_pic;
-	for (; i < NR_IRQS; ++i)
-		irq_desc[i].handler = &xics_pic;
-
-	cppr_info(0) = 0xff;
-	if (request_irq(XICS_IRQ_8259_CASCADE + XICS_IRQ_OFFSET, no_action,
-			0, "8259 cascade", 0))
-		printk(KERN_ERR "xics_init_IRQ: couldn't get 8259 cascade\n");
-	i8259_init();
-
-#ifdef CONFIG_SMP
-	request_irq(XICS_IPI + XICS_IRQ_OFFSET, xics_ipi_action, 0, "IPI", 0);
-#endif
-}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/kernel/xics.h linux/arch/ppc/kernel/xics.h
--- linux.orig/arch/ppc/kernel/xics.h	2001-05-22 00:04:47.000000000 +0000
+++ linux/arch/ppc/kernel/xics.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,26 +0,0 @@
-/*
- * BK Id: SCCS/s.xics.h 1.5 05/17/01 18:14:22 cort
- */
-/*
- * arch/ppc/kernel/xics.h
- *
- * Copyright 2000 IBM Corporation.
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- */
-
-#ifndef _PPC_KERNEL_XICS_H
-#define _PPC_KERNEL_XICS_H
-
-#include "local_irq.h"
-
-extern struct hw_interrupt_type xics_pic;
-extern struct hw_interrupt_type xics_8259_pic;
-
-void xics_init_IRQ(void);
-int xics_get_irq(struct pt_regs *);
-
-#endif /* _PPC_KERNEL_XICS_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/lib/checksum.S linux/arch/ppc/lib/checksum.S
--- linux.orig/arch/ppc/lib/checksum.S	2001-08-28 13:58:33.000000000 +0000
+++ linux/arch/ppc/lib/checksum.S	2002-08-12 22:14:10.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.checksum.S 1.8 08/20/01 22:09:34 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * This file contains assembly-language implementations
@@ -18,7 +18,7 @@
 #include <linux/sys.h>
 #include <asm/processor.h>
 #include <asm/errno.h>
-#include "../kernel/ppc_asm.tmpl"
+#include <asm/ppc_asm.h>
 
 	.text
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/lib/string.S linux/arch/ppc/lib/string.S
--- linux.orig/arch/ppc/lib/string.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc/lib/string.S	2002-08-12 22:14:02.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.string.S 1.11 05/21/02 21:44:32 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  * String handling functions for PowerPC.
@@ -11,11 +11,11 @@
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  */
-#include "../kernel/ppc_asm.tmpl"
 #include <linux/config.h>
 #include <asm/processor.h>
 #include <asm/cache.h>
 #include <asm/errno.h>
+#include <asm/ppc_asm.h>
 
 #define COPY_16_BYTES		\
 	lwz	r7,4(r4);	\
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/mm/hashtable.S linux/arch/ppc/mm/hashtable.S
--- linux.orig/arch/ppc/mm/hashtable.S	2001-08-28 13:58:33.000000000 +0000
+++ linux/arch/ppc/mm/hashtable.S	2002-08-12 22:14:11.000000000 +0000
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.hashtable.S 1.18 08/15/01 22:43:07 paulus
+ * BK Id: %F% %I% %G% %U% %#%
  */
 /*
  *  arch/ppc/kernel/hashtable.S
@@ -27,11 +27,13 @@
  */
 
 #include <linux/config.h>
-#include "../kernel/ppc_asm.h"
+#include <asm/ppc_asm.h>
 #include <asm/processor.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+#include <kernel/ppc_defs.h>
 
 #ifdef CONFIG_SMP
 	.comm	hash_table_lock,4
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/Makefile linux/arch/ppc/platforms/Makefile
--- linux.orig/arch/ppc/platforms/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/Makefile	2002-08-12 22:14:21.000000000 +0000
@@ -0,0 +1,53 @@
+# BK Id: SCCS/s.Makefile 1.57 09/24/01 07:45:31 trini
+#
+#
+# Makefile for the linux kernel.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definitions are now in the main makefile...
+
+USE_STANDARD_AS_RULE	:= true
+
+ifdef CONFIG_PPC64BRIDGE
+EXTRA_AFLAGS		:= -Wa,-mppc64bridge
+endif
+ifdef CONFIG_40x
+EXTRA_AFLAGS		:= -Wa,-m405
+endif
+
+# Extra CFLAGS so we don't have to do relative includes
+CFLAGS_pmac_setup.o	+= -I$(TOPDIR)/drivers/scsi -I$(TOPDIR)/fs/partitions \
+				-I$(TOPDIR)/arch/$(ARCH)/mm
+
+O_TARGET := platform.o
+
+export-objs			:= prep_setup.o
+
+obj-$(CONFIG_WALNUT)		+= walnut.o
+
+obj-$(CONFIG_APUS)		+= apus_setup.o
+ifeq ($(CONFIG_APUS),y)
+obj-$(CONFIG_PCI)		+= apus_pci.o
+endif
+
+obj-$(CONFIG_ALL_PPC)		+= pmac_pic.o pmac_setup.o pmac_time.o \
+					pmac_feature.o pmac_pci.o chrp_setup.o\
+					chrp_time.o chrp_pci.o prep_pci.o \
+					prep_time.o prep_setup.o
+ifeq ($(CONFIG_ALL_PPC),y)
+obj-$(CONFIG_NVRAM)		+= pmac_nvram.o
+endif
+obj-$(CONFIG_PMAC_BACKLIGHT)	+= pmac_backlight.o
+obj-$(CONFIG_PMAC_PBOOK)	+= sleep.o
+obj-$(CONFIG_PPC_RTAS)		+= error_log.o proc_rtas.o
+obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
+obj-$(CONFIG_GEMINI)		+= gemini_pci.o gemini_setup.o gemini_prom.o
+
+ifeq ($(CONFIG_SMP),y)
+obj-$(CONFIG_ALL_PPC)		+= pmac_smp.o chrp_smp.o
+endif
+
+include $(TOPDIR)/Rules.make
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/apus_pci.c linux/arch/ppc/platforms/apus_pci.c
--- linux.orig/arch/ppc/platforms/apus_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/apus_pci.c	2002-08-12 22:14:25.000000000 +0000
@@ -0,0 +1,187 @@
+/*
+ * BK Id: SCCS/s.apus_pci.c 1.5 09/08/01 15:47:42 paulus
+ */
+/*
+ * Copyright (C) Michel Dänzer <michdaen@iiic.ethz.ch>
+ *
+ * APUS PCI routines.
+ *
+ * Currently, only B/CVisionPPC cards (Permedia2) are supported.
+ *
+ * Thanks to Geert Uytterhoeven for the idea:
+ * Read values from given config space(s) for the first devices, -1 otherwise
+ *
+ */
+
+#include <linux/config.h>
+#ifdef CONFIG_AMIGA
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "apus_pci.h"
+
+
+/* These definitions are mostly adapted from pm2fb.c */
+
+#undef APUS_PCI_MASTER_DEBUG
+#ifdef APUS_PCI_MASTER_DEBUG
+#define DPRINTK(a,b...)	printk(KERN_DEBUG "apus_pci: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif 
+
+/*
+ * The _DEFINITIVE_ memory mapping/unmapping functions.
+ * This is due to the fact that they're changing soooo often...
+ */
+#define DEFW()		wmb()
+#define DEFR()		rmb()
+#define DEFRW()		mb()
+
+#define DEVNO(d)	((d)>>3)
+#define FNNO(d)		((d)&7)
+
+
+extern unsigned long powerup_PCI_present;
+
+static struct pci_controller *apus_hose;
+
+
+void *pci_io_base(unsigned int bus)
+{
+	return 0;
+}
+
+
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((val), (type *)(addr)); DEFW()
+#define cfg_read_bad	*val = ~0;
+#define cfg_write_bad	;
+#define cfg_read_val(val)	*val
+#define cfg_write_val(val)	val
+
+#define APUS_PCI_OP(rw, size, type, op, mask)					\
+int									\
+apus_pcibios_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
+{										\
+	int fnno = FNNO(dev->devfn);						\
+	int devno = DEVNO(dev->devfn);						\
+										\
+	if (dev->bus->number > 0 || devno != 1) {				\
+		cfg_##rw##_bad;							\
+		return PCIBIOS_DEVICE_NOT_FOUND;				\
+	}									\
+	/* base address + function offset + offset ^ endianness conversion */	\
+	cfg_##rw(val, apus_hose->cfg_data + (fnno<<5) + (offset ^ mask),	\
+		 type, op);							\
+										\
+	DPRINTK(#op " b: 0x%x, d: 0x%x, f: 0x%x, o: 0x%x, v: 0x%x\n",		\
+		dev->bus->number, dev->devfn>>3, dev->devfn&7,			\
+		offset, cfg_##rw##_val(val));					\
+	return PCIBIOS_SUCCESSFUL;						\
+}
+
+APUS_PCI_OP(read, byte, u8 *, readb, 3)
+APUS_PCI_OP(read, word, u16 *, readw, 2)
+APUS_PCI_OP(read, dword, u32 *, readl, 0)
+APUS_PCI_OP(write, byte, u8, writeb, 3)
+APUS_PCI_OP(write, word, u16, writew, 2)
+APUS_PCI_OP(write, dword, u32, writel, 0)
+
+
+static struct pci_ops apus_pci_ops = {
+	apus_pcibios_read_config_byte,
+	apus_pcibios_read_config_word,
+	apus_pcibios_read_config_dword,
+	apus_pcibios_write_config_byte,
+	apus_pcibios_write_config_word,
+	apus_pcibios_write_config_dword
+};
+
+static struct resource pci_mem = { "B/CVisionPPC PCI mem", CVPPC_FB_APERTURE_ONE, CVPPC_PCI_CONFIG, IORESOURCE_MEM };
+
+void __init
+apus_pcibios_fixup(void)
+{
+/*	struct pci_dev *dev = pci_find_slot(0, 1<<3);
+	unsigned int reg, val, offset;*/
+
+	/* FIXME: interrupt? */
+	/*dev->interrupt = xxx;*/
+
+        request_resource(&iomem_resource, &pci_mem);
+    	printk("%s: PCI mem resource requested\n", __FUNCTION__);
+}
+
+static void __init apus_pcibios_fixup_bus(struct pci_bus *bus)
+{
+        bus->resource[1] = &pci_mem;
+}
+
+
+/* 
+ * This is from pm2fb.c again
+ * 
+ * Check if PCI (B/CVisionPPC) is available, initialize it and set up
+ * the pcibios_* pointers
+ */
+
+
+void __init
+apus_setup_pci_ptrs(void)
+{
+	if (!powerup_PCI_present) {
+		DPRINTK("no PCI bridge detected\n");
+		return;
+	}
+	DPRINTK("Phase5 B/CVisionPPC PCI bridge detected.\n");
+
+	apus_hose = pcibios_alloc_controller();
+	if (!apus_hose) {
+		printk("apus_pci: Can't allocate PCI controller structure\n");
+		return;
+	}
+
+	if (!(apus_hose->cfg_data = ioremap(CVPPC_PCI_CONFIG, 256))) {
+		printk("apus_pci: unable to map PCI config region\n");
+		return;
+	}
+
+	if (!(apus_hose->cfg_addr = ioremap(CSPPC_PCI_BRIDGE, 256))) {
+		printk("apus_pci: unable to map PCI bridge\n");
+		return;
+	}
+
+	writel(CSPPCF_BRIDGE_BIG_ENDIAN, apus_hose->cfg_addr + CSPPC_BRIDGE_ENDIAN);
+	DEFW();
+
+	writel(CVPPC_REGS_REGION,  apus_hose->cfg_data+ PCI_BASE_ADDRESS_0);
+	DEFW();
+	writel(CVPPC_FB_APERTURE_ONE, apus_hose->cfg_data + PCI_BASE_ADDRESS_1);
+	DEFW();
+	writel(CVPPC_FB_APERTURE_TWO, apus_hose->cfg_data + PCI_BASE_ADDRESS_2);
+	DEFW();
+	writel(CVPPC_ROM_ADDRESS, apus_hose->cfg_data + PCI_ROM_ADDRESS);
+	DEFW();
+
+	writel(0xef000000 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+		PCI_COMMAND_MASTER, apus_hose->cfg_data + PCI_COMMAND);
+	DEFW();
+
+	apus_hose->first_busno = 0;
+	apus_hose->last_busno = 0;
+	apus_hose->ops = &apus_pci_ops;
+	ppc_md.pcibios_fixup = apus_pcibios_fixup;
+	ppc_md.pcibios_fixup_bus = apus_pcibios_fixup_bus;
+
+	return;
+}
+
+#endif /* CONFIG_AMIGA */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/apus_pci.h linux/arch/ppc/platforms/apus_pci.h
--- linux.orig/arch/ppc/platforms/apus_pci.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/apus_pci.h	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,37 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef APUS_PCI_H
+#define APUS_PCI_H
+
+
+#define CSPPC_PCI_BRIDGE		0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN		0x0000
+#define CSPPC_BRIDGE_INT		0x0010
+
+#define	CVPPC_PCI_CONFIG		0xfffc0000
+#define CVPPC_ROM_ADDRESS		0xe2000001
+#define CVPPC_REGS_REGION		0xef000000
+#define CVPPC_FB_APERTURE_ONE		0xe0000000
+#define CVPPC_FB_APERTURE_TWO		0xe1000000
+#define CVPPC_FB_SIZE			0x00800000
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN	0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2	0x01
+
+
+#endif	/* APUS_PCI_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/apus_setup.c linux/arch/ppc/platforms/apus_setup.c
--- linux.orig/arch/ppc/platforms/apus_setup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/apus_setup.c	2002-08-12 22:14:22.000000000 +0000
@@ -0,0 +1,1111 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platforms/apus_setup.c
+ *
+ *  Copyright (C) 1998, 1999  Jesper Skov
+ *
+ *  Basically what is needed to replace functionality found in
+ *  arch/m68k allowing Amiga drivers to work under APUS.
+ *  Bits of code and/or ideas from arch/m68k and arch/ppc files.
+ *
+ * TODO:
+ *  This file needs a *really* good cleanup. Restructure and optimize.
+ *  Make sure it can be compiled for non-APUS configs. Begin to move
+ *  Amiga specific stuff into mach/amiga.
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/kd.h>
+#include <linux/init.h>
+#include <linux/hdreg.h>
+#include <linux/blk.h>
+#include <linux/pci.h>
+#include <linux/seq_file.h>
+
+#ifdef CONFIG_APUS
+#include <asm/logging.h>
+#endif
+
+/* Needs INITSERIAL call in head.S! */
+#undef APUS_DEBUG
+
+
+#include <linux/ide.h>
+#define T_CHAR          (0x0000)        /* char:  don't touch  */
+#define T_SHORT         (0x4000)        /* short: 12 -> 21     */
+#define T_INT           (0x8000)        /* int:   1234 -> 4321 */
+#define T_TEXT          (0xc000)        /* text:  12 -> 21     */
+
+#define T_MASK_TYPE     (0xc000)
+#define T_MASK_COUNT    (0x3fff)
+
+#define D_CHAR(cnt)     (T_CHAR  | (cnt))
+#define D_SHORT(cnt)    (T_SHORT | (cnt))
+#define D_INT(cnt)      (T_INT   | (cnt))
+#define D_TEXT(cnt)     (T_TEXT  | (cnt))
+
+static u_short driveid_types[] = {
+        D_SHORT(10),    /* config - vendor2 */
+        D_TEXT(20),     /* serial_no */
+        D_SHORT(3),     /* buf_type, buf_size - ecc_bytes */
+        D_TEXT(48),     /* fw_rev - model */
+        D_CHAR(2),      /* max_multsect - vendor3 */
+        D_SHORT(1),     /* dword_io */
+        D_CHAR(2),      /* vendor4 - capability */
+        D_SHORT(1),     /* reserved50 */
+        D_CHAR(4),      /* vendor5 - tDMA */
+        D_SHORT(4),     /* field_valid - cur_sectors */
+        D_INT(1),       /* cur_capacity */
+        D_CHAR(2),      /* multsect - multsect_valid */
+        D_INT(1),       /* lba_capacity */
+        D_SHORT(194)    /* dma_1word - reservedyy */
+};
+
+#define num_driveid_types       (sizeof(driveid_types)/sizeof(*driveid_types))
+
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/amigappc.h>
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+
+unsigned long m68k_machtype;
+char debug_device[6] = "";
+
+extern void amiga_init_IRQ(void);
+
+void (*mach_sched_init) (void (*handler)(int, void *, struct pt_regs *)) __initdata = NULL;
+/* machine dependent keyboard functions */
+int (*mach_keyb_init) (void) __initdata = NULL;
+int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
+void (*mach_kbd_leds) (unsigned int) = NULL;
+/* machine dependent irq functions */
+void (*mach_init_IRQ) (void) __initdata = NULL;
+void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
+void (*mach_get_model) (char *model) = NULL;
+int (*mach_get_hardware_list) (char *buffer) = NULL;
+int (*mach_get_irq_list) (char *) = NULL;
+void (*mach_process_int) (int, struct pt_regs *) = NULL;
+/* machine dependent timer functions */
+unsigned long (*mach_gettimeoffset) (void);
+void (*mach_gettod) (int*, int*, int*, int*, int*, int*);
+int (*mach_hwclk) (int, struct hwclk_time*) = NULL;
+int (*mach_set_clock_mmss) (unsigned long) = NULL;
+void (*mach_reset)( void );
+long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
+#if defined(CONFIG_AMIGA_FLOPPY)
+void (*mach_floppy_setup) (char *, int *) __initdata = NULL;
+#endif
+#ifdef CONFIG_HEARTBEAT
+void (*mach_heartbeat) (int) = NULL;
+extern void apus_heartbeat (void);
+#endif
+
+extern unsigned long amiga_model;
+extern unsigned decrementer_count;/* count value for 1e6/HZ microseconds */
+extern unsigned count_period_num; /* 1 decrementer count equals */
+extern unsigned count_period_den; /* count_period_num / count_period_den us */
+
+int num_memory = 0;
+struct mem_info memory[NUM_MEMINFO];/* memory description */
+/* FIXME: Duplicate memory data to avoid conflicts with m68k shared code. */
+int m68k_realnum_memory = 0;
+struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
+
+struct mem_info ramdisk;
+
+extern void amiga_floppy_setup(char *, int *);
+extern void config_amiga(void);
+
+static int __60nsram = 0;
+
+/* for cpuinfo */
+static int __bus_speed = 0;
+static int __speed_test_failed = 0;
+
+/********************************************** COMPILE PROTECTION */
+/* Provide some stubs that links to Amiga specific functions. 
+ * This allows CONFIG_APUS to be removed from generic PPC files while
+ * preventing link errors for other PPC targets.
+ */
+unsigned long apus_get_rtc_time(void)
+{
+#ifdef CONFIG_APUS
+	extern unsigned long m68k_get_rtc_time(void);
+	
+	return m68k_get_rtc_time ();
+#else
+	return 0;
+#endif
+}
+
+int apus_set_rtc_time(unsigned long nowtime)
+{
+#ifdef CONFIG_APUS
+	extern int m68k_set_rtc_time(unsigned long nowtime);
+
+	return m68k_set_rtc_time (nowtime);
+#else
+	return 0;
+#endif
+}
+
+
+
+/* Here some functions we don't support, but which the other ports reference */
+int pckbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+	return 0; 
+}
+int pckbd_getkeycode(unsigned int scancode) 
+{ 
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+	return 0; 
+}
+int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		    char raw_mode) 
+{
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+	return 0; 
+}
+char pckbd_unexpected_up(unsigned char keycode)
+{
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+	return 0;
+}
+void pckbd_leds(unsigned char leds)
+{
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+}
+void pckbd_init_hw(void)
+{
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+}
+unsigned char pckbd_sysrq_xlate[128];
+
+struct pci_bus * __init pci_scan_peer_bridge(int bus)
+{
+	printk("Bogus call to " __FILE__ ":" __FUNCTION__ "\n");
+	return NULL;
+}
+
+/*********************************************************** SETUP */
+/* From arch/m68k/kernel/setup.c. */
+void __init apus_setup_arch(void)
+{
+#ifdef CONFIG_APUS
+	extern char cmd_line[];
+	int i;
+	char *p, *q;
+
+	/* Let m68k-shared code know it should do the Amiga thing. */
+	m68k_machtype = MACH_AMIGA;
+
+	/* Parse the command line for arch-specific options.
+	 * For the m68k, this is currently only "debug=xxx" to enable printing
+	 * certain kernel messages to some machine-specific device.  */
+	for( p = cmd_line; p && *p; ) {
+	    i = 0;
+	    if (!strncmp( p, "debug=", 6 )) {
+		    strncpy( debug_device, p+6, sizeof(debug_device)-1 );
+		    debug_device[sizeof(debug_device)-1] = 0;
+		    if ((q = strchr( debug_device, ' ' ))) *q = 0;
+		    i = 1;
+	    } else if (!strncmp( p, "60nsram", 7 )) {
+		    APUS_WRITE (APUS_REG_WAITSTATE, 
+				REGWAITSTATE_SETRESET
+				|REGWAITSTATE_PPCR
+				|REGWAITSTATE_PPCW);
+		    __60nsram = 1;
+		    i = 1;
+	    }
+
+	    if (i) {
+		/* option processed, delete it */
+		if ((q = strchr( p, ' ' )))
+		    strcpy( p, q+1 );
+		else
+		    *p = 0;
+	    } else {
+		if ((p = strchr( p, ' ' ))) ++p;
+	    }
+	}
+
+	config_amiga();
+
+#if 0 /* Enable for logging - also include logging.o in Makefile rule */
+	{
+#define LOG_SIZE 4096
+		void* base;
+
+		/* Throw away some memory - the P5 firmare stomps on top
+		 * of CHIP memory during bootup.
+		 */
+		amiga_chip_alloc(0x1000);
+
+		base = amiga_chip_alloc(LOG_SIZE+sizeof(klog_data_t));
+		LOG_INIT(base, base+sizeof(klog_data_t), LOG_SIZE);
+	}
+#endif
+#endif
+}
+
+int
+apus_show_cpuinfo(struct seq_file *m)
+{
+	extern int __map_without_bats;
+	extern unsigned long powerup_PCI_present;
+
+	seq_printf(m, "machine\t\t: Amiga\n");
+	seq_printf(m, "bus speed\t: %d%s", __bus_speed,
+		   (__speed_test_failed) ? " [failed]\n" : "\n");
+	seq_printf(m, "using BATs\t: %s\n",
+		   (__map_without_bats) ? "No" : "Yes");
+	seq_printf(m, "ram speed\t: %dns\n", (__60nsram) ? 60 : 70);
+	seq_printf(m, "PCI bridge\t: %s\n",
+		   (powerup_PCI_present) ? "Yes" : "No");
+	return 0;
+}
+
+static void get_current_tb(unsigned long long *time)
+{
+	__asm __volatile ("1:mftbu 4      \n\t"
+			  "  mftb  5      \n\t"
+			  "  mftbu 6      \n\t"
+			  "  cmpw  4,6    \n\t"
+			  "  bne   1b     \n\t"
+			  "  stw   4,0(%0)\n\t"
+			  "  stw   5,4(%0)\n\t"
+			  : 
+			  : "r" (time)
+			  : "r4", "r5", "r6");
+}
+
+
+void apus_calibrate_decr(void)
+{
+#ifdef CONFIG_APUS
+	unsigned long freq;
+
+	/* This algorithm for determining the bus speed was
+           contributed by Ralph Schmidt. */
+	unsigned long long start, stop;
+	int bus_speed;
+	int speed_test_failed = 0;
+
+	{
+		unsigned long loop = amiga_eclock / 10;
+
+		get_current_tb (&start);
+		while (loop--) {
+			unsigned char tmp;
+
+			tmp = ciaa.pra;
+		}
+		get_current_tb (&stop);
+	}
+
+	bus_speed = (((unsigned long)(stop-start))*10*4) / 1000000;
+	if (AMI_1200 == amiga_model)
+		bus_speed /= 2;
+
+	if ((bus_speed >= 47) && (bus_speed < 53)) {
+		bus_speed = 50;
+		freq = 12500000;
+	} else if ((bus_speed >= 57) && (bus_speed < 63)) {
+		bus_speed = 60;
+		freq = 15000000;
+	} else if ((bus_speed >= 63) && (bus_speed < 69)) {
+		bus_speed = 67;
+		freq = 16666667;
+	} else {
+		printk ("APUS: Unable to determine bus speed (%d). "
+			"Defaulting to 50MHz", bus_speed);
+		bus_speed = 50;
+		freq = 12500000;
+		speed_test_failed = 1;
+	}
+
+	/* Ease diagnostics... */
+	{
+		extern int __map_without_bats;
+		extern unsigned long powerup_PCI_present;
+
+		printk ("APUS: BATs=%d, BUS=%dMHz",
+			(__map_without_bats) ? 0 : 1,
+			bus_speed);
+		if (speed_test_failed)
+			printk ("[FAILED - please report]");
+
+		printk (", RAM=%dns, PCI bridge=%d\n",
+			(__60nsram) ? 60 : 70,
+			(powerup_PCI_present) ? 1 : 0);
+
+		/* print a bit more if asked politely... */
+		if (!(ciaa.pra & 0x40)){
+			extern unsigned int bat_addrs[4][3];
+			int b;
+			for (b = 0; b < 4; ++b) {
+				printk ("APUS: BAT%d ", b);
+				printk ("%08x-%08x -> %08x\n",
+					bat_addrs[b][0],
+					bat_addrs[b][1],
+					bat_addrs[b][2]);
+			}
+		}
+
+	}
+
+        printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+	       freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+
+	__bus_speed = bus_speed;
+	__speed_test_failed = speed_test_failed;
+#endif
+}
+
+void arch_gettod(int *year, int *mon, int *day, int *hour,
+		 int *min, int *sec)
+{
+#ifdef CONFIG_APUS
+	if (mach_gettod)
+		mach_gettod(year, mon, day, hour, min, sec);
+	else
+		*year = *mon = *day = *hour = *min = *sec = 0;
+#endif
+}
+
+/* for "kbd-reset" cmdline param */
+__init
+void kbd_reset_setup(char *str, int *ints)
+{
+}
+
+/*********************************************************** FLOPPY */
+#if defined(CONFIG_AMIGA_FLOPPY)
+__init 
+void floppy_setup(char *str, int *ints)
+{
+	if (mach_floppy_setup)
+		mach_floppy_setup (str, ints);
+}
+#endif
+
+/*********************************************************** MEMORY */
+#define KMAP_MAX 32
+unsigned long kmap_chunks[KMAP_MAX*3];
+int kmap_chunk_count = 0;
+
+/* From pgtable.h */
+static __inline__ pte_t *my_find_pte(struct mm_struct *mm,unsigned long va)
+{
+	pgd_t *dir = 0;
+	pmd_t *pmd = 0;
+	pte_t *pte = 0;
+
+	va &= PAGE_MASK;
+	
+	dir = pgd_offset( mm, va );
+	if (dir)
+	{
+		pmd = pmd_offset(dir, va & PAGE_MASK);
+		if (pmd && pmd_present(*pmd))
+		{
+			pte = pte_offset(pmd, va);
+		}
+	}
+	return pte;
+}
+
+
+/* Again simulating an m68k/mm/kmap.c function. */
+void kernel_set_cachemode( unsigned long address, unsigned long size,
+			   unsigned int cmode )
+{
+	unsigned long mask, flags;
+
+	switch (cmode)
+	{
+	case IOMAP_FULL_CACHING:
+		mask = ~(_PAGE_NO_CACHE | _PAGE_GUARDED);
+		flags = 0;
+		break;
+	case IOMAP_NOCACHE_SER:
+		mask = ~0;
+		flags = (_PAGE_NO_CACHE | _PAGE_GUARDED);
+		break;
+	default:
+		panic ("kernel_set_cachemode() doesn't support mode %d\n", 
+		       cmode);
+		break;
+	}
+	
+	size /= PAGE_SIZE;
+	address &= PAGE_MASK;
+	while (size--)
+	{
+		pte_t *pte;
+
+		pte = my_find_pte(&init_mm, address);
+		if ( !pte )
+		{
+			printk("pte NULL in kernel_set_cachemode()\n");
+			return;
+		}
+
+                pte_val (*pte) &= mask;
+                pte_val (*pte) |= flags;
+                flush_tlb_page(find_vma(&init_mm,address),address);
+
+		address += PAGE_SIZE;
+	}
+}
+
+unsigned long mm_ptov (unsigned long paddr)
+{
+	unsigned long ret;
+	if (paddr < 16*1024*1024)
+		ret = ZTWO_VADDR(paddr);
+	else {
+		int i;
+
+		for (i = 0; i < kmap_chunk_count;){
+			unsigned long phys = kmap_chunks[i++];
+			unsigned long size = kmap_chunks[i++];
+			unsigned long virt = kmap_chunks[i++];
+			if (paddr >= phys
+			    && paddr < (phys + size)){
+				ret = virt + paddr - phys;
+				goto exit;
+			}
+		}
+		
+		ret = (unsigned long) __va(paddr);
+	}
+exit:
+#ifdef DEBUGPV
+	printk ("PTOV(%lx)=%lx\n", paddr, ret);
+#endif
+	return ret;
+}
+
+int mm_end_of_chunk (unsigned long addr, int len)
+{
+	if (memory[0].addr + memory[0].size == addr + len)
+		return 1;
+	return 0;
+}
+
+/*********************************************************** CACHE */
+
+#define L1_CACHE_BYTES 32
+#define MAX_CACHE_SIZE 8192
+void cache_push(__u32 addr, int length)
+{
+	addr = mm_ptov(addr);
+
+	if (MAX_CACHE_SIZE < length)
+		length = MAX_CACHE_SIZE;
+
+	while(length > 0){
+		__asm ("dcbf 0,%0\n\t"
+		       : : "r" (addr));
+		addr += L1_CACHE_BYTES;
+		length -= L1_CACHE_BYTES;
+	}
+	/* Also flush trailing block */
+	__asm ("dcbf 0,%0\n\t"
+	       "sync \n\t"
+	       : : "r" (addr));
+}
+
+void cache_clear(__u32 addr, int length)
+{
+	if (MAX_CACHE_SIZE < length)
+		length = MAX_CACHE_SIZE;
+
+	addr = mm_ptov(addr);
+
+	__asm ("dcbf 0,%0\n\t"
+	       "sync \n\t"
+	       "icbi 0,%0 \n\t"
+	       "isync \n\t"
+	       : : "r" (addr));
+	
+	addr += L1_CACHE_BYTES;
+	length -= L1_CACHE_BYTES;
+
+	while(length > 0){
+		__asm ("dcbf 0,%0\n\t"
+		       "sync \n\t"
+		       "icbi 0,%0 \n\t"
+		       "isync \n\t"
+		       : : "r" (addr));
+		addr += L1_CACHE_BYTES;
+		length -= L1_CACHE_BYTES;
+	}
+
+	__asm ("dcbf 0,%0\n\t"
+	       "sync \n\t"
+	       "icbi 0,%0 \n\t"
+	       "isync \n\t"
+	       : : "r" (addr));
+}
+
+/****************************************************** from setup.c */
+void
+apus_restart(char *cmd)
+{
+	cli();
+
+	APUS_WRITE(APUS_REG_LOCK, 
+		   REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK2);
+	APUS_WRITE(APUS_REG_LOCK, 
+		   REGLOCK_BLACKMAGICK1|REGLOCK_BLACKMAGICK3);
+	APUS_WRITE(APUS_REG_LOCK, 
+		   REGLOCK_BLACKMAGICK2|REGLOCK_BLACKMAGICK3);
+	APUS_WRITE(APUS_REG_SHADOW, REGSHADOW_SELFRESET);
+	APUS_WRITE(APUS_REG_RESET, REGRESET_AMIGARESET);
+	for(;;);
+}
+
+void
+apus_power_off(void)
+{
+	for (;;);
+}
+
+void
+apus_halt(void)
+{
+   apus_restart(NULL);
+}
+
+/****************************************************** from setup.c/IDE */
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+
+#if 0	/* no longer used  -- paulus */
+void
+apus_ide_fix_driveid(struct hd_driveid *id)
+{
+   u_char *p = (u_char *)id;
+   int i, j, cnt;
+   u_char t;
+
+   if (!MACH_IS_AMIGA && !MACH_IS_MAC)
+   	return;
+   for (i = 0; i < num_driveid_types; i++) {
+      cnt = driveid_types[i] & T_MASK_COUNT;
+      switch (driveid_types[i] & T_MASK_TYPE) {
+         case T_CHAR:
+            p += cnt;
+            break;
+         case T_SHORT:
+            for (j = 0; j < cnt; j++) {
+               t = p[0];
+               p[0] = p[1];
+               p[1] = t;
+               p += 2;
+            }
+            break;
+         case T_INT:
+            for (j = 0; j < cnt; j++) {
+               t = p[0];
+               p[0] = p[3];
+               p[3] = t;
+               t = p[1];
+               p[1] = p[2];
+               p[2] = t;
+               p += 4;
+            }
+            break;
+         case T_TEXT:
+            for (j = 0; j < cnt; j += 2) {
+               t = p[0];
+               p[0] = p[1];
+               p[1] = t;
+               p += 2;
+            }
+            break;
+      }
+   }
+}
+#endif /* 0 */
+
+__init
+void apus_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, 
+			       ide_ioreg_t ctrl_port, int *irq)
+{
+        if (data_port || ctrl_port)
+                printk("apus_ide_init_hwif_ports: must not be called\n");
+}
+#endif
+/****************************************************** IRQ stuff */
+
+static unsigned int apus_irq_cannonicalize(unsigned int irq)
+{
+	return irq;
+}
+
+int apus_get_irq_list(char *buf)
+{
+#ifdef CONFIG_APUS
+	extern int amiga_get_irq_list(char *buf);
+	
+	return amiga_get_irq_list (buf);
+#else
+	return 0;
+#endif
+}
+
+/* IPL must be between 0 and 7 */
+static inline void apus_set_IPL(unsigned long ipl)
+{
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | IPLEMU_DISABLEINT);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_IPLMASK);
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_SETRESET | ((~ipl) & IPLEMU_IPLMASK));
+	APUS_WRITE(APUS_IPL_EMU, IPLEMU_DISABLEINT);
+}
+
+static inline unsigned long apus_get_IPL(void)
+{
+	/* This returns the present IPL emulation level. */
+	unsigned long __f;
+	APUS_READ(APUS_IPL_EMU, __f);
+	return ((~__f) & IPLEMU_IPLMASK);
+}
+
+static inline unsigned long apus_get_prev_IPL(struct pt_regs* regs)
+{
+	/* The value saved in mq is the IPL_EMU value at the time of
+	   interrupt. The lower bits are the current interrupt level,
+	   the upper bits the requested level. Thus, to restore the
+	   IPL level to the post-interrupt state, we will need to use
+	   the lower bits. */
+	unsigned long __f = regs->mq;
+	return ((~__f) & IPLEMU_IPLMASK);
+}
+
+
+#ifdef CONFIG_APUS
+void free_irq(unsigned int irq, void *dev_id)
+{
+	extern void amiga_free_irq(unsigned int irq, void *dev_id);
+
+	amiga_free_irq (irq, dev_id);
+}
+
+int request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+	unsigned long irqflags, const char * devname, void *dev_id)
+{
+	extern int  amiga_request_irq(unsigned int irq, 
+				      void (*handler)(int, void *, 
+						      struct pt_regs *),
+				      unsigned long flags, 
+				      const char *devname, 
+				      void *dev_id);
+
+	return amiga_request_irq (irq, handler, irqflags, devname, dev_id);
+}
+
+/* In Linux/m68k the sys_request_irq deals with vectors 0-7. That's what
+   callers expect - but on Linux/APUS we actually use the IRQ_AMIGA_AUTO
+   vectors (24-31), so we put this dummy function in between to adjust
+   the vector argument (rather have cruft here than in the generic irq.c). */
+int sys_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
+		    unsigned long irqflags, const char * devname, void *dev_id)
+{
+	extern int request_sysirq(unsigned int irq, 
+				  void (*handler)(int, void *, 
+						  struct pt_regs *),
+				  unsigned long irqflags,
+				  const char * devname, void *dev_id);
+	return request_sysirq(irq+IRQ_AMIGA_AUTO, handler, irqflags, 
+			      devname, dev_id);
+}
+#endif
+
+int apus_get_irq(struct pt_regs* regs)
+{
+#ifdef CONFIG_APUS
+	int level = apus_get_IPL();
+
+#ifdef __INTERRUPT_DEBUG
+	printk("<%d:%d>", level, apus_get_prev_IPL(regs));
+#endif
+
+	if (0 == level)
+		return -8;
+	if (7 == level)
+		return -9;
+
+	return level + IRQ_AMIGA_AUTO;
+#else
+	return 0;
+#endif
+}
+
+void apus_post_irq(struct pt_regs* regs, int level)
+{
+#ifdef __INTERRUPT_DEBUG
+	printk("{%d}", apus_get_prev_IPL(regs));
+#endif
+	/* Restore IPL to the previous value */
+	apus_set_IPL(apus_get_prev_IPL(regs));
+}
+
+/****************************************************** keyboard */
+static int apus_kbd_setkeycode(unsigned int scancode, unsigned int keycode)
+{
+	return -EOPNOTSUPP;
+}
+
+static int apus_kbd_getkeycode(unsigned int scancode)
+{
+	return scancode > 127 ? -EINVAL : scancode;
+}
+
+static int apus_kbd_translate(unsigned char keycode, unsigned char *keycodep,
+			      char raw_mode)
+{
+	*keycodep = keycode;
+	return 1;
+}
+
+static char apus_kbd_unexpected_up(unsigned char keycode)
+{
+	return 0200;
+}
+
+static void apus_kbd_leds(unsigned char leds)
+{
+}
+
+static void apus_kbd_init_hw(void)
+{
+#ifdef CONFIG_APUS
+	extern int amiga_keyb_init(void);
+
+	amiga_keyb_init();
+#endif
+}
+
+
+/****************************************************** debugging */
+
+/* some serial hardware definitions */
+#define SDR_OVRUN   (1<<15)
+#define SDR_RBF     (1<<14)
+#define SDR_TBE     (1<<13)
+#define SDR_TSRE    (1<<12)
+
+#define AC_SETCLR   (1<<15)
+#define AC_UARTBRK  (1<<11)
+
+#define SER_DTR     (1<<7)
+#define SER_RTS     (1<<6)
+#define SER_DCD     (1<<5)
+#define SER_CTS     (1<<4)
+#define SER_DSR     (1<<3)
+
+static __inline__ void ser_RTSon(void)
+{
+    ciab.pra &= ~SER_RTS; /* active low */
+}
+
+int __debug_ser_out( unsigned char c )
+{
+	custom.serdat = c | 0x100;
+	mb();
+	while (!(custom.serdatr & 0x2000))
+		barrier();
+	return 1;
+}
+
+unsigned char __debug_ser_in( void )
+{
+	unsigned char c;
+
+	/* XXX: is that ok?? derived from amiga_ser.c... */
+	while( !(custom.intreqr & IF_RBF) )
+		barrier();
+	c = custom.serdatr;
+	/* clear the interrupt, so that another character can be read */
+	custom.intreq = IF_RBF;
+	return c;
+}
+
+int __debug_serinit( void )
+{	
+	unsigned long flags;
+	
+	save_flags (flags);
+	cli();
+
+	/* turn off Rx and Tx interrupts */
+	custom.intena = IF_RBF | IF_TBE;
+
+	/* clear any pending interrupt */
+	custom.intreq = IF_RBF | IF_TBE;
+
+	restore_flags (flags);
+
+	/*
+	 * set the appropriate directions for the modem control flags,
+	 * and clear RTS and DTR
+	 */
+	ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
+	ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
+	
+#ifdef CONFIG_KGDB
+	/* turn Rx interrupts on for GDB */
+	custom.intena = IF_SETCLR | IF_RBF;
+	ser_RTSon();
+#endif
+
+	return 0;
+}
+
+void __debug_print_hex(unsigned long x)
+{
+	int i;
+	char hexchars[] = "0123456789ABCDEF";
+
+	for (i = 0; i < 8; i++) {
+		__debug_ser_out(hexchars[(x >> 28) & 15]);
+		x <<= 4;
+	}
+	__debug_ser_out('\n');
+	__debug_ser_out('\r');
+}
+
+void __debug_print_string(char* s)
+{
+	unsigned char c;
+	while((c = *s++))
+		__debug_ser_out(c);
+	__debug_ser_out('\n');
+	__debug_ser_out('\r');
+}
+
+static void apus_progress(char *s, unsigned short value)
+{
+	__debug_print_string(s);
+}
+
+/****************************************************** init */
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+#define NUM_IRQ_NODES 100
+static irq_node_t nodes[NUM_IRQ_NODES];
+
+extern void (*amiga_default_handler[AUTO_IRQS])(int, void *, struct pt_regs *);
+
+static const char *default_names[SYS_IRQS] = {
+	"spurious int", "int1 handler", "int2 handler", "int3 handler",
+	"int4 handler", "int5 handler", "int6 handler", "int7 handler"
+};
+
+irq_node_t *new_irq_node(void)
+{
+	irq_node_t *node;
+	short i;
+
+	for (node = nodes, i = NUM_IRQ_NODES-1; i >= 0; node++, i--)
+		if (!node->handler)
+			return node;
+
+	printk ("new_irq_node: out of nodes\n");
+	return NULL;
+}
+
+extern void amiga_enable_irq(unsigned int irq);
+extern void amiga_disable_irq(unsigned int irq);
+
+struct hw_interrupt_type amiga_irqctrl = {
+	" Amiga  ",
+	NULL,
+	NULL,
+	amiga_enable_irq,
+	amiga_disable_irq,
+	0,
+	0
+};
+
+#define HARDWARE_MAPPED_SIZE (512*1024)
+unsigned long __init apus_find_end_of_memory(void)
+{
+	int shadow = 0;
+	unsigned long total;
+
+	/* The memory size reported by ADOS excludes the 512KB
+	   reserved for PPC exception registers and possibly 512KB
+	   containing a shadow of the ADOS ROM. */
+	{
+		unsigned long size = memory[0].size;
+
+		/* If 2MB aligned, size was probably user
+                   specified. We can't tell anything about shadowing
+                   in this case so skip shadow assignment. */
+		if (0 != (size & 0x1fffff)){
+			/* Align to 512KB to ensure correct handling
+			   of both memfile and system specified
+			   sizes. */
+			size = ((size+0x0007ffff) & 0xfff80000);
+			/* If memory is 1MB aligned, assume
+                           shadowing. */
+			shadow = !(size & 0x80000);
+		}
+
+		/* Add the chunk that ADOS does not see. by aligning
+                   the size to the nearest 2MB limit upwards.  */
+		memory[0].size = ((size+0x001fffff) & 0xffe00000);
+	}
+
+	total = memory[0].size;
+
+	/* Remove the memory chunks that are controlled by special
+           Phase5 hardware. */
+
+	/* Remove the upper 512KB if it contains a shadow of
+	   the ADOS ROM. FIXME: It might be possible to
+	   disable this shadow HW. Check the booter
+	   (ppc_boot.c) */
+	if (shadow)
+		total -= HARDWARE_MAPPED_SIZE;
+
+	/* Remove the upper 512KB where the PPC exception
+	   vectors are mapped. */
+	total -= HARDWARE_MAPPED_SIZE;
+
+	/* Linux/APUS only handles one block of memory -- the one on
+	   the PowerUP board. Other system memory is horrible slow in
+	   comparison. The user can use other memory for swapping
+	   using the z2ram device. */
+	ram_phys_base = memory[0].addr;
+	return total;
+}
+
+static void __init
+apus_map_io(void)
+{
+	/* Map PPC exception vectors. */
+	io_block_mapping(0xfff00000, 0xfff00000, 0x00020000, _PAGE_KERNEL);
+	/* Map chip and ZorroII memory */
+	io_block_mapping(zTwoBase,   0x00000000, 0x01000000, _PAGE_IO);
+}
+
+__init
+void apus_init_IRQ(void)
+{
+	int i;
+
+	for ( i = 0 ; i < NR_IRQS ; i++ )
+		irq_desc[i].handler = &amiga_irqctrl;
+
+	for (i = 0; i < NUM_IRQ_NODES; i++)
+		nodes[i].handler = NULL;
+
+	for (i = 0; i < AUTO_IRQS; i++) {
+		if (amiga_default_handler[i] != NULL)
+			sys_request_irq(i, amiga_default_handler[i],
+					0, default_names[i], NULL);
+	}
+
+	amiga_init_IRQ();
+
+}
+
+__init
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		   unsigned long r6, unsigned long r7)
+{
+	extern int parse_bootinfo(const struct bi_record *);
+	extern char _end[];
+	
+	/* Parse bootinfo. The bootinfo is located right after
+           the kernel bss */
+	parse_bootinfo((const struct bi_record *)&_end);
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* Take care of initrd if we have one. Use data from
+	   bootinfo to avoid the need to initialize PPC
+	   registers when kernel is booted via a PPC reset. */
+	if ( ramdisk.addr ) {
+		initrd_start = (unsigned long) __va(ramdisk.addr);
+		initrd_end = (unsigned long) 
+			__va(ramdisk.size + ramdisk.addr);
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+
+	ppc_md.setup_arch     = apus_setup_arch;
+	ppc_md.show_cpuinfo   = apus_show_cpuinfo;
+	ppc_md.irq_cannonicalize = apus_irq_cannonicalize;
+	ppc_md.init_IRQ       = apus_init_IRQ;
+	ppc_md.get_irq        = apus_get_irq;
+	
+#error Should use the ->end() member of irq_desc[x]. -- Cort
+	/*ppc_md.post_irq       = apus_post_irq;*/
+	
+#ifdef CONFIG_HEARTBEAT
+	ppc_md.heartbeat      = apus_heartbeat;
+	ppc_md.heartbeat_count = 1;
+#endif
+#ifdef APUS_DEBUG
+	__debug_serinit();
+	ppc_md.progress       = apus_progress;
+#endif
+	ppc_md.init           = NULL;
+
+	ppc_md.restart        = apus_restart;
+	ppc_md.power_off      = apus_power_off;
+	ppc_md.halt           = apus_halt;
+
+	ppc_md.time_init      = NULL;
+	ppc_md.set_rtc_time   = apus_set_rtc_time;
+	ppc_md.get_rtc_time   = apus_get_rtc_time;
+	ppc_md.calibrate_decr = apus_calibrate_decr;
+
+	ppc_md.find_end_of_memory = apus_find_end_of_memory;
+	ppc_md.setup_io_mappings = apus_map_io;
+
+	ppc_md.nvram_read_val = NULL;
+	ppc_md.nvram_write_val = NULL;
+
+	/* These should not be used for the APUS yet, since it uses
+	   the M68K keyboard now. */
+	ppc_md.kbd_setkeycode    = apus_kbd_setkeycode;
+	ppc_md.kbd_getkeycode    = apus_kbd_getkeycode;
+	ppc_md.kbd_translate     = apus_kbd_translate;
+	ppc_md.kbd_unexpected_up = apus_kbd_unexpected_up;
+	ppc_md.kbd_leds          = apus_kbd_leds;
+	ppc_md.kbd_init_hw       = apus_kbd_init_hw;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+        ppc_ide_md.ide_init_hwif = apus_ide_init_hwif_ports;
+#endif		
+}
+
+
+/*************************************************** coexistence */
+void __init adbdev_init(void)
+{
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/bseip.h linux/arch/ppc/platforms/bseip.h
--- linux.orig/arch/ppc/platforms/bseip.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/bseip.h	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,42 @@
+/*
+ * BK Id: SCCS/s.bseip.h 1.10 08/17/01 15:23:17 paulus
+ */
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Bright Star Engineering ip-Engine board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_BSEIP_DEFS
+#define __MACH_BSEIP_DEFS
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * All we need to get started is the IMMR.
+ */
+#define IMAP_ADDR		((uint)0xff000000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0x04000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#endif	/* !__ASSEMBLY__ */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/chrp_pci.c linux/arch/ppc/platforms/chrp_pci.c
--- linux.orig/arch/ppc/platforms/chrp_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/chrp_pci.c	2002-08-12 22:14:27.000000000 +0000
@@ -0,0 +1,328 @@
+/*
+ * BK Id: SCCS/s.chrp_pci.c 1.22 09/08/01 15:47:42 paulus
+ */
+/*
+ * CHRP pci routines.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/ide.h>
+#include <linux/bootmem.h>
+
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/machdep.h>
+#include <asm/sections.h>
+#include <asm/pci-bridge.h>
+#include <asm/open_pic.h>
+
+/* LongTrail */
+unsigned long gg2_pci_config_base;
+
+#define pci_config_addr(dev, offset) \
+(gg2_pci_config_base | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
+
+volatile struct Hydra *Hydra = NULL;
+
+/*
+ * The VLSI Golden Gate II has only 512K of PCI configuration space, so we
+ * limit the bus number to 3 bits
+ */
+
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
+
+#define cfg_read_bad(val, size)		*val = bad_##size;
+#define cfg_write_bad(val, size)
+
+#define bad_byte	0xff
+#define bad_word	0xffff
+#define bad_dword	0xffffffffU
+
+#define GG2_PCI_OP(rw, size, type, op)					    \
+int __chrp gg2_##rw##_config_##size(struct pci_dev *dev, int off, type val) \
+{									    \
+	if (dev->bus->number > 7) {					    \
+		cfg_##rw##_bad(val, size)				    \
+		return PCIBIOS_DEVICE_NOT_FOUND;			    \
+	}								    \
+	cfg_##rw(val, pci_config_addr(dev, off), type, op);		    \
+	return PCIBIOS_SUCCESSFUL;					    \
+}
+
+GG2_PCI_OP(read, byte, u8 *, in_8)
+GG2_PCI_OP(read, word, u16 *, in_le16)
+GG2_PCI_OP(read, dword, u32 *, in_le32)
+GG2_PCI_OP(write, byte, u8, out_8)
+GG2_PCI_OP(write, word, u16, out_le16)
+GG2_PCI_OP(write, dword, u32, out_le32)
+
+static struct pci_ops gg2_pci_ops =
+{
+	gg2_read_config_byte,
+	gg2_read_config_word,
+	gg2_read_config_dword,
+	gg2_write_config_byte,
+	gg2_write_config_word,
+	gg2_write_config_dword
+};
+
+/*
+ * Access functions for PCI config space on IBM "python" host bridges.
+ */
+#define PYTHON_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
+				 | (((o) & ~3) << 24))
+
+#define PYTHON_PCI_OP(rw, size, type, op, mask)			    	     \
+int __chrp								     \
+python_##rw##_config_##size(struct pci_dev *dev, int offset, type val) 	     \
+{									     \
+	struct pci_controller *hose = dev->sysdata;			     \
+									     \
+	out_be32(hose->cfg_addr,					     \
+		 PYTHON_CFA(dev->bus->number, dev->devfn, offset));	     \
+	cfg_##rw(val, hose->cfg_data + (offset & mask), type, op);   	     \
+	return PCIBIOS_SUCCESSFUL;					     \
+}
+
+PYTHON_PCI_OP(read, byte, u8 *, in_8, 3)
+PYTHON_PCI_OP(read, word, u16 *, in_le16, 2)
+PYTHON_PCI_OP(read, dword, u32 *, in_le32, 0)
+PYTHON_PCI_OP(write, byte, u8, out_8, 3)
+PYTHON_PCI_OP(write, word, u16, out_le16, 2)
+PYTHON_PCI_OP(write, dword, u32, out_le32, 0)
+
+static struct pci_ops python_pci_ops =
+{
+	python_read_config_byte,
+	python_read_config_word,
+	python_read_config_dword,
+	python_write_config_byte,
+	python_write_config_word,
+	python_write_config_dword
+};
+
+/*
+ * Access functions for PCI config space using RTAS calls.
+ */
+#define RTAS_PCI_READ_OP(size, type, nbytes)			    	  \
+int __chrp								  \
+rtas_read_config_##size(struct pci_dev *dev, int offset, type val) 	  \
+{									  \
+	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
+		| ((dev->bus->number & 0xff) << 16);			  \
+	unsigned long ret = ~0UL;					  \
+	int rval;							  \
+									  \
+	rval = call_rtas("read-pci-config", 2, 2, &ret, addr, nbytes);	  \
+	*val = ret;							  \
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;    	  \
+}
+
+#define RTAS_PCI_WRITE_OP(size, type, nbytes)				  \
+int __chrp								  \
+rtas_write_config_##size(struct pci_dev *dev, int offset, type val)	  \
+{									  \
+	unsigned long addr = (offset & 0xff) | ((dev->devfn & 0xff) << 8) \
+		| ((dev->bus->number & 0xff) << 16);			  \
+	int rval;							  \
+									  \
+	rval = call_rtas("write-pci-config", 3, 1, NULL,		  \
+			 addr, nbytes, (ulong)val);			  \
+	return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL;	  \
+}
+
+RTAS_PCI_READ_OP(byte, u8 *, 1)
+RTAS_PCI_READ_OP(word, u16 *, 2)
+RTAS_PCI_READ_OP(dword, u32 *, 4)
+RTAS_PCI_WRITE_OP(byte, u8, 1)
+RTAS_PCI_WRITE_OP(word, u16, 2)
+RTAS_PCI_WRITE_OP(dword, u32, 4)
+
+static struct pci_ops rtas_pci_ops =
+{
+	rtas_read_config_byte,
+	rtas_read_config_word,
+	rtas_read_config_dword,
+	rtas_write_config_byte,
+	rtas_write_config_word,
+	rtas_write_config_dword
+};
+
+    /*
+     *  Temporary fixes for PCI devices. These should be replaced by OF query
+     *  code -- Geert
+     */
+
+static u_char hydra_openpic_initsenses[] __initdata = {
+    1,	/* HYDRA_INT_SIO */
+    0,	/* HYDRA_INT_SCSI_DMA */
+    0,	/* HYDRA_INT_SCCA_TX_DMA */
+    0,	/* HYDRA_INT_SCCA_RX_DMA */
+    0,	/* HYDRA_INT_SCCB_TX_DMA */
+    0,	/* HYDRA_INT_SCCB_RX_DMA */
+    1,	/* HYDRA_INT_SCSI */
+    1,	/* HYDRA_INT_SCCA */
+    1,	/* HYDRA_INT_SCCB */
+    1,	/* HYDRA_INT_VIA */
+    1,	/* HYDRA_INT_ADB */
+    0,	/* HYDRA_INT_ADB_NMI */
+    	/* all others are 1 (= default) */
+};
+
+int __init
+hydra_init(void)
+{
+	struct device_node *np;
+
+	np = find_devices("mac-io");
+	if (np == NULL || np->n_addrs == 0) {
+		printk(KERN_WARNING "Warning: no mac-io found\n");
+		return 0;
+	}
+	Hydra = ioremap(np->addrs[0].address, np->addrs[0].size);
+	printk("Hydra Mac I/O at %x\n", np->addrs[0].address);
+	out_le32(&Hydra->Feature_Control, (HYDRA_FC_SCC_CELL_EN |
+					   HYDRA_FC_SCSI_CELL_EN |
+					   HYDRA_FC_SCCA_ENABLE |
+					   HYDRA_FC_SCCB_ENABLE |
+					   HYDRA_FC_ARB_BYPASS |
+					   HYDRA_FC_MPIC_ENABLE |
+					   HYDRA_FC_SLOW_SCC_PCLK |
+					   HYDRA_FC_MPIC_IS_MASTER));
+	OpenPIC_Addr = &Hydra->OpenPIC;
+	OpenPIC_InitSenses = hydra_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(hydra_openpic_initsenses);
+	return 1;
+}
+
+void __init
+chrp_pcibios_fixup(void)
+{
+	struct pci_dev *dev;
+	struct device_node *np;
+
+	/* PCI interrupts are controlled by the OpenPIC */
+	pci_for_each_dev(dev) {
+		np = pci_device_to_OF_node(dev);
+		if ((np != 0) && (np->n_intrs > 0) && (np->intrs[0].line != 0))
+			dev->irq = np->intrs[0].line;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+void __init
+chrp_find_bridges(void)
+{
+	struct device_node *dev;
+	int *bus_range;
+	int len, index = -1;
+	struct pci_controller *hose;
+	volatile unsigned char *cfg;
+	unsigned int *dma;
+	char *model, *machine;
+	int is_longtrail = 0, is_mot = 0;
+	struct device_node *root = find_path_device("/");
+#ifdef CONFIG_POWER3
+	unsigned int *opprop = (unsigned int *)
+		get_property(root, "platform-open-pic", NULL);
+	int i;
+#endif
+
+	/*
+	 * The PCI host bridge nodes on some machines don't have
+	 * properties to adequately identify them, so we have to
+	 * look at what sort of machine this is as well.
+	 */
+	machine = get_property(root, "model", NULL);
+	if (machine != NULL) {
+		is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0;
+		is_mot = strncmp(machine, "MOT", 3) == 0;
+	}
+	for (dev = root->child; dev != NULL; dev = dev->sibling) {
+		if (dev->type == NULL || strcmp(dev->type, "pci") != 0)
+			continue;
+		++index;
+		/* The GG2 bridge on the LongTrail doesn't have an address */
+		if (dev->n_addrs < 1 && !is_longtrail) {
+			printk(KERN_WARNING "Can't use %s: no address\n",
+			       dev->full_name);
+			continue;
+		}
+		bus_range = (int *) get_property(dev, "bus-range", &len);
+		if (bus_range == NULL || len < 2 * sizeof(int)) {
+			printk(KERN_WARNING "Can't get bus-range for %s\n",
+				dev->full_name);
+			continue;
+		}
+		if (bus_range[1] == bus_range[0])
+			printk(KERN_INFO "PCI bus %d", bus_range[0]);
+		else
+			printk(KERN_INFO "PCI buses %d..%d",
+			       bus_range[0], bus_range[1]);
+		printk(" controlled by %s", dev->type);
+		if (dev->n_addrs > 0)
+			printk(" at %x", dev->addrs[0].address);
+		printk("\n");
+
+		hose = pcibios_alloc_controller();
+		if (!hose) {
+			printk("Can't allocate PCI controller structure for %s\n",
+				dev->full_name);
+			continue;
+		}
+		hose->arch_data = dev;
+		hose->first_busno = bus_range[0];
+		hose->last_busno = bus_range[1];
+
+		model = get_property(dev, "model", NULL);
+		if (model == NULL)
+			model = "<none>";
+		if (device_is_compatible(dev, "IBM,python")) {
+			hose->ops = &python_pci_ops;
+			cfg = ioremap(dev->addrs[0].address + 0xf8000, 0x20);
+			hose->cfg_addr = (volatile unsigned int *) cfg;
+			hose->cfg_data = cfg + 0x10;
+		} else if (is_mot
+			   || strncmp(model, "Motorola, Grackle", 17) == 0) {
+			setup_grackle(hose);
+		} else if (is_longtrail) {
+			hose->ops = &gg2_pci_ops;
+			gg2_pci_config_base = (unsigned long)
+				ioremap(GG2_PCI_CONFIG_BASE, 0x80000);
+		} else {
+			printk("No methods for %s (model %s), using RTAS\n",
+			       dev->full_name, model);
+			hose->ops = &rtas_pci_ops;
+		}
+
+		pci_process_bridge_OF_ranges(hose, dev, index == 0);
+
+#ifdef CONFIG_POWER3
+		if (opprop != NULL) {
+			i = prom_n_addr_cells(root) * (index + 2) - 1;
+			openpic_setup_ISU(index, opprop[i]);
+		}
+#endif /* CONFIG_POWER3 */
+
+		/* check the first bridge for a property that we can
+		   use to set pci_dram_offset */
+		dma = (unsigned int *)
+			get_property(dev, "ibm,dma-ranges", &len);
+		if (index == 0 && dma != NULL && len >= 6 * sizeof(*dma)) {
+			pci_dram_offset = dma[2] - dma[3];
+			printk("pci_dram_offset = %lx\n", pci_dram_offset);
+		}
+	}
+
+	ppc_md.pcibios_fixup = chrp_pcibios_fixup;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/chrp_setup.c linux/arch/ppc/platforms/chrp_setup.c
--- linux.orig/arch/ppc/platforms/chrp_setup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/chrp_setup.c	2002-08-12 22:14:11.000000000 +0000
@@ -0,0 +1,632 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platforms/setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ */
+
+/*
+ * 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/slab.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/ioport.h>
+#include <linux/console.h>
+#include <linux/pci.h>
+#include <linux/version.h>
+#include <linux/adb.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/prom.h>
+#include <asm/gg2.h>
+#include <asm/pci-bridge.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/irq.h>
+#include <asm/hydra.h>
+#include <asm/keyboard.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+#include <asm/btext.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+#include <asm/xics.h>
+
+unsigned long chrp_get_rtc_time(void);
+int chrp_set_rtc_time(unsigned long nowtime);
+void chrp_calibrate_decr(void);
+long chrp_time_init(void);
+
+void chrp_find_bridges(void);
+void chrp_event_scan(void);
+void rtas_display_progress(char *, unsigned short);
+void rtas_indicator_progress(char *, unsigned short);
+void btext_progress(char *, unsigned short);
+
+extern unsigned long pmac_find_end_of_memory(void);
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+extern void select_adb_keyboard(void);
+extern int of_show_percpuinfo(struct seq_file *, int);
+
+extern kdev_t boot_dev;
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+static int max_width;
+
+#ifdef CONFIG_SMP
+extern struct smp_ops_t chrp_smp_ops;
+extern struct smp_ops_t xics_smp_ops;
+#endif
+
+static const char *gg2_memtypes[4] = {
+	"FPM", "SDRAM", "EDO", "BEDO"
+};
+static const char *gg2_cachesizes[4] = {
+	"256 KB", "512 KB", "1 MB", "Reserved"
+};
+static const char *gg2_cachetypes[4] = {
+	"Asynchronous", "Reserved", "Flow-Through Synchronous",
+	"Pipelined Synchronous"
+};
+static const char *gg2_cachemodes[4] = {
+	"Disabled", "Write-Through", "Copy-Back", "Transparent Mode"
+};
+
+int __chrp
+chrp_show_cpuinfo(struct seq_file *m)
+{
+	int i, sdramen;
+	unsigned int t;
+	struct device_node *root;
+	const char *model = "";
+
+	root = find_path_device("/");
+	if (root)
+		model = get_property(root, "model", NULL);
+	seq_printf(m, "machine\t\t: CHRP %s\n", model);
+
+	/* longtrail (goldengate) stuff */
+	if (!strncmp(model, "IBM,LongTrail", 13)) {
+		/* VLSI VAS96011/12 `Golden Gate 2' */
+		/* Memory banks */
+		sdramen = (in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
+						GG2_PCI_DRAM_CTRL))
+			   >>31) & 1;
+		for (i = 0; i < (sdramen ? 4 : 6); i++) {
+			t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+
+						 GG2_PCI_DRAM_BANK0+
+						 i*4));
+			if (!(t & 1))
+				continue;
+			switch ((t>>8) & 0x1f) {
+			case 0x1f:
+				model = "4 MB";
+				break;
+			case 0x1e:
+				model = "8 MB";
+				break;
+			case 0x1c:
+				model = "16 MB";
+				break;
+			case 0x18:
+				model = "32 MB";
+				break;
+			case 0x10:
+				model = "64 MB";
+				break;
+			case 0x00:
+				model = "128 MB";
+				break;
+			default:
+				model = "Reserved";
+				break;
+			}
+			seq_printf(m, "memory bank %d\t: %s %s\n", i, model,
+				   gg2_memtypes[sdramen ? 1 : ((t>>1) & 3)]);
+		}
+		/* L2 cache */
+		t = in_le32((unsigned *)(GG2_PCI_CONFIG_BASE+GG2_PCI_CC_CTRL));
+		seq_printf(m, "board l2\t: %s %s (%s)\n",
+			   gg2_cachesizes[(t>>7) & 3],
+			   gg2_cachetypes[(t>>2) & 3],
+			   gg2_cachemodes[t & 3]);
+	}
+	return 0;
+}
+
+/*
+ *  Fixes for the National Semiconductor PC78308VUL SuperI/O
+ *
+ *  Some versions of Open Firmware incorrectly initialize the IRQ settings
+ *  for keyboard and mouse
+ */
+static inline void __init sio_write(u8 val, u8 index)
+{
+	outb(index, 0x15c);
+	outb(val, 0x15d);
+}
+
+static inline u8 __init sio_read(u8 index)
+{
+	outb(index, 0x15c);
+	return inb(0x15d);
+}
+
+static void __init sio_fixup_irq(const char *name, u8 device, u8 level,
+				     u8 type)
+{
+	u8 level0, type0, active;
+
+	/* select logical device */
+	sio_write(device, 0x07);
+	active = sio_read(0x30);
+	level0 = sio_read(0x70);
+	type0 = sio_read(0x71);
+	if (level0 != level || type0 != type || !active) {
+		printk(KERN_WARNING "sio: %s irq level %d, type %d, %sactive: "
+		       "remapping to level %d, type %d, active\n",
+		       name, level0, type0, !active ? "in" : "", level, type);
+		sio_write(0x01, 0x30);
+		sio_write(level, 0x70);
+		sio_write(type, 0x71);
+	}
+}
+
+static void __init sio_init(void)
+{
+	struct device_node *root;
+
+	if ((root = find_path_device("/")) &&
+	    !strncmp(get_property(root, "model", NULL), "IBM,LongTrail", 13)) {
+		/* logical device 0 (KBC/Keyboard) */
+		sio_fixup_irq("keyboard", 0, 1, 2);
+		/* select logical device 1 (KBC/Mouse) */
+		sio_fixup_irq("mouse", 1, 12, 2);
+	}
+}
+
+
+void __init
+chrp_setup_arch(void)
+{
+	struct device_node *device;
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* this is fine for chrp */
+	initrd_below_start_ok = 1;
+	
+	if (initrd_start)
+		ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(0x0802); /* sda2 (sda1 is for the kernel) */
+
+	/* Lookup PCI host bridges */
+	chrp_find_bridges();
+
+#ifndef CONFIG_PPC64BRIDGE
+	/*
+	 *  Temporary fixes for PCI devices.
+	 *  -- Geert
+	 */
+	hydra_init();		/* Mac I/O */
+
+#endif /* CONFIG_PPC64BRIDGE */
+
+	/* Some IBM machines don't have the hydra -- Cort */
+	if (!OpenPIC_Addr) {
+		struct device_node *root;
+		unsigned long *opprop;
+		int n;
+
+		root = find_path_device("/");
+		opprop = (unsigned long *) get_property
+			(root, "platform-open-pic", NULL);
+		n = prom_n_addr_cells(root);
+		if (opprop != 0) {
+			printk("OpenPIC addrs: %lx %lx %lx\n",
+			       opprop[n-1], opprop[2*n-1], opprop[3*n-1]);
+			OpenPIC_Addr = ioremap(opprop[n-1], 0x40000);
+		}
+	}
+
+	/*
+	 *  Fix the Super I/O configuration
+	 */
+	sio_init();
+
+	/*
+	 *  Setup the console operations
+	 */
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	/* Get the event scan rate for the rtas so we know how
+	 * often it expects a heartbeat. -- Cort
+	 */
+	if ( rtas_data ) {
+		struct property *p;
+		device = find_devices("rtas");
+		for ( p = device->properties;
+		      p && strncmp(p->name, "rtas-event-scan-rate", 20);
+		      p = p->next )
+			/* nothing */ ;
+		if ( p && *(unsigned long *)p->value ) {
+			ppc_md.heartbeat = chrp_event_scan;
+			ppc_md.heartbeat_reset = (HZ/(*(unsigned long *)p->value)*30)-1;
+			ppc_md.heartbeat_count = 1;
+			printk("RTAS Event Scan Rate: %lu (%lu jiffies)\n",
+			       *(unsigned long *)p->value, ppc_md.heartbeat_reset );
+		}
+	}
+}
+
+void __chrp
+chrp_event_scan(void)
+{
+	unsigned char log[1024];
+	unsigned long ret = 0;
+	/* XXX: we should loop until the hardware says no more error logs -- Cort */
+	call_rtas( "event-scan", 4, 1, &ret, 0xffffffff, 0,
+		   __pa(log), 1024 );
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+	
+void __chrp
+chrp_restart(char *cmd)
+{
+	printk("RTAS system-reboot returned %d\n",
+	       call_rtas("system-reboot", 0, 1, NULL));
+	for (;;);
+}
+
+void __chrp
+chrp_power_off(void)
+{
+	/* allow power on only with power button press */
+	printk("RTAS power-off returned %d\n",
+	       call_rtas("power-off", 2, 1, NULL,0xffffffff,0xffffffff));
+	for (;;);
+}
+
+void __chrp
+chrp_halt(void)
+{
+	chrp_power_off();
+}
+
+u_int __chrp
+chrp_irq_cannonicalize(u_int irq)
+{
+	if (irq == 2)
+		return 9;
+	return irq;
+}
+
+void __init chrp_init_IRQ(void)
+{
+	struct device_node *np;
+	int i;
+	unsigned int *addrp;
+	unsigned char* chrp_int_ack_special = 0;
+	unsigned char init_senses[NR_IRQS - NUM_8259_INTERRUPTS];
+	int nmi_irq = -1;
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)	
+	struct device_node *kbd;
+#endif
+
+	if (!(np = find_devices("pci"))
+	    || !(addrp = (unsigned int *)
+		 get_property(np, "8259-interrupt-acknowledge", NULL)))
+		printk("Cannot find pci to get ack address\n");
+	else
+		chrp_int_ack_special = (unsigned char *)
+			ioremap(addrp[prom_n_addr_cells(np)-1], 1);
+	/* hydra still sets OpenPIC_InitSenses to a static set of values */
+	if (OpenPIC_InitSenses == NULL) {
+		prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS);
+		OpenPIC_InitSenses = init_senses;
+		OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS;
+	}
+	openpic_init(1, NUM_8259_INTERRUPTS, chrp_int_ack_special, nmi_irq);
+	for ( i = 0 ; i < NUM_8259_INTERRUPTS  ; i++ )
+		irq_desc[i].handler = &i8259_pic;
+	i8259_init(0);
+#if defined(CONFIG_VT) && defined(CONFIG_ADB_KEYBOARD) && defined(XMON)
+	/* see if there is a keyboard in the device tree
+	   with a parent of type "adb" */
+	for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next)
+		if (kbd->parent && kbd->parent->type
+		    && strcmp(kbd->parent->type, "adb") == 0)
+			break;
+	if (kbd)
+		request_irq( HYDRA_INT_ADB_NMI, xmon_irq, 0, "XMON break", 0);
+#endif
+}
+
+void __init
+chrp_init2(void)
+{
+#ifdef CONFIG_NVRAM  
+	pmac_nvram_init();
+#endif
+
+	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");
+
+	if (ppc_md.progress)
+		ppc_md.progress("  Have fun!    ", 0x7777);
+
+#if defined(CONFIG_VT) && (defined(CONFIG_ADB_KEYBOARD) || defined(CONFIG_INPUT))
+	/* see if there is a keyboard in the device tree
+	   with a parent of type "adb" */
+	{
+		struct device_node *kbd;
+
+		for (kbd = find_devices("keyboard"); kbd; kbd = kbd->next) {
+			if (kbd->parent && kbd->parent->type
+			    && strcmp(kbd->parent->type, "adb") == 0) {
+				select_adb_keyboard();
+				break;
+			}
+		}
+	}
+#endif /* CONFIG_VT && (CONFIG_ADB_KEYBOARD || CONFIG_INPUT) */
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+
+static int __chrp
+chrp_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+        return check_region(from, extent);
+}
+
+static void __chrp
+chrp_ide_request_region(ide_ioreg_t from,
+			unsigned int extent,
+			const char *name)
+{
+        request_region(from, extent, name);
+}
+
+static void __chrp
+chrp_ide_release_region(ide_ioreg_t from,
+			unsigned int extent)
+{
+        release_region(from, extent);
+}
+
+static void __chrp
+chrp_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;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+}
+#endif
+
+/*
+ * One of the main thing these mappings are needed for is so that
+ * xmon can get to the serial port early on.  We probably should
+ * handle the machines with the mpc106 as well as the python (F50)
+ * and the GG2 (longtrail).  Actually we should look in the device
+ * tree and do the right thing.
+ */
+static void __init
+chrp_map_io(void)
+{
+	char *name;
+
+	/*
+	 * The code below tends to get removed, please don't take it out.
+	 * The F50 needs this mapping and it you take it out I'll track you
+	 * down and slap your hands.  If it causes problems please email me.
+	 *  -- Cort <cort@fsmlabs.com>
+	 */
+	name = get_property(find_path_device("/"), "name", NULL);
+	if (name && strncmp(name, "IBM-70", 6) == 0
+	    && strstr(name, "-F50")) {
+		io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
+		io_block_mapping(0x90000000, 0x90000000, 0x10000000, _PAGE_IO);
+		return;
+	} else {
+		io_block_mapping(0xf8000000, 0xf8000000, 0x04000000, _PAGE_IO);
+	}
+}
+
+void __init
+chrp_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	  unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* take care of initrd if we have one */
+	if ( r6 )
+	{
+		initrd_start = r6 + KERNELBASE;
+		initrd_end = r6 + r7 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+	isa_io_base = CHRP_ISA_IO_BASE;		/* default value */
+
+	ppc_md.setup_arch     = chrp_setup_arch;
+	ppc_md.show_percpuinfo = of_show_percpuinfo;
+	ppc_md.show_cpuinfo   = chrp_show_cpuinfo;
+	ppc_md.irq_cannonicalize = chrp_irq_cannonicalize;
+#ifndef CONFIG_POWER4
+	ppc_md.init_IRQ       = chrp_init_IRQ;
+	ppc_md.get_irq        = openpic_get_irq;
+#else
+	ppc_md.init_IRQ	      = xics_init_IRQ;
+	ppc_md.get_irq	      = xics_get_irq;
+#endif /* CONFIG_POWER4 */
+
+	ppc_md.init           = chrp_init2;
+
+	ppc_md.restart        = chrp_restart;
+	ppc_md.power_off      = chrp_power_off;
+	ppc_md.halt           = chrp_halt;
+
+	ppc_md.time_init      = chrp_time_init;
+	ppc_md.set_rtc_time   = chrp_set_rtc_time;
+	ppc_md.get_rtc_time   = chrp_get_rtc_time;
+	ppc_md.calibrate_decr = chrp_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+	ppc_md.setup_io_mappings = chrp_map_io;
+
+#ifdef CONFIG_VT
+	/* these are adjusted in chrp_init2 if we have an ADB keyboard */
+	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.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
+	SYSRQ_KEY = 0x54;
+#endif /* CONFIG_MAGIC_SYSRQ */
+#endif /* CONFIG_VT */
+
+	if (rtas_data) {
+		struct device_node *rtas;
+		unsigned int *p;
+
+		rtas = find_devices("rtas");
+		if (rtas != NULL) {
+			if (get_property(rtas, "display-character", NULL)) {
+				ppc_md.progress = rtas_display_progress;
+				p = (unsigned int *) get_property
+				       (rtas, "ibm,display-line-length", NULL);
+				if (p)
+					max_width = *p;
+			} else if (get_property(rtas, "set-indicator", NULL))
+				ppc_md.progress = rtas_indicator_progress;
+		}
+	}
+#ifdef CONFIG_BOOTX_TEXT
+	if (ppc_md.progress == NULL && boot_text_mapped)
+		ppc_md.progress = btext_progress;
+#endif
+
+#ifdef CONFIG_SMP
+#ifndef CONFIG_POWER4
+	ppc_md.smp_ops = &chrp_smp_ops;
+#else
+	ppc_md.smp_ops = &xics_smp_ops;
+#endif /* CONFIG_POWER4 */
+#endif /* CONFIG_SMP */
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+        ppc_ide_md.ide_check_region = chrp_ide_check_region;
+        ppc_ide_md.ide_request_region = chrp_ide_request_region;
+        ppc_ide_md.ide_release_region = chrp_ide_release_region;
+        ppc_ide_md.ide_init_hwif = chrp_ide_init_hwif_ports;
+#endif
+
+	/*
+	 * Print the banner, then scroll down so boot progress
+	 * can be printed.  -- Cort 
+	 */
+	if ( ppc_md.progress ) ppc_md.progress("Linux/PPC "UTS_RELEASE"\n", 0x0);
+}
+
+void __chrp
+rtas_display_progress(char *s, unsigned short hex)
+{
+	int width;
+	char *os = s;
+
+	if ( call_rtas( "display-character", 1, 1, NULL, '\r' ) )
+		return;
+
+	width = max_width;
+	while ( *os )
+	{
+		if ( (*os == '\n') || (*os == '\r') )
+			width = max_width;
+		else
+			width--;
+		call_rtas( "display-character", 1, 1, NULL, *os++ );
+		/* if we overwrite the screen length */
+		if ( width == 0 )
+			while ( (*os != 0) && (*os != '\n') && (*os != '\r') )
+				os++;
+	}
+
+	/*while ( width-- > 0 )*/
+	call_rtas( "display-character", 1, 1, NULL, ' ' );
+}
+
+void __chrp
+rtas_indicator_progress(char *s, unsigned short hex)
+{
+	call_rtas("set-indicator", 3, 1, NULL, 6, 0, hex);
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void
+btext_progress(char *s, unsigned short hex)
+{
+	prom_print(s);
+	prom_print("\n");
+}
+#endif /* CONFIG_BOOTX_TEXT */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/chrp_smp.c linux/arch/ppc/platforms/chrp_smp.c
--- linux.orig/arch/ppc/platforms/chrp_smp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/chrp_smp.c	2002-08-12 22:14:15.000000000 +0000
@@ -0,0 +1,147 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * Smp support for CHRP machines.
+ *
+ * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great
+ * deal of code from the sparc and intel versions.
+ *
+ * Copyright (C) 1999 Cort Dougan <cort@cs.nmt.edu>
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+
+extern unsigned long smp_chrp_cpu_nr;
+
+static int __init
+smp_chrp_probe(void)
+{
+	if (smp_chrp_cpu_nr > 1)
+		openpic_request_IPIs();
+
+	return smp_chrp_cpu_nr;
+}
+
+static void __init
+smp_chrp_kick_cpu(int nr)
+{
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+}
+
+static void __init
+smp_chrp_setup_cpu(int cpu_nr)
+{
+	static atomic_t ready = ATOMIC_INIT(1);
+	static volatile int frozen = 0;
+
+	if (cpu_nr == 0) {
+		/* wait for all the others */
+		while (atomic_read(&ready) < smp_num_cpus)
+			barrier();
+		atomic_set(&ready, 1);
+		/* freeze the timebase */
+		call_rtas("freeze-time-base", 0, 1, NULL);
+		mb();
+		frozen = 1;
+		/* XXX assumes this is not a 601 */
+		set_tb(0, 0);
+		last_jiffy_stamp(0) = 0;
+		while (atomic_read(&ready) < smp_num_cpus)
+			barrier();
+		/* thaw the timebase again */
+		call_rtas("thaw-time-base", 0, 1, NULL);
+		mb();
+		frozen = 0;
+		smp_tb_synchronized = 1;
+	} else {
+		atomic_inc(&ready);
+		while (!frozen)
+			barrier();
+		set_tb(0, 0);
+		last_jiffy_stamp(0) = 0;
+		mb();
+		atomic_inc(&ready);
+		while (frozen)
+			barrier();
+	}
+
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+#ifdef CONFIG_POWER4
+static void __chrp
+smp_xics_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	/* for now, only do reschedule messages
+	   since we only have one IPI */
+	if (msg != PPC_MSG_RESCHEDULE)
+		return;
+	for (i = 0; i < smp_num_cpus; ++i) {
+		if (target == MSG_ALL || target == i
+		    || (target == MSG_ALL_BUT_SELF
+			&& i != smp_processor_id()))
+			xics_cause_IPI(i);
+	}
+}
+
+static int __chrp
+smp_xics_probe(void)
+{
+	return smp_chrp_cpu_nr;
+}
+
+static void __chrp
+smp_xics_setup_cpu(int cpu_nr)
+{
+	if (cpu_nr > 0)
+		xics_setup_cpu();
+}
+#endif /* CONFIG_POWER4 */
+
+/* CHRP with openpic */
+struct smp_ops_t chrp_smp_ops __chrpdata = {
+	smp_openpic_message_pass,
+	smp_chrp_probe,
+	smp_chrp_kick_cpu,
+	smp_chrp_setup_cpu,
+};
+
+#ifdef CONFIG_POWER4
+/* CHRP with new XICS interrupt controller */
+struct smp_ops_t xics_smp_ops __chrpdata = {
+	smp_xics_message_pass,
+	smp_xics_probe,
+	smp_chrp_kick_cpu,
+	smp_xics_setup_cpu,
+};
+#endif /* CONFIG_POWER4 */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/chrp_time.c linux/arch/ppc/platforms/chrp_time.c
--- linux.orig/arch/ppc/platforms/chrp_time.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/chrp_time.c	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,195 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platforms/chrp_time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * Adapted for PowerPC (PReP) by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu).
+ * Copied and modified from arch/i386/kernel/time.c
+ *
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+#include <linux/mc146818rtc.h>
+#include <linux/init.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/nvram.h>
+#include <asm/prom.h>
+#include <asm/sections.h>
+#include <asm/time.h>
+
+extern spinlock_t rtc_lock;
+
+static int nvram_as1 = NVRAM_AS1;
+static int nvram_as0 = NVRAM_AS0;
+static int nvram_data = NVRAM_DATA;
+
+long __init chrp_time_init(void)
+{
+	struct device_node *rtcs;
+	int base;
+
+	rtcs = find_compatible_devices("rtc", "pnpPNP,b00");
+	if (rtcs == NULL || rtcs->addrs == NULL)
+		return 0;
+	base = rtcs->addrs[0].address;
+	nvram_as1 = 0;
+	nvram_as0 = base;
+	nvram_data = base + 1;
+
+	return 0;
+}
+
+int __chrp chrp_cmos_clock_read(int addr)
+{
+	if (nvram_as1 != 0)
+		outb(addr>>8, nvram_as1);
+	outb(addr, nvram_as0);
+	return (inb(nvram_data));
+}
+
+void __chrp chrp_cmos_clock_write(unsigned long val, int addr)
+{
+	if (nvram_as1 != 0)
+		outb(addr>>8, nvram_as1);
+	outb(addr, nvram_as0);
+	outb(val, nvram_data);
+	return;
+}
+
+/*
+ * Set the hardware clock. -- Cort
+ */
+int __chrp chrp_set_rtc_time(unsigned long nowtime)
+{
+	unsigned char save_control, save_freq_select;
+	struct rtc_time tm;
+
+	spin_lock(&rtc_lock);
+	to_tm(nowtime, &tm);
+
+	save_control = chrp_cmos_clock_read(RTC_CONTROL); /* tell the clock it's being set */
+
+	chrp_cmos_clock_write((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = chrp_cmos_clock_read(RTC_FREQ_SELECT); /* stop and reset prescaler */
+
+	chrp_cmos_clock_write((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+        tm.tm_year -= 1900;
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BIN_TO_BCD(tm.tm_sec);
+		BIN_TO_BCD(tm.tm_min);
+		BIN_TO_BCD(tm.tm_hour);
+		BIN_TO_BCD(tm.tm_mon);
+		BIN_TO_BCD(tm.tm_mday);
+		BIN_TO_BCD(tm.tm_year);
+	}
+	chrp_cmos_clock_write(tm.tm_sec,RTC_SECONDS);
+	chrp_cmos_clock_write(tm.tm_min,RTC_MINUTES);
+	chrp_cmos_clock_write(tm.tm_hour,RTC_HOURS);
+	chrp_cmos_clock_write(tm.tm_mon,RTC_MONTH);
+	chrp_cmos_clock_write(tm.tm_mday,RTC_DAY_OF_MONTH);
+	chrp_cmos_clock_write(tm.tm_year,RTC_YEAR);
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	chrp_cmos_clock_write(save_control, RTC_CONTROL);
+	chrp_cmos_clock_write(save_freq_select, RTC_FREQ_SELECT);
+
+	if ( (time_state == TIME_ERROR) || (time_state == TIME_BAD) )
+		time_state = TIME_OK;
+	spin_unlock(&rtc_lock);
+	return 0;
+}
+
+unsigned long __chrp chrp_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int uip, i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+
+	/* Since the UIP flag is set for about 2.2 ms and the clock
+	 * is typically written with a precision of 1 jiffy, trying
+	 * to obtain a precision better than a few milliseconds is 
+	 * an illusion. Only consistency is interesting, this also
+	 * allows to use the routine for /dev/rtc without a potential
+	 * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
+	 */
+
+	for ( i = 0; i<1000000; i++) {
+		uip = chrp_cmos_clock_read(RTC_FREQ_SELECT);
+		sec = chrp_cmos_clock_read(RTC_SECONDS);
+		min = chrp_cmos_clock_read(RTC_MINUTES);
+		hour = chrp_cmos_clock_read(RTC_HOURS);
+		day = chrp_cmos_clock_read(RTC_DAY_OF_MONTH);
+		mon = chrp_cmos_clock_read(RTC_MONTH);
+		year = chrp_cmos_clock_read(RTC_YEAR);
+		uip |= chrp_cmos_clock_read(RTC_FREQ_SELECT);
+		if ((uip & RTC_UIP)==0) break;
+	}
+
+	if (!(chrp_cmos_clock_read(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+
+void __init chrp_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	unsigned int freq, *fp;
+
+	if (via_calibrate_decr())
+		return;
+
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	freq = 16666000;		/* hardcoded default */
+	cpu = find_type_devices("cpu");
+	if (cpu != 0) {
+		fp = (unsigned int *)
+			get_property(cpu, "timebase-frequency", NULL);
+		if (fp != 0)
+			freq = *fp;
+	}
+	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+ 	       freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/error_log.c linux/arch/ppc/platforms/error_log.c
--- linux.orig/arch/ppc/platforms/error_log.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/error_log.c	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,186 @@
+/*
+ * BK Id: SCCS/s.error_log.c 1.6 05/17/01 18:14:21 cort
+ */
+/*
+ *  arch/ppc/kernel/error_log.c
+ *  
+ *  Copyright (c) 2000 Tilmann Bitterberg
+ *  (tilmann@bitterberg.de)
+ *
+ *  Error processing of errors found by rtas even-scan routine
+ *  which is done with every heartbeat. (chrp_setup.c)
+ */
+
+#include <linux/sched.h>
+
+#include <asm/prom.h>
+
+#include "error_log.h"
+
+/* ****************************************************************** */
+/* 
+ * EVENT-SCAN
+ * The whole stuff below here doesn't take any action when it found
+ * an error, it just prints as much information as possible and 
+ * then its up to the user to decide what to do.
+ *
+ * Returns 0 if no errors were found
+ * Returns 1 if there may be more errors
+ */
+int ppc_rtas_errorlog_scan(void)
+{
+const char *_errlog_severity[] = {
+#ifdef VERBOSE_ERRORS
+	"No Error\n\t\
+Should require no further information",
+	"Event\n\t\
+This is not really an error, it is an event. I use events\n\t\
+to communicate with RTAS back and forth.",
+	"Warning\n\t\
+Indicates a non-state-losing error, either fully recovered\n\t\
+by RTAS or not needing recovery. Ignore it.",
+	"Error sync\n\t\
+May only be fatal to a certain program or thread. Recovery\n\t\
+and continuation is possible, if I only had a handler for\n\t\
+this. Less serious",
+	"Error\n\t\
+Less serious, but still causing a loss of data and state.\n\t\
+I can't tell you exactly what to do, You have to decide\n\t\
+with help from the target and initiator field, what kind\n\t\
+of further actions may take place.",
+	"Fatal\n\t\
+Represent a permanent hardware failure and I believe this\n\t\
+affects my overall performance and behaviour. I would not\n\t\
+attempt to continue normal operation."
+#else
+	"No Error",
+	"Event",
+	"Warning",
+	"Error sync",
+	"Error",
+	"Fatal"
+#endif /* VERBOSE_ERRORS */
+};
+
+#if 0 /* unused?? */
+const char *_errlog_disposition[] = {
+#ifdef VERBOSE_ERRORS
+	"Fully recovered\n\t\
+There was an error, but it is fully recovered by RTAS.",
+	"Limited recovery\n\t\
+RTAS was able to recover the state of the machine, but some\n\t\
+feature of the machine has been disabled or lost (for example\n\t\
+error checking) or performance may suffer.",
+	"Not recovered\n\t\
+Whether RTAS did not try to recover anything or recovery failed:\n\t\
+HOUSTON, WE HAVE A PROBLEM!"
+#else
+	"Fully recovered",
+	"Limited recovery",
+	"Not recovered"
+#endif /* VERBOSE_ERRORS */
+};
+#endif
+
+const char *_errlog_extended[] = {
+#ifdef VERBOSE_ERRORS
+	"Not present\n\t\
+Sad, the RTAS call didn't return an extended error log.",
+	"Present\n\t\
+The extended log is present and hopefully it contains a lot of\n\t\
+useful information, which leads to the solution of the problem."
+#else
+	"Not present",
+	"Present"
+#endif /* VERBOSE_ERRORS */
+};
+
+const char *_errlog_initiator[] = { 
+	"Unknown or not applicable",
+	"CPU",
+	"PCI",
+	"ISA",
+	"Memory",
+	"Power management"
+};
+
+const char *_errlog_target[] = { 
+	"Unknown or not applicable",
+	"CPU",
+	"PCI",
+	"ISA",
+	"Memory",
+	"Power management"
+};
+	rtas_error_log error_log;
+	char logdata[1024];
+	int error;
+#if 0 /* unused?? */
+	int retries = 0; /* if HW error, try 10 times */
+#endif
+
+	error = call_rtas ("event-scan", 4, 1, (unsigned long *)&error_log,
+			INTERNAL_ERROR | EPOW_WARNING,
+			0, __pa(logdata), 1024);
+
+	if (error == 1) /* no errors found */
+		return 0;
+
+	if (error == -1) {
+		printk(KERN_ERR "Unable to get errors. Do you a favor and throw this box away\n");
+		return 0;
+	}
+	if (error_log.version != 1)
+		printk(KERN_WARNING "Unknown version (%d), please implement me\n", 
+				error_log.version);
+
+	switch (error_log.disposition) {
+		case DISP_FULLY_RECOVERED:
+			/* there was an error, but everything is fine now */
+			return 0;
+		case DISP_NOT_RECOVERED:
+			printk("We have a really serious Problem!\n");
+		case DISP_LIMITED_RECOVERY:
+			printk("Error classification\n");
+			printk("Severity  : %s\n", 
+					ppc_rtas_errorlog_check_severity (error_log));
+			printk("Initiator : %s\n", 
+					ppc_rtas_errorlog_check_initiator (error_log));
+			printk("Target    : %s\n", 
+					ppc_rtas_errorlog_check_target (error_log));
+			printk("Type      : %s\n", 
+					ppc_rtas_errorlog_check_type (error_log));
+			printk("Ext. log  : %s\n", 
+					ppc_rtas_errorlog_check_extended (error_log));
+			if (error_log.extended)
+				ppc_rtas_errorlog_disect_extended (logdata);
+			return 1;	
+		default:
+			/* nothing */
+			break;
+	}
+	return 0;
+}
+/* ****************************************************************** */
+const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log)
+{
+	const char *_errlog_type[] = {
+		"unknown type",
+		"too many tries failed",
+		"TCE error",
+		"RTAS device failed",
+		"target timed out",
+		"parity error on data",			/* 5 */
+		"parity error on address",
+		"parity error on external cache",
+		"access to invalid address",
+		"uncorrectable ECC error",
+		"corrected ECC error"			/* 10 */
+	};
+	if (error_log.type == TYPE_EPOW) 
+		return "EPOW"; 
+	if (error_log.type >= TYPE_PMGM_POWER_SW_ON)
+		return "PowerMGM Event (not handled right now)";
+	return _errlog_type[error_log.type];
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/error_log.h linux/arch/ppc/platforms/error_log.h
--- linux.orig/arch/ppc/platforms/error_log.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/error_log.h	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,98 @@
+/*
+ * BK Id: SCCS/s.error_log.h 1.5 05/17/01 18:14:21 cort
+ */
+#ifndef __ERROR_LOG_H__
+#define __ERROR_LOG_H__
+
+#define VERBOSE_ERRORS		1 /* Maybe I enlarge the kernel too much */
+#undef VERBOSE_ERRORS
+
+/* Event classes */
+/* XXX: Endianess correct? NOW*/
+#define INTERNAL_ERROR		0x80000000 /* set bit 0 */
+#define EPOW_WARNING		0x40000000 /* set bit 1 */
+#define POWERMGM_EVENTS		0x20000000 /* set bit 2 */
+
+/* event-scan returns */
+#define SEVERITY_FATAL		0x5
+#define SEVERITY_ERROR		0x4
+#define SEVERITY_ERROR_SYNC	0x3
+#define SEVERITY_WARNING	0x2
+#define SEVERITY_EVENT		0x1
+#define SEVERITY_NO_ERROR	0x0
+#define DISP_FULLY_RECOVERED	0x0
+#define DISP_LIMITED_RECOVERY	0x1
+#define DISP_NOT_RECOVERED	0x2
+#define PART_PRESENT		0x0
+#define PART_NOT_PRESENT	0x1
+#define INITIATOR_UNKNOWN	0x0
+#define INITIATOR_CPU		0x1
+#define INITIATOR_PCI		0x2
+#define INITIATOR_ISA		0x3
+#define INITIATOR_MEMORY	0x4
+#define INITIATOR_POWERMGM	0x5
+#define TARGET_UNKNOWN		0x0
+#define TARGET_CPU		0x1
+#define TARGET_PCI		0x2
+#define TARGET_ISA		0x3
+#define TARGET_MEMORY		0x4
+#define TARGET_POWERMGM		0x5
+#define TYPE_RETRY		0x01
+#define TYPE_TCE_ERR		0x02
+#define TYPE_INTERN_DEV_FAIL	0x03
+#define TYPE_TIMEOUT		0x04
+#define TYPE_DATA_PARITY	0x05
+#define TYPE_ADDR_PARITY	0x06
+#define TYPE_CACHE_PARITY	0x07
+#define TYPE_ADDR_INVALID	0x08
+#define TYPE_ECC_UNCORR		0x09
+#define TYPE_ECC_CORR		0x0a
+#define TYPE_EPOW		0x40
+/* I don't add PowerMGM events right now, this is a different topic */ 
+#define TYPE_PMGM_POWER_SW_ON	0x60
+#define TYPE_PMGM_POWER_SW_OFF	0x61
+#define TYPE_PMGM_LID_OPEN	0x62
+#define TYPE_PMGM_LID_CLOSE	0x63
+#define TYPE_PMGM_SLEEP_BTN	0x64
+#define TYPE_PMGM_WAKE_BTN	0x65
+#define TYPE_PMGM_BATTERY_WARN	0x66
+#define TYPE_PMGM_BATTERY_CRIT	0x67
+#define TYPE_PMGM_SWITCH_TO_BAT	0x68
+#define TYPE_PMGM_SWITCH_TO_AC	0x69
+#define TYPE_PMGM_KBD_OR_MOUSE	0x6a
+#define TYPE_PMGM_ENCLOS_OPEN	0x6b
+#define TYPE_PMGM_ENCLOS_CLOSED	0x6c
+#define TYPE_PMGM_RING_INDICATE	0x6d
+#define TYPE_PMGM_LAN_ATTENTION	0x6e
+#define TYPE_PMGM_TIME_ALARM	0x6f
+#define TYPE_PMGM_CONFIG_CHANGE	0x70
+#define TYPE_PMGM_SERVICE_PROC	0x71
+
+typedef struct _rtas_error_log {
+	unsigned long version:8;		/* Architectural version */
+	unsigned long severity:3;		/* Severity level of error */
+	unsigned long disposition:2;		/* Degree of recovery */
+	unsigned long extended:1;		/* extended log present? */
+	unsigned long /* reserved */ :2;	/* Reserved for future use */
+	unsigned long initiator:4;		/* Initiator of event */
+	unsigned long target:4;			/* Target of failed operation */
+	unsigned long type:8;			/* General event or error*/
+	unsigned long extended_log_length:32;	/* length in bytes */
+} rtas_error_log;
+
+/* ****************************************************************** */
+#define ppc_rtas_errorlog_check_severity(x) \
+	(_errlog_severity[x.severity])
+#define ppc_rtas_errorlog_check_target(x) \
+	(_errlog_target[x.target])
+#define ppc_rtas_errorlog_check_initiator(x) \
+	(_errlog_initiator[x.initiator])
+#define ppc_rtas_errorlog_check_extended(x) \
+	(_errlog_extended[x.extended])
+#define ppc_rtas_errorlog_disect_extended(x) \
+	do { /* implement me */ } while(0)
+extern const char * ppc_rtas_errorlog_check_type (rtas_error_log error_log);
+extern int ppc_rtas_errorlog_scan(void);
+
+
+#endif /* __ERROR_LOG_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/est8260.h linux/arch/ppc/platforms/est8260.h
--- linux.orig/arch/ppc/platforms/est8260.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/est8260.h	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,31 @@
+/*
+ * BK Id: SCCS/s.est8260.h 1.5 05/17/01 18:14:24 cort
+ */
+
+/* Board information for the EST8260, which should be generic for
+ * all 8260 boards.  The IMMR is now given to us so the hard define
+ * will soon be removed.  All of the clock values are computed from
+ * the configuration SCMR and the Power-On-Reset word.
+ */
+
+#define IMAP_ADDR	((uint)0xf0000000)
+
+
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in MHz */
+	unsigned int	bi_cpmfreq;	/* CPM Freq, in MHz */
+	unsigned int	bi_brgfreq;	/* BRG Freq, in MHz */
+	unsigned int	bi_vco;		/* VCO Out from PLL */
+	unsigned int	bi_baudrate;	/* Default console baud rate */
+	unsigned int	bi_immr;	/* IMMR when called from boot rom */
+	unsigned char	bi_enetaddr[6];
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/fads.h linux/arch/ppc/platforms/fads.h
--- linux.orig/arch/ppc/platforms/fads.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/fads.h	2002-08-12 22:14:01.000000000 +0000
@@ -0,0 +1,61 @@
+/*
+ * BK Id: SCCS/s.fads.h 1.14 10/26/01 10:14:09 trini
+ */
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola 860T FADS board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __ASM_FADS_H__
+#define __ASM_FADS_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+/* Memory map is configured by the PROM startup.
+ * I tried to follow the FADS manual, although the startup PROM
+ * dictates this and we simply have to move some of the physical
+ * addresses for Linux.
+ */
+#define BCSR_ADDR		((uint)0xff010000)
+#define BCSR_SIZE		((uint)(64 * 1024))
+#define	BCSR0			((uint)0xff010000)
+#define	BCSR1			((uint)0xff010004)
+#define	BCSR2			((uint)0xff010008)
+#define	BCSR3			((uint)0xff01000c)
+#define	BCSR4			((uint)0xff010010)
+
+#define IMAP_ADDR		((uint)0xff000000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+
+#define PCMCIA_MEM_ADDR		((uint)0xff020000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+
+/* Bits of interest in the BCSRs.
+ */
+#define BCSR1_ETHEN		((uint)0x20000000)
+#define BCSR1_RS232EN_1		((uint)0x01000000)
+#define BCSR1_RS232EN_2		((uint)0x00040000)
+#define BCSR4_ETHLOOP		((uint)0x80000000)	/* EEST Loopback */
+#define BCSR4_EEFDX		((uint)0x40000000)	/* EEST FDX enable */
+#define BCSR4_FETH_EN		((uint)0x08000000)	/* PHY enable */
+#define BCSR4_FETHCFG0		((uint)0x04000000)	/* PHY autoneg mode */
+#define BCSR4_FETHCFG1		((uint)0x00400000)	/* PHY autoneg mode */
+#define BCSR4_FETHFDE		((uint)0x02000000)	/* PHY FDX advertise */
+#define BCSR4_FETHRST		((uint)0x00200000)	/* PHY Reset */
+
+/* Interrupt level assignments.
+ */
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+#define PHY_INTERRUPT	SIU_IRQ2	/* PHY link change interrupt */
+
+/* We don't use the 8259.
+ */
+#define NR_8259_INTS	0
+
+#endif /* __ASM_FADS_H__ */
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/gemini.h linux/arch/ppc/platforms/gemini.h
--- linux.orig/arch/ppc/platforms/gemini.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/gemini.h	2002-08-12 22:14:18.000000000 +0000
@@ -0,0 +1,171 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  include/asm-ppc/platforms/gemini.h
+ *
+ *
+ *  Onboard registers and descriptions for Synergy Microsystems' 
+ *  "Gemini" boards.
+ *
+ */
+#ifdef __KERNEL__
+#ifndef __PPC_GEMINI_H
+#define __PPC_GEMINI_H
+
+/*  Registers  */
+
+#define GEMINI_SERIAL_B     (0xffeffb00)
+#define GEMINI_SERIAL_A     (0xffeffb08)
+#define GEMINI_USWITCH      (0xffeffd00)
+#define GEMINI_BREV         (0xffeffe00)
+#define GEMINI_BECO         (0xffeffe08)
+#define GEMINI_FEAT         (0xffeffe10)
+#define GEMINI_BSTAT        (0xffeffe18)
+#define GEMINI_CPUSTAT      (0xffeffe20)
+#define GEMINI_L2CFG        (0xffeffe30)
+#define GEMINI_MEMCFG       (0xffeffe38)
+#define GEMINI_FLROM        (0xffeffe40)
+#define GEMINI_P0PCI        (0xffeffe48)
+#define GEMINI_FLWIN        (0xffeffe50)
+#define GEMINI_P0INTMASK    (0xffeffe60)
+#define GEMINI_P0INTAP      (0xffeffe68)
+#define GEMINI_PCIERR       (0xffeffe70)
+#define GEMINI_LEDBASE      (0xffeffe80)
+#define GEMINI_RTC          (0xffe9fff8)
+#define GEMINI_LEDS         8
+#define GEMINI_SWITCHES     8
+
+
+/* Flash ROM bit definitions */
+#define GEMINI_FLS_WEN      (1<<0)
+#define GEMINI_FLS_JMP      (1<<6)
+#define GEMINI_FLS_BOOT     (1<<7)
+
+/* Memory bit definitions */
+#define GEMINI_MEM_TYPE_MASK 0xc0
+#define GEMINI_MEM_SIZE_MASK 0x38
+#define GEMINI_MEM_BANK_MASK 0x07
+
+/* L2 cache bit definitions */
+#define GEMINI_L2_SIZE_MASK  0xc0
+#define GEMINI_L2_RATIO_MASK 0x03
+
+/* Timebase register bit definitons */
+#define GEMINI_TIMEB0_EN     (1<<0)
+#define GEMINI_TIMEB1_EN     (1<<1)
+#define GEMINI_TIMEB2_EN     (1<<2)
+#define GEMINI_TIMEB3_EN     (1<<3)
+
+/* CPU status bit definitions */
+#define GEMINI_CPU_ID_MASK   0x03
+#define GEMINI_CPU_COUNT_MASK 0x0c
+#define GEMINI_CPU0_HALTED   (1<<4)
+#define GEMINI_CPU1_HALTED   (1<<5)
+#define GEMINI_CPU2_HALTED   (1<<6)
+#define GEMINI_CPU3_HALTED   (1<<7)
+
+/* Board status bit definitions */
+#define GEMINI_BRD_FAIL      (1<<0)   /* FAIL led is lit */
+#define GEMINI_BRD_BUS_MASK  0x0c     /* PowerPC bus speed */
+
+/* Board family/feature bit descriptions */
+#define GEMINI_FEAT_HAS_FLASH (1<<0)
+#define GEMINI_FEAT_HAS_ETH   (1<<1)
+#define GEMINI_FEAT_HAS_SCSI  (1<<2)
+#define GEMINI_FEAT_HAS_P0    (1<<3)
+#define GEMINI_FEAT_FAM_MASK  0xf0
+
+/* Mod/ECO bit definitions */
+#define GEMINI_ECO_LEVEL_MASK 0x0f
+#define GEMINI_MOD_MASK       0xf0
+
+/* Type/revision bit definitions */
+#define GEMINI_REV_MASK       0x0f
+#define GEMINI_TYPE_MASK      0xf0
+
+/* User switch definitions */
+#define GEMINI_SWITCH_VERBOSE    1     /* adds "debug" to boot cmd line */
+#define GEMINI_SWITCH_SINGLE_USER 7    /* boots into "single-user" mode */
+
+#define SGS_RTC_CONTROL  0
+#define SGS_RTC_SECONDS  1
+#define SGS_RTC_MINUTES  2
+#define SGS_RTC_HOURS    3
+#define SGS_RTC_DAY      4
+#define SGS_RTC_DAY_OF_MONTH 5
+#define SGS_RTC_MONTH    6
+#define SGS_RTC_YEAR     7
+
+#define SGS_RTC_SET  0x80
+#define SGS_RTC_IS_STOPPED 0x80
+
+#define GRACKLE_CONFIG_ADDR_ADDR  (0xfec00000)
+#define GRACKLE_CONFIG_DATA_ADDR  (0xfee00000)
+
+#define GEMINI_BOOT_INIT  (0xfff00100)
+
+#ifndef __ASSEMBLY__
+
+static inline void grackle_write( unsigned long addr, unsigned long data )
+{
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %0\n \
+    sync\n \
+    stwbrx %3, 0, %2\n \
+    sync "
+  : /* no output */
+  : "r" (GRACKLE_CONFIG_ADDR_ADDR), "r" (addr),
+    "r" (GRACKLE_CONFIG_DATA_ADDR), "r" (data));
+}
+
+static inline unsigned long grackle_read( unsigned long addr )
+{
+  unsigned long val;
+
+  __asm__ __volatile__(
+  " stwbrx %1, 0, %2\n \
+    sync\n \
+    lwbrx %0, 0, %3\n \
+    sync "
+  : "=r" (val)
+  : "r" (addr), "r" (GRACKLE_CONFIG_ADDR_ADDR),
+    "r" (GRACKLE_CONFIG_DATA_ADDR));
+
+  return val;
+}
+
+static inline void gemini_led_on( int led )
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 1;
+}
+
+static inline void gemini_led_off(int led)
+{
+  if (led >= 0 && led < GEMINI_LEDS)
+    *(unsigned char *)(GEMINI_LEDBASE + (led<<3)) = 0;
+}
+
+static inline int gemini_led_val(int led)
+{
+  int val = 0;
+  if (led >= 0 && led < GEMINI_LEDS)
+    val = *(unsigned char *)(GEMINI_LEDBASE + (led<<3));
+  return (val & 0x1);
+}
+
+/* returns processor id from the board */
+static inline int gemini_processor(void)
+{
+  unsigned char cpu = *(unsigned char *)(GEMINI_CPUSTAT);
+  return (int) ((cpu == 0) ? 4 : (cpu & GEMINI_CPU_ID_MASK));
+}
+
+
+extern void _gemini_reboot(void);
+extern void gemini_prom_init(void);
+extern void gemini_init_l2(void);
+#endif /* __ASSEMBLY__ */
+#endif
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/gemini_pci.c linux/arch/ppc/platforms/gemini_pci.c
--- linux.orig/arch/ppc/platforms/gemini_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/gemini_pci.c	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,122 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+
+#include <asm/machdep.h>
+#include <platforms/gemini.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/pci-bridge.h>
+
+#define pci_config_addr(bus,dev,offset) \
+        (0x80000000 | (bus<<16) | (dev<<8) | offset)
+
+
+int
+gemini_pcibios_read_config_byte(struct pci_dev *dev, int offset, u8 *val)
+{
+	unsigned long reg;
+	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					   (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_word(struct pci_dev *dev, int offset, u16 *val)
+{
+	unsigned long reg;
+	reg = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					   (offset & ~(0x3))));
+	*val = ((reg >> ((offset & 0x3) << 3)) & 0xffff);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_read_config_dword(struct pci_dev *dev, int offset, u32 *val)
+{
+	*val = grackle_read(pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3))));
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_byte(struct pci_dev *dev, int offset, u8 val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3)));
+
+	reg = grackle_read(addr);
+	reg = (reg & ~(0xff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write(addr, reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_word(struct pci_dev *dev, int offset, u16 val)
+{
+	unsigned long reg;
+	int shifts = offset & 0x3;
+	unsigned int addr = pci_config_addr(dev->bus->number, dev->devfn,
+					    (offset & ~(0x3)));
+
+	reg = grackle_read(addr);
+	reg = (reg & ~(0xffff << (shifts << 3))) | (val << (shifts << 3));
+	grackle_write(addr, reg );
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int
+gemini_pcibios_write_config_dword(struct pci_dev *dev, int offset, u32 val)
+{
+	grackle_write(pci_config_addr(dev->bus->number, dev->devfn,
+				      (offset & ~(0x3))), val);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops gemini_pci_ops =
+{
+	gemini_pcibios_read_config_byte,
+	gemini_pcibios_read_config_word,
+	gemini_pcibios_read_config_dword,
+	gemini_pcibios_write_config_byte,
+	gemini_pcibios_write_config_word,
+	gemini_pcibios_write_config_dword
+};
+
+void __init gemini_pcibios_fixup(void)
+{
+	int i;
+	struct pci_dev *dev;
+	
+	pci_for_each_dev(dev) {
+		for(i = 0; i < 6; i++) {
+			if (dev->resource[i].flags & IORESOURCE_IO) {
+				dev->resource[i].start |= (0xfe << 24);
+				dev->resource[i].end |= (0xfe << 24);
+			}
+		}
+	}
+}
+
+
+/* The "bootloader" for Synergy boards does none of this for us, so we need to
+   lay it all out ourselves... --Dan */
+void __init gemini_find_bridges(void)
+{
+	struct pci_controller* hose;
+	
+	ppc_md.pcibios_fixup = gemini_pcibios_fixup;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+	hose->ops = &gemini_pci_ops;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/gemini_prom.S linux/arch/ppc/platforms/gemini_prom.S
--- linux.orig/arch/ppc/platforms/gemini_prom.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/gemini_prom.S	2002-08-12 22:14:01.000000000 +0000
@@ -0,0 +1,98 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/kernel/gemini_prom.S
+ *
+ *  Not really prom support code (yet), but sort of anti-prom code.  The current
+ *  bootloader does a number of things it shouldn't and doesn't do things that it
+ *  should.  The stuff in here is mainly a hodge-podge collection of setup code
+ *  to get the board up and running.
+ *    ---Dan
+ */
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <platforms/gemini.h>
+#include <asm/ppc_asm.h>
+
+#define HID0_ABE (1<<3)
+
+/*
+ *  On 750's the MMU is on when Linux is booted, so we need to clear out the
+ *  bootloader's BAT settings, make sure we're in supervisor state (gotcha!),
+ *  and turn off the MMU.
+ *
+ */
+
+_GLOBAL(gemini_prom_init)
+#ifdef CONFIG_SMP
+	/* Since the MMU's on, get stuff in rom space that we'll need */
+	lis	r4,GEMINI_CPUSTAT@h
+	ori	r4,r4,GEMINI_CPUSTAT@l
+	lbz	r5,0(r4)
+	andi.	r5,r5,3
+	mr	r24,r5		/* cpu # used later on */
+#endif
+	mfmsr	r4
+	li	r3,MSR_PR	/* ensure supervisor! */
+	ori	r3,r3,MSR_IR|MSR_DR
+	andc	r4,r4,r3
+	mtmsr	r4
+	isync
+#if 0
+	/* zero out the bats now that the MMU is off */
+prom_no_mmu:	
+	li	r3,0
+        mtspr   IBAT0U,r3
+        mtspr   IBAT0L,r3
+        mtspr   IBAT1U,r3
+        mtspr   IBAT1L,r3
+        mtspr   IBAT2U,r3
+        mtspr   IBAT2L,r3
+        mtspr   IBAT3U,r3
+        mtspr   IBAT3L,r3
+
+        mtspr   DBAT0U,r3
+        mtspr   DBAT0L,r3
+        mtspr   DBAT1U,r3
+        mtspr   DBAT1L,r3
+        mtspr   DBAT2U,r3
+	mtspr   DBAT2L,r3
+        mtspr   DBAT3U,r3
+        mtspr   DBAT3L,r3
+#endif
+
+	/* the bootloader (as far as I'm currently aware) doesn't mess with page
+	   tables, but since we're already here, might as well zap these, too */
+	li	r4,0
+	mtspr	SDR1,r4
+
+	li	r4,16
+	mtctr	r4
+	li	r3,0
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,1
+	bdnz	3b
+
+#ifdef CONFIG_SMP
+	/* The 750 book (and Mot/IBM support) says that this will "assist" snooping
+	   when in SMP.  Not sure yet whether this should stay or leave... */
+	mfspr	r4,HID0
+	ori	r4,r4,HID0_ABE
+	mtspr	HID0,r4
+	sync
+#endif /* CONFIG_SMP */
+	blr
+
+/*  apparently, SMon doesn't pay attention to HID0[SRST].  Disable the MMU and
+    branch to 0xfff00100 */
+_GLOBAL(_gemini_reboot)
+	lis	r5,GEMINI_BOOT_INIT@h
+	ori	r5,r5,GEMINI_BOOT_INIT@l
+	li	r6,MSR_IP
+	mtspr	SRR0,r5
+	mtspr	SRR1,r6
+	rfi
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/gemini_serial.h linux/arch/ppc/platforms/gemini_serial.h
--- linux.orig/arch/ppc/platforms/gemini_serial.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/gemini_serial.h	2002-08-12 22:14:16.000000000 +0000
@@ -0,0 +1,44 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+#ifdef __KERNEL__
+#ifndef __ASMPPC_GEMINI_SERIAL_H
+#define __ASMPPC_GEMINI_SERIAL_H
+
+#include <linux/config.h>
+#include <platforms/gemini.h>
+
+#ifdef CONFIG_SERIAL_MANY_PORTS
+#define RS_TABLE_SIZE  64
+#else
+#define RS_TABLE_SIZE  4
+#endif
+
+/* Rate for the 24.576 Mhz clock for the onboard serial chip */
+#define BASE_BAUD  (24576000 / 16)
+
+#ifdef CONFIG_SERIAL_DETECT_IRQ
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST|ASYNC_AUTO_IRQ)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_AUTO_IRQ)
+#else
+#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF|ASYNC_SKIP_TEST)
+#define STD_COM4_FLAGS (ASYNC_BOOT_AUTOCONF)
+#endif
+
+#define STD_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, GEMINI_SERIAL_A, 15, STD_COM_FLAGS }, /* ttyS0 */ \
+        { 0, BASE_BAUD, GEMINI_SERIAL_B, 14, STD_COM_FLAGS }, /* ttyS1 */ \
+
+#ifdef CONFIG_GEMINI_PU32
+#define PU32_SERIAL_PORT_DEFNS \
+        { 0, BASE_BAUD, NULL, 0, STD_COM_FLAGS },
+#else
+#define PU32_SERIAL_PORT_DEFNS
+#endif
+
+#define SERIAL_PORT_DFNS \
+        STD_SERIAL_PORT_DEFNS \
+        PU32_SERIAL_PORT_DEFNS
+
+#endif
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/gemini_setup.c linux/arch/ppc/platforms/gemini_setup.c
--- linux.orig/arch/ppc/platforms/gemini_setup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/gemini_setup.c	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,584 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platforms/setup.c
+ *
+ *  Copyright (C) 1995 Linus Torvalds
+ *  Adapted from 'alpha' version by Gary Thomas
+ *  Modified by Cort Dougan (cort@cs.nmt.edu)
+ *  Synergy Microsystems board support by Dan Cox (dan@synergymicro.com)
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <linux/time.h>
+#include <linux/kdev_t.h>
+#include <linux/types.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/console.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/page.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/m48t35.h>
+#include <platforms/gemini.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/bootinfo.h>
+
+void gemini_find_bridges(void);
+static int gemini_get_clock_speed(void);
+extern void gemini_pcibios_fixup(void);
+
+static char *gemini_board_families[] = {
+  "VGM", "VSS", "KGM", "VGR", "VCM", "VCS", "KCM", "VCR"
+};
+static int gemini_board_count = sizeof(gemini_board_families) /
+                                 sizeof(gemini_board_families[0]);
+
+static unsigned int cpu_7xx[16] = {
+	0, 15, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 16, 12, 7, 0
+};
+static unsigned int cpu_6xx[16] = {
+	0, 0, 14, 0, 0, 13, 5, 9, 6, 11, 8, 10, 0, 12, 7, 0
+};
+
+/*
+ * prom_init is the Gemini version of prom.c:prom_init.  We only need
+ * the BSS clearing code, so I copied that out of prom.c.  This is a
+ * lot simpler than hacking prom.c so it will build with Gemini. -VAL
+ */
+
+#define PTRRELOC(x)	((typeof(x))((unsigned long)(x) + offset))
+
+unsigned long
+prom_init(void)
+{
+	unsigned long offset = reloc_offset();
+	unsigned long phys;
+	extern char __bss_start, _end;
+
+	/* First zero the BSS -- use memset, some arches don't have
+	 * caches on yet */
+	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+
+ 	/* Default */
+ 	phys = offset + KERNELBASE;
+
+	gemini_prom_init();
+
+	return phys;
+}
+
+int
+gemini_show_cpuinfo(struct seq_file *m)
+{
+	unsigned char reg, rev;
+	char *family;
+	unsigned int type;
+
+	reg = readb(GEMINI_FEAT);
+	family = gemini_board_families[((reg>>4) & 0xf)];
+	if (((reg>>4) & 0xf) > gemini_board_count)
+		printk(KERN_ERR "cpuinfo(): unable to determine board family\n");
+
+	reg = readb(GEMINI_BREV);
+	type = (reg>>4) & 0xf;
+	rev = reg & 0xf;
+
+	reg = readb(GEMINI_BECO);
+
+	seq_printf(m, "machine\t\t: Gemini %s%d, rev %c, eco %d\n", 
+		   family, type, (rev + 'A'), (reg & 0xf));
+
+	seq_printf(m, "board\t\t: Gemini %s", family);
+	if (type > 9)
+		seq_printf(m, "%c", (type - 10) + 'A');
+	else
+		seq_printf(m, "%d", type);
+
+	seq_printf(m, ", rev %c, eco %d\n", (rev + 'A'), (reg & 0xf));
+
+	seq_printf(m, "clock\t\t: %dMhz\n", gemini_get_clock_speed());
+
+	return 0;
+}
+
+static u_char gemini_openpic_initsenses[] = {
+	1,
+	1,
+	1,
+	1,
+	0,
+	0,
+	1, /* remainder are level-triggered */
+};
+
+#define GEMINI_MPIC_ADDR (0xfcfc0000)
+#define GEMINI_MPIC_PCI_CFG (0x80005800)
+
+void __init gemini_openpic_init(void)
+{
+
+	OpenPIC_Addr = (volatile struct OpenPIC *)
+		grackle_read(GEMINI_MPIC_PCI_CFG + 0x10);
+	OpenPIC_InitSenses = gemini_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof( gemini_openpic_initsenses );
+
+	ioremap( GEMINI_MPIC_ADDR, OPENPIC_SIZE);
+}
+
+
+extern unsigned long loops_per_jiffy;
+extern int root_mountflags;
+extern char cmd_line[];
+
+void
+gemini_heartbeat(void)
+{
+	static unsigned long led = GEMINI_LEDBASE+(4*8);
+	static char direction = 8;
+
+	/* We only want to do this on 1 CPU */
+	if (smp_processor_id())
+		return;
+	*(char *)led = 0;
+	if ( (led + direction) > (GEMINI_LEDBASE+(7*8)) ||
+	     (led + direction) < (GEMINI_LEDBASE+(4*8)) )
+		direction *= -1;
+	led += direction;
+	*(char *)led = 0xff;
+	ppc_md.heartbeat_count = ppc_md.heartbeat_reset;
+}
+
+void __init gemini_setup_arch(void)
+{
+	extern char cmd_line[];
+
+
+	loops_per_jiffy = 50000000/HZ;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	/* bootable off CDROM */
+	if (initrd_start)
+		ROOT_DEV = MKDEV(SCSI_CDROM_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(0x0801);
+
+	/* nothing but serial consoles... */
+	sprintf(cmd_line, "%s console=ttyS0", cmd_line);
+
+	printk("Boot arguments: %s\n", cmd_line);
+
+	ppc_md.heartbeat = gemini_heartbeat;
+	ppc_md.heartbeat_reset = HZ/8;
+	ppc_md.heartbeat_count = 1;
+
+	/* Lookup PCI hosts */
+	gemini_find_bridges();
+	/* take special pains to map the MPIC, since it isn't mapped yet */
+	gemini_openpic_init();
+	/* start the L2 */
+	gemini_init_l2();
+}
+
+
+int
+gemini_get_clock_speed(void)
+{
+	unsigned long hid1, pvr;
+	int clock;
+
+	pvr = mfspr(PVR);
+	hid1 = (mfspr(HID1) >> 28) & 0xf;
+	if (PVR_VER(pvr) == 8 ||
+	    PVR_VER(pvr) == 12)
+		hid1 = cpu_7xx[hid1];
+	else
+		hid1 = cpu_6xx[hid1];
+
+	switch((readb(GEMINI_BSTAT) & 0xc) >> 2) {
+
+	case 0:
+	default:
+		clock = (hid1*100)/3;
+		break;
+
+	case 1:
+		clock = (hid1*125)/3;
+		break;
+
+	case 2:
+		clock = (hid1*50);
+		break;
+	}
+
+	return clock;
+}
+
+void __init gemini_init_l2(void)
+{
+        unsigned char reg, brev, fam, creg;
+        unsigned long cache;
+        unsigned long pvr;
+
+        reg = readb(GEMINI_L2CFG);
+        brev = readb(GEMINI_BREV);
+        fam = readb(GEMINI_FEAT);
+        pvr = mfspr(PVR);
+
+        switch(PVR_VER(pvr)) {
+
+        case 8:
+                if (reg & 0xc0)
+                        cache = (((reg >> 6) & 0x3) << 28);
+                else
+                        cache = 0x3 << 28;
+
+#ifdef CONFIG_SMP
+                /* Pre-3.0 processor revs had snooping errata.  Leave
+                   their L2's disabled with SMP. -- Dan */
+                if (PVR_CFG(pvr) < 3) {
+                        printk("Pre-3.0 750; L2 left disabled!\n");
+                        return;
+                }
+#endif /* CONFIG_SMP */
+
+                /* Special case: VGM5-B's came before L2 ratios were set on
+                   the board.  Processor speed shouldn't be too high, so
+                   set L2 ratio to 1:1.5.  */
+                if ((brev == 0x51) && ((fam & 0xa0) >> 4) == 0)
+                        reg |= 1;
+
+                /* determine best cache ratio based upon what the board
+                   tells us (which sometimes _may_ not be true) and
+                   the processor speed. */
+                else {
+                        if (gemini_get_clock_speed() > 250)
+                                reg = 2;
+                }
+                break;
+        case 12:
+	{
+		static unsigned long l2_size_val = 0;
+
+		if (!l2_size_val)
+			l2_size_val = _get_L2CR();
+		cache = l2_size_val;
+                break;
+	}
+        case 4:
+        case 9:
+                creg = readb(GEMINI_CPUSTAT);
+                if (((creg & 0xc) >> 2) != 1)
+                        printk("Dual-604 boards don't support the use of L2\n");
+                else
+                        writeb(1, GEMINI_L2CFG);
+                return;
+        default:
+                printk("Unknown processor; L2 left disabled\n");
+                return;
+        }
+
+        cache |= ((1<<reg) << 25);
+        cache |= (L2CR_L2RAM_MASK|L2CR_L2CTL|L2CR_L2DO);
+        _set_L2CR(0);
+        _set_L2CR(cache | L2CR_L2E);
+
+}
+
+void
+gemini_restart(char *cmd)
+{
+	__cli();
+	/* make a clean restart, not via the MPIC */
+	_gemini_reboot();
+	for(;;);
+}
+
+void
+gemini_power_off(void)
+{
+	for(;;);
+}
+
+void
+gemini_halt(void)
+{
+	gemini_restart(NULL);
+}
+
+void __init gemini_init_IRQ(void)
+{
+	/* gemini has no 8259 */
+	openpic_init(1, 0, 0, -1);
+}
+
+#define gemini_rtc_read(x)       (readb(GEMINI_RTC+(x)))
+#define gemini_rtc_write(val,x)  (writeb((val),(GEMINI_RTC+(x))))
+
+/* ensure that the RTC is up and running */
+long __init gemini_time_init(void)
+{
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+
+	if ( reg & M48T35_RTC_STOPPED ) {
+		printk(KERN_INFO "M48T35 real-time-clock was stopped. Now starting...\n");
+		gemini_rtc_write((reg & ~(M48T35_RTC_STOPPED)), M48T35_RTC_CONTROL);
+		gemini_rtc_write((reg | M48T35_RTC_SET), M48T35_RTC_CONTROL);
+	}
+	return 0;
+}
+
+#undef DEBUG_RTC
+
+unsigned long
+gemini_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned char reg;
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+	gemini_rtc_write((reg|M48T35_RTC_READ), M48T35_RTC_CONTROL);
+#ifdef DEBUG_RTC
+	printk("get rtc: reg = %x\n", reg);
+#endif
+
+	do {
+		sec = gemini_rtc_read(M48T35_RTC_SECONDS);
+		min = gemini_rtc_read(M48T35_RTC_MINUTES);
+		hour = gemini_rtc_read(M48T35_RTC_HOURS);
+		day = gemini_rtc_read(M48T35_RTC_DOM);
+		mon = gemini_rtc_read(M48T35_RTC_MONTH);
+		year = gemini_rtc_read(M48T35_RTC_YEAR);
+	} while( sec != gemini_rtc_read(M48T35_RTC_SECONDS));
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+#ifdef DEBUG_RTC
+	printk("get rtc: sec=%x, min=%x, hour=%x, day=%x, mon=%x, year=%x\n", 
+	       sec, min, hour, day, mon, year);
+#endif
+
+	return mktime( year, mon, day, hour, min, sec );
+}
+
+
+int
+gemini_set_rtc_time( unsigned long now )
+{
+	unsigned char reg;
+	struct rtc_time tm;
+
+	to_tm( now, &tm );
+
+	reg = gemini_rtc_read(M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: reg = %x\n", reg);
+#endif
+
+	gemini_rtc_write((reg|M48T35_RTC_SET), M48T35_RTC_CONTROL);
+#if DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	tm.tm_year -= 1900;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+#ifdef DEBUG_RTC
+	printk("set rtc: tm vals - sec=%x, min=%x, hour=%x, mon=%x, mday=%x, year=%x\n",
+	       tm.tm_sec, tm.tm_min, tm.tm_hour, tm.tm_mon, tm.tm_mday, tm.tm_year);
+#endif
+
+	gemini_rtc_write(tm.tm_sec, M48T35_RTC_SECONDS);
+	gemini_rtc_write(tm.tm_min, M48T35_RTC_MINUTES);
+	gemini_rtc_write(tm.tm_hour, M48T35_RTC_HOURS);
+	gemini_rtc_write(tm.tm_mday, M48T35_RTC_DOM);
+	gemini_rtc_write(tm.tm_mon, M48T35_RTC_MONTH);
+	gemini_rtc_write(tm.tm_year, M48T35_RTC_YEAR);
+
+	/* done writing */
+	gemini_rtc_write(reg, M48T35_RTC_CONTROL);
+
+	if ((time_state == TIME_ERROR) || (time_state == TIME_BAD))
+		time_state = TIME_OK;
+
+	return 0;
+}
+
+/*  use the RTC to determine the decrementer count */
+void __init gemini_calibrate_decr(void)
+{
+	int freq, divisor;
+	unsigned char reg;
+
+	/* determine processor bus speed */
+	reg = readb(GEMINI_BSTAT);
+
+	switch(((reg & 0x0c)>>2)&0x3) {
+	case 0:
+	default:
+		freq = 66667;
+		break;
+	case 1:
+		freq = 83000;
+		break;
+	case 2:
+		freq = 100000;
+		break;
+	}
+
+	freq *= 1000;
+	divisor = 4;
+	tb_ticks_per_jiffy = freq / HZ / divisor;
+	tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+}
+
+unsigned long __init gemini_find_end_of_memory(void)
+{
+	unsigned long total;
+	unsigned char reg;
+
+	reg = readb(GEMINI_MEMCFG);
+	total = ((1<<((reg & 0x7) - 1)) *
+		 (8<<((reg >> 3) & 0x7)));
+	total *= (1024*1024);
+	return total;
+}
+
+static void __init
+gemini_map_io(void)
+{
+	io_block_mapping(0xf0000000, 0xf0000000, 0x10000000, _PAGE_IO);
+	io_block_mapping(0x80000000, 0x80000000, 0x10000000, _PAGE_IO);
+}
+
+#ifdef CONFIG_SMP
+static int
+smp_gemini_probe(void)
+{
+	int i, nr;
+
+        nr = (readb(GEMINI_CPUSTAT) & GEMINI_CPU_COUNT_MASK) >> 2;
+	if (nr == 0)
+		nr = 4;
+
+	if (nr > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < nr; ++i)
+			smp_hw_index[i] = i;
+	}
+
+	return nr;
+}
+
+static void
+smp_gemini_kick_cpu(int nr)
+{
+	openpic_reset_processor_phys(1 << nr);
+	openpic_reset_processor_phys(0);
+}
+
+static void
+smp_gemini_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+	if (cpu_nr > 0)
+		gemini_init_l2();
+}
+
+static struct smp_ops_t gemini_smp_ops = {
+	smp_openpic_message_pass,
+	smp_gemini_probe,
+	smp_gemini_kick_cpu,
+	smp_gemini_setup_cpu,
+};
+#endif /* CONFIG_SMP */
+
+void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+			  unsigned long r6, unsigned long r7)
+{
+	int i;
+
+	for(i = 0; i < GEMINI_LEDS; i++)
+		gemini_led_off(i);
+
+	ISA_DMA_THRESHOLD = 0;
+	DMA_MODE_READ = 0;
+	DMA_MODE_WRITE = 0;
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if ( r4 )
+	{
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif
+
+	ppc_md.setup_arch = gemini_setup_arch;
+	ppc_md.show_cpuinfo = gemini_show_cpuinfo;
+	ppc_md.irq_cannonicalize = NULL;
+	ppc_md.init_IRQ = gemini_init_IRQ;
+	ppc_md.get_irq = openpic_get_irq;
+	ppc_md.init = NULL;
+
+	ppc_md.restart = gemini_restart;
+	ppc_md.power_off = gemini_power_off;
+	ppc_md.halt = gemini_halt;
+
+	ppc_md.time_init = gemini_time_init;
+	ppc_md.set_rtc_time = gemini_set_rtc_time;
+	ppc_md.get_rtc_time = gemini_get_rtc_time;
+	ppc_md.calibrate_decr = gemini_calibrate_decr;
+
+	ppc_md.find_end_of_memory = gemini_find_end_of_memory;
+	ppc_md.setup_io_mappings = gemini_map_io;
+
+	/* no keyboard/mouse/video stuff yet.. */
+	ppc_md.kbd_setkeycode = NULL;
+	ppc_md.kbd_getkeycode = NULL;
+	ppc_md.kbd_translate = NULL;
+	ppc_md.kbd_unexpected_up = NULL;
+	ppc_md.kbd_leds = NULL;
+	ppc_md.kbd_init_hw = NULL;
+	ppc_md.ppc_kbd_sysrq_xlate = NULL;
+	ppc_md.pcibios_fixup_bus = gemini_pcibios_fixup;
+
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops = &gemini_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/ivms8.h linux/arch/ppc/platforms/ivms8.h
--- linux.orig/arch/ppc/platforms/ivms8.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/ivms8.h	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,59 @@
+/*
+ * BK Id: SCCS/s.ivms8.h 1.8 10/26/01 10:14:09 trini
+ */
+/*
+ * Speech Design Integrated Voicemail board specific definitions
+ * - IVMS8  (small,  8 channels)
+ * - IVML24 (large, 24 channels)
+ *
+ * In 2.5 when we force a new bootloader, we can merge these two, and add
+ * in _MACH_'s for them. -- Tom
+ *
+ * Copyright (c) 2000, 2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_IVMS8_H__
+#define __ASM_IVMS8_H__
+
+#include <linux/config.h>
+
+#include <asm/ppcboot.h>
+
+#define IVMS_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
+#define IVMS_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
+
+#define IMAP_ADDR	IVMS_IMMR_BASE	/* phys. base address of IMMR area */
+#define IMAP_SIZE	IVMS_IMAP_SIZE	/* mapped size of IMMR area */
+
+#define PCMCIA_MEM_ADDR	((uint)0xFE100000)
+#define PCMCIA_MEM_SIZE	((uint)(64 * 1024))
+
+#define FEC_INTERRUPT	 9		/* = SIU_LEVEL4 */
+#define IDE0_INTERRUPT	10		/* = IRQ5 */
+#define CPM_INTERRUPT	11		/* = SIU_LEVEL5 (was: SIU_LEVEL2) */
+#define PHY_INTERRUPT	12		/* = IRQ6 */
+
+/* override the default number of IDE hardware interfaces */
+#define MAX_HWIFS	1
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0x0000	/* Offset in PCMCIA memory */
+#define IDE0_DATA_REG_OFFSET		0x0000
+#define IDE0_ERROR_REG_OFFSET		0x0081
+#define IDE0_NSECTOR_REG_OFFSET		0x0082
+#define IDE0_SECTOR_REG_OFFSET		0x0083
+#define IDE0_LCYL_REG_OFFSET		0x0084
+#define IDE0_HCYL_REG_OFFSET		0x0085
+#define IDE0_SELECT_REG_OFFSET		0x0086
+#define IDE0_STATUS_REG_OFFSET		0x0087
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/* We don't use the 8259. */
+#define NR_8259_INTS	0
+
+#endif /* __ASM_IVMS8_H__ */
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/mbx.h linux/arch/ppc/platforms/mbx.h
--- linux.orig/arch/ppc/platforms/mbx.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/mbx.h	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,98 @@
+/*
+ * BK Id: SCCS/s.mbx.h 1.11 08/17/01 15:23:17 paulus
+ */
+/*
+ * A collection of structures, addresses, and values associated with
+ * the Motorola MBX boards.  This was originally created for the
+ * MBX860, and probably needs revisions for other boards (like the 821).
+ * When this file gets out of control, we can split it up into more
+ * meaningful pieces.
+ *
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_MBX_DEFS
+#define __MACH_MBX_DEFS
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * EPPC-Bug starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_tag;		/* Should be 0x42444944 "BDID" */
+	unsigned int	bi_size;	/* Size of this structure */
+	unsigned int	bi_revision;	/* revision of this structure */
+	unsigned int	bi_bdate;	/* EPPCbug date, i.e. 0x11061997 */
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned int	bi_clun;	/* Boot device controller */
+	unsigned int	bi_dlun;	/* Boot device logical dev */
+
+	/* These fields are not part of the board information structure
+	 * provided by the boot rom.  They are filled in by embed_config.c
+	 * so we have the information consistent with other platforms.
+	 */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+/* Memory map for the MBX as configured by EPPC-Bug.  We could reprogram
+ * The SIU and PCI bridge, and try to use larger MMU pages, but the
+ * performance gain is not measureable and it certainly complicates the
+ * generic MMU model.
+ *
+ * In a effort to minimize memory usage for embedded applications, any
+ * PCI driver or ISA driver must request or map the region required by
+ * the device.  For convenience (and since we can map up to 4 Mbytes with
+ * a single page table page), the MMU initialization will map the
+ * NVRAM, Status/Control registers, CPM Dual Port RAM, and the PCI
+ * Bridge CSRs 1:1 into the kernel address space.
+ */
+#define PCI_ISA_IO_ADDR		((unsigned)0x80000000)
+#define PCI_ISA_IO_SIZE		((uint)(512 * 1024 * 1024))
+#define PCI_IDE_ADDR		((unsigned)0x81000000)
+#define PCI_ISA_MEM_ADDR	((unsigned)0xc0000000)
+#define PCI_ISA_MEM_SIZE	((uint)(512 * 1024 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0xe0000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024 * 1024))
+#define PCMCIA_DMA_ADDR		((uint)0xe4000000)
+#define PCMCIA_DMA_SIZE		((uint)(64 * 1024 * 1024))
+#define PCMCIA_ATTRB_ADDR	((uint)0xe8000000)
+#define PCMCIA_ATTRB_SIZE	((uint)(64 * 1024 * 1024))
+#define PCMCIA_IO_ADDR		((uint)0xec000000)
+#define PCMCIA_IO_SIZE		((uint)(64 * 1024 * 1024))
+#define NVRAM_ADDR		((uint)0xfa000000)
+#define NVRAM_SIZE		((uint)(1 * 1024 * 1024))
+#define MBX_CSR_ADDR		((uint)0xfa100000)
+#define MBX_CSR_SIZE		((uint)(1 * 1024 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCI_CSR_ADDR		((uint)0xfa210000)
+#define PCI_CSR_SIZE		((uint)(64 * 1024))
+
+/* Map additional physical space into well known virtual addresses.  Due
+ * to virtual address mapping, these physical addresses are not accessible
+ * in a 1:1 virtual to physical mapping.
+ */
+#define ISA_IO_VIRT_ADDR	((uint)0xfa220000)
+#define ISA_IO_VIRT_SIZE	((uint)64 * 1024)
+
+/* Interrupt assignments.
+ * These are defined (and fixed) by the MBX hardware implementation.
+ */
+#define POWER_FAIL_INT	SIU_IRQ0	/* Power fail */
+#define TEMP_HILO_INT	SIU_IRQ1	/* Temperature sensor */
+#define QSPAN_INT	SIU_IRQ2	/* PCI Bridge (DMA CTLR?) */
+#define ISA_BRIDGE_INT	SIU_IRQ3	/* All those PC things */
+#define COMM_L_INT	SIU_IRQ6	/* MBX Comm expansion connector pin */
+#define STOP_ABRT_INT	SIU_IRQ7	/* Stop/Abort header pin */
+#endif /* !__ASSEMBLY__ */
+
+/* The MBX uses the 8259.
+*/
+#define NR_8259_INTS	16
+
+#endif
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/oak.h linux/arch/ppc/platforms/oak.h
--- linux.orig/arch/ppc/platforms/oak.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/oak.h	2002-08-12 22:14:09.000000000 +0000
@@ -0,0 +1,65 @@
+/*
+ * BK Id: SCCS/s.oak.h 1.12 10/11/01 13:05:07 trini
+ */
+/*
+ *
+ *    Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oak.h
+ *
+ *    Description:
+ *	Macros, definitions, and data structures specific to the IBM PowerPC
+ *      403G{A,B,C,CX} "Oak" evaluation board. Anything specific to the pro-
+ *      cessor itself is defined elsewhere.
+ *
+ */
+
+#ifdef __KERNEL__
+#ifndef	__OAK_H__
+#define	__OAK_H__
+
+#define _IO_BASE	0
+#define _ISA_MEM_BASE	0
+#define PCI_DRAM_OFFSET	0
+
+/* Memory map for the "Oak" evaluation board */
+
+#define	PPC403SPU_IO_BASE      	0x40000000	/* 403 On-chip serial port */
+#define	PPC403SPU_IO_SIZE      	0x00000008
+#define	OAKSERIAL_IO_BASE	0x7E000000	/* NS16550DV serial port */
+#define	OAKSERIAL_IO_SIZE	0x00000008
+#define	OAKNET_IO_BASE		0xF4000000	/* NS83902AV Ethernet */
+#define	OAKNET_IO_SIZE		0x00000040
+#define	OAKPROM_IO_BASE		0xFFFE0000	/* AMD 29F010 Flash ROM */
+#define	OAKPROM_IO_SIZE		0x00020000
+
+
+/* Interrupt assignments fixed by the hardware implementation */
+
+/* This is annoying kbuild-2.4 problem. -- Tom */
+
+#define	PPC403SPU_RX_INT	4	/* AIC_INT4 */
+#define	PPC403SPU_TX_INT	5	/* AIC_INT5 */
+#define	OAKNET_INT		27	/* AIC_INT27 */
+#define	OAKSERIAL_INT		28	/* AIC_INT28 */
+
+#ifndef __ASSEMBLY__
+/*
+ * Data structure defining board information maintained by the boot
+ * ROM on IBM's "Oak" evaluation board. An effort has been made to
+ * keep the field names consistent with the 8xx 'bd_t' board info
+ * structures.
+ */
+
+typedef struct board_info {
+	unsigned char	 bi_s_version[4];	/* Version of this structure */
+	unsigned char	 bi_r_version[30];	/* Version of the IBM ROM */
+	unsigned int	 bi_memsize;		/* DRAM installed, in bytes */
+	unsigned char	 bi_enetaddr[6];	/* Ethernet MAC address */
+	unsigned int	 bi_intfreq;		/* Processor speed, in Hz */
+	unsigned int	 bi_busfreq;		/* Bus speed, in Hz */
+} bd_t;
+
+#endif /* !__ASSEMBLY__ */
+#endif /* __OAK_H__ */
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/oak_setup.c linux/arch/ppc/platforms/oak_setup.c
--- linux.orig/arch/ppc/platforms/oak_setup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/oak_setup.c	2002-08-12 22:14:09.000000000 +0000
@@ -0,0 +1,291 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oak_setup.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ *      <dan@net4x.com>.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+
+#include <asm/processor.h>
+#include <asm/board.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+#include <asm/bootinfo.h>
+#include <asm/ppc4xx_pic.h>
+#include <asm/time.h>
+
+#include "oak_setup.h"
+
+/* Function Prototypes */
+
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init oak_init()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *   r3 - Optional pointer to a board information structure.
+ *   r4 - Optional pointer to the physical starting address of the init RAM
+ *        disk.
+ *   r5 - Optional pointer to the physical ending address of the init RAM
+ *        disk.
+ *   r6 - Optional pointer to the physical starting address of any kernel
+ *        command-line parameters.
+ *   r7 - Optional pointer to the physical ending address of any kernel
+ *        command-line parameters.
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	      unsigned long r6, unsigned long r7)
+{
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+	}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+ 		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+	}
+
+	/* Initialize machine-dependency vectors */
+
+	ppc_md.setup_arch	 	= oak_setup_arch;
+	ppc_md.show_percpuinfo	 	= oak_show_percpuinfo;
+	ppc_md.irq_cannonicalize 	= NULL;
+	ppc_md.init_IRQ		 	= oak_init_IRQ;
+	ppc_md.get_irq		 	= oak_get_irq;
+	ppc_md.init		 	= NULL;
+
+	ppc_md.restart		 	= oak_restart;
+	ppc_md.power_off	 	= oak_power_off;
+	ppc_md.halt		 	= oak_halt;
+
+	ppc_md.time_init	 	= oak_time_init;
+	ppc_md.set_rtc_time	 	= oak_set_rtc_time;
+	ppc_md.get_rtc_time	 	= oak_get_rtc_time;
+	ppc_md.calibrate_decr	 	= oak_calibrate_decr;
+
+	ppc_md.kbd_setkeycode    	= NULL;
+	ppc_md.kbd_getkeycode    	= NULL;
+	ppc_md.kbd_translate     	= NULL;
+	ppc_md.kbd_unexpected_up 	= NULL;
+	ppc_md.kbd_leds          	= NULL;
+	ppc_md.kbd_init_hw       	= NULL;
+	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_setup_arch(void)
+{
+	/* XXX - Implement me */
+}
+
+/*
+ * int oak_show_percpuinfo()
+ *
+ * Description:
+ *   This routine pretty-prints the platform's internal CPU and bus clock
+ *   frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ *  *buffer - Buffer into which CPU and bus clock frequencies are to be
+ *            printed.
+ *
+ * Output(s):
+ *  *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ *   on error.
+ */
+int
+oak_show_percpuinfo(struct seq_file *m, int i)
+{
+	bd_t *bp = (bd_t *)__res;
+
+	seq_printf(m, "clock\t\t: %dMHz\n"
+		   "bus clock\t\t: %dMHz\n",
+		   bp->bi_intfreq / 1000000,
+		   bp->bi_busfreq / 1000000);
+
+	return 0;
+}
+
+/*
+ * Document me.
+ */
+void __init
+oak_init_IRQ(void)
+{
+	int i;
+
+	ppc4xx_pic_init();
+
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].handler = ppc4xx_pic;
+	}
+
+	return;
+}
+
+/*
+ * Document me.
+ */
+int
+oak_get_irq(struct pt_regs *regs)
+{
+	return (ppc4xx_pic_get_irq(regs));
+}
+
+/*
+ * Document me.
+ */
+void
+oak_restart(char *cmd)
+{
+	abort();
+}
+
+/*
+ * Document me.
+ */
+void
+oak_power_off(void)
+{
+	oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+oak_halt(void)
+{
+	oak_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+long __init
+oak_time_init(void)
+{
+	/* XXX - Implement me */
+	return 0;
+}
+
+/*
+ * Document me.
+ */
+int __init
+oak_set_rtc_time(unsigned long time)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+oak_get_rtc_time(void)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * void __init oak_calibrate_decr()
+ *
+ * Description:
+ *   This routine retrieves the internal processor frequency from the board
+ *   information structure, sets up the kernel timer decrementer based on
+ *   that value, enables the 403 programmable interval timer (PIT) and sets
+ *   it up for auto-reload.
+ *
+ * Input(s):
+ *   N/A
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+oak_calibrate_decr(void)
+{
+	unsigned int freq;
+	bd_t *bip = (bd_t *)__res;
+
+	freq = bip->bi_intfreq;
+
+	decrementer_count = freq / HZ;
+	count_period_num = 1;
+	count_period_den = freq;
+
+	/* Enable the PIT and set auto-reload of its value */
+
+	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+	/* Clear any pending timer interrupts */
+
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/oak_setup.h linux/arch/ppc/platforms/oak_setup.h
--- linux.orig/arch/ppc/platforms/oak_setup.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/oak_setup.h	2002-08-12 22:14:16.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * BK Id: SCCS/s.oak_setup.h 1.5 05/17/01 18:14:21 cort
+ */
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: oak_setup.h
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ *      <dan@netx4.com>.
+ *
+ */
+
+#ifndef	__OAK_SETUP_H__
+#define	__OAK_SETUP_H__
+
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned char	 __res[sizeof(bd_t)];
+
+extern void		 oak_init(unsigned long r3,
+				  unsigned long ird_start,
+				  unsigned long ird_end,
+				  unsigned long cline_start,
+				  unsigned long cline_end);
+extern void		 oak_setup_arch(void);
+extern int		 oak_setup_residual(char *buffer);
+extern void		 oak_init_IRQ(void);
+extern int		 oak_get_irq(struct pt_regs *regs);
+extern void		 oak_restart(char *cmd);
+extern void		 oak_power_off(void);
+extern void		 oak_halt(void);
+extern void		 oak_time_init(void);
+extern int		 oak_set_rtc_time(unsigned long now);
+extern unsigned long	 oak_get_rtc_time(void);
+extern void		 oak_calibrate_decr(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OAK_SETUP_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_backlight.c linux/arch/ppc/platforms/pmac_backlight.c
--- linux.orig/arch/ppc/platforms/pmac_backlight.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_backlight.c	2002-08-12 22:14:19.000000000 +0000
@@ -0,0 +1,150 @@
+/*
+ * BK Id: SCCS/s.pmac_backlight.c 1.10 12/01/01 20:09:06 benh
+ */
+/*
+ * Miscellaneous procedures for dealing with the PowerMac hardware.
+ * Contains support for the backlight.
+ * 
+ *   Copyright (C) 2000 Benjamin Herrenschmidt
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/reboot.h>
+#include <linux/nvram.h>
+#include <asm/sections.h>
+#include <asm/ptrace.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+#include <asm/backlight.h>
+
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+static struct backlight_controller *backlighter = NULL;
+static void* backlighter_data = NULL;
+static int backlight_autosave = 0;
+static int backlight_level = BACKLIGHT_MAX;
+static int backlight_enabled = 1;
+
+void __pmac
+register_backlight_controller(struct backlight_controller *ctrler, void *data, char *type)
+{
+	struct device_node* bk_node;
+	char *prop;
+	int valid = 0;
+
+	bk_node = find_devices("backlight");
+	
+#ifdef CONFIG_ADB_PMU
+	/* Special case for the old PowerBook since I can't test on it */
+	backlight_autosave = machine_is_compatible("AAPL,3400/2400")
+		|| machine_is_compatible("AAPL,3500");
+	if ((backlight_autosave
+	     || machine_is_compatible("AAPL,PowerBook1998")
+	     || machine_is_compatible("PowerBook1,1"))
+	    && !strcmp(type, "pmu"))
+		valid = 1;
+#endif
+	if (bk_node) {
+		prop = get_property(bk_node, "backlight-control", NULL);
+		if (prop && !strncmp(prop, type, strlen(type)))
+			valid = 1;
+	}
+	if (!valid)
+		return;
+	backlighter = ctrler;
+	backlighter_data = data;
+	
+	if (bk_node && !backlight_autosave)
+		prop = get_property(bk_node, "bklt", NULL);
+	else
+		prop = NULL;
+	if (prop) {
+		backlight_level = ((*prop)+1) >> 1;
+		if (backlight_level > BACKLIGHT_MAX)
+			backlight_level = BACKLIGHT_MAX;
+	}
+	
+#ifdef CONFIG_ADB_PMU
+	if (backlight_autosave) {
+		struct adb_request req;
+		pmu_request(&req, NULL, 2, 0xd9, 0);
+		while (!req.complete)
+			pmu_poll();
+		backlight_level = req.reply[0] >> 4;
+	}
+#endif
+	if (!backlighter->set_enable(1, backlight_level, data))
+		backlight_enabled = 1;
+
+	printk(KERN_INFO "Registered \"%s\" backlight controller, level: %d/15\n",
+		type, backlight_level);
+}
+
+void __pmac
+unregister_backlight_controller(struct backlight_controller *ctrler, void *data)
+{
+	/* We keep the current backlight level (for now) */
+	if (ctrler == backlighter && data == backlighter_data)
+		backlighter = NULL;
+}
+
+int __pmac
+set_backlight_enable(int enable)
+{
+	int rc;
+	
+	if (!backlighter)
+		return -ENODEV;
+	rc = backlighter->set_enable(enable, backlight_level, backlighter_data);
+	if (!rc)
+		backlight_enabled = enable;
+	return rc;
+}
+
+int __pmac
+get_backlight_enable(void)
+{
+	if (!backlighter)
+		return -ENODEV;
+	return backlight_enabled;
+}
+
+int __pmac
+set_backlight_level(int level)
+{
+	int rc = 0;
+	
+	if (!backlighter)
+		return -ENODEV;
+	if (level < BACKLIGHT_MIN)
+		level = BACKLIGHT_OFF;
+	if (level > BACKLIGHT_MAX)
+		level = BACKLIGHT_MAX;
+	if (backlight_enabled)
+		rc = backlighter->set_level(level, backlighter_data);
+	if (!rc)
+		backlight_level = level;
+	if (!rc && !backlight_autosave) {
+		level <<=1;
+		if (level & 0x10)
+			level |= 0x01;
+		// -- todo: save to property "bklt"
+	}
+	return rc;
+}
+
+int __pmac
+get_backlight_level(void)
+{
+	if (!backlighter)
+		return -ENODEV;
+	return backlight_level;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_feature.c linux/arch/ppc/platforms/pmac_feature.c
--- linux.orig/arch/ppc/platforms/pmac_feature.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_feature.c	2002-08-12 22:14:08.000000000 +0000
@@ -0,0 +1,2139 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platform/pmac_feature.c
+ *
+ *  Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au)
+ *                          Ben. Herrenschmidt (benh@kernel.crashing.org)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *  
+ *  TODO: 
+ *  
+ *   - Replace mdelay with some schedule loop if possible
+ *   - Shorten some obfuscated delays on some routines (like modem
+ *     power)
+ *
+ */
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+#include <asm/sections.h>
+#include <asm/errno.h>
+#include <asm/ohare.h>
+#include <asm/heathrow.h>
+#include <asm/keylargo.h>
+#include <asm/uninorth.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/dbdma.h>
+
+#undef DEBUG_FEATURE
+
+#ifdef DEBUG_FEATURE
+#define DBG(fmt,...) printk(KERN_DEBUG fmt)
+#else
+#define DBG(fmt,...)
+#endif
+
+/* Exported from arch/ppc/kernel/idle.c */
+extern unsigned long powersave_nap;
+
+/*
+ * We use a single global lock to protect accesses. Each driver has
+ * to take care of it's own locking
+ */
+static spinlock_t feature_lock  __pmacdata = SPIN_LOCK_UNLOCKED;
+
+#define LOCK(flags)	spin_lock_irqsave(&feature_lock, flags);
+#define UNLOCK(flags)	spin_unlock_irqrestore(&feature_lock, flags);
+
+/*
+ * Helper functions regarding the various flavors of mac-io
+ */
+ 
+#define MAX_MACIO_CHIPS		2
+
+enum {
+	macio_unknown = 0,
+	macio_grand_central,
+	macio_ohare,
+	macio_ohareII,
+	macio_heathrow,
+	macio_gatwick,
+	macio_paddington,
+	macio_keylargo,
+	macio_pangea
+};
+
+static const char* macio_names[] __pmacdata = 
+{
+	"Unknown",
+	"Grand Central",
+	"OHare",
+	"OHareII",
+	"Heathrow",
+	"Gatwick",
+	"Paddington",
+	"Keylargo",
+	"Pangea"
+};
+
+static struct macio_chip
+{
+	struct device_node*	of_node;
+	int			type;
+	int			rev;
+	volatile u32*		base;
+	unsigned long		flags;
+} macio_chips[MAX_MACIO_CHIPS]  __pmacdata;
+
+#define MACIO_FLAG_SCCA_ON	0x00000001
+#define MACIO_FLAG_SCCB_ON	0x00000002
+#define MACIO_FLAG_SCC_LOCKED	0x00000004
+#define MACIO_FLAG_AIRPORT_ON	0x00000010
+#define MACIO_FLAG_FW_SUPPORTED	0x00000020
+
+static struct macio_chip* __pmac
+macio_find(struct device_node* child, int type)
+{
+	while(child) {
+		int	i;
+	
+		for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++)
+			if (child == macio_chips[i].of_node &&
+			    (!type || macio_chips[i].type == type))
+				return &macio_chips[i];
+		child = child->parent;
+	}
+	return NULL;
+}
+
+#define MACIO_FCR32(macio, r)	((macio)->base + ((r) >> 2))
+#define MACIO_FCR8(macio, r)	(((volatile u8*)((macio)->base)) + (r))
+
+#define MACIO_IN32(r)		(in_le32(MACIO_FCR32(macio,r)))
+#define MACIO_OUT32(r,v)	(out_le32(MACIO_FCR32(macio,r), (v)))
+#define MACIO_BIS(r,v)		(MACIO_OUT32((r), MACIO_IN32(r) | (v)))
+#define MACIO_BIC(r,v)		(MACIO_OUT32((r), MACIO_IN32(r) & ~(v)))
+#define MACIO_IN8(r)		(in_8(MACIO_FCR8(macio,r)))
+#define MACIO_OUT8(r,v)		(out_8(MACIO_FCR8(macio,r), (v)))
+
+/*
+ * Uninorth reg. access. Note that Uni-N regs are big endian
+ */
+ 
+#define UN_REG(r)	(uninorth_base + ((r) >> 2))
+#define UN_IN(r)	(in_be32(UN_REG(r)))
+#define UN_OUT(r,v)	(out_be32(UN_REG(r), (v)))
+#define UN_BIS(r,v)	(UN_OUT((r), UN_IN(r) | (v)))
+#define UN_BIC(r,v)	(UN_OUT((r), UN_IN(r) & ~(v)))
+
+static struct device_node* uninorth_node __pmacdata;
+static u32* uninorth_base __pmacdata;
+static u32 uninorth_rev __pmacdata;
+
+
+/*
+ * For each motherboard family, we have a table of functions pointers
+ * that handle the various features.
+ */
+
+typedef int (*feature_call)(struct device_node* node, int param, int value);
+
+struct feature_table_entry {
+	unsigned int	selector;	
+	feature_call	function;
+};
+
+struct pmac_mb_def
+{
+	const char*			model_string;
+	const char*			model_name;
+	int				model_id;
+	struct feature_table_entry* 	features;
+	unsigned long			board_flags;
+};
+static struct pmac_mb_def pmac_mb __pmacdata;
+
+/*
+ * Here are the chip specific feature functions
+ */
+
+static inline int __pmac
+simple_feature_tweak(struct device_node* node, int type, int reg, u32 mask, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, type);
+	if (!macio)
+		return -ENODEV;
+	LOCK(flags);
+	if (value)
+		MACIO_BIS(reg, mask);
+	else
+		MACIO_BIC(reg, mask);
+	(void)MACIO_IN32(reg);
+	UNLOCK(flags);
+
+	return 0;
+}
+
+static int __pmac
+ohare_htw_scc_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		chan_mask;
+	unsigned long		fcr;
+	unsigned long		flags;
+	int			htw, trans;
+	unsigned long		rmask;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (!strcmp(node->name, "ch-a"))
+		chan_mask = MACIO_FLAG_SCCA_ON;
+	else if (!strcmp(node->name, "ch-b"))
+		chan_mask = MACIO_FLAG_SCCB_ON;
+	else
+		return -ENODEV;
+
+	htw = (macio->type == macio_heathrow || macio->type == macio_paddington
+		|| macio->type == macio_gatwick);
+	/* On these machines, the HRW_SCC_TRANS_EN_N bit mustn't be touched */
+	trans = (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+	    	 pmac_mb.model_id != PMAC_TYPE_YIKES);
+	if (value) {
+#ifdef CONFIG_ADB_PMU
+		if ((param & 0xfff) == PMAC_SCC_IRDA)
+			pmu_enable_irled(1);
+#endif /* CONFIG_ADB_PMU */		
+		LOCK(flags);
+		fcr = MACIO_IN32(OHARE_FCR);
+		/* Check if scc cell need enabling */
+		if (!(fcr & OH_SCC_ENABLE)) {
+			fcr |= OH_SCC_ENABLE;
+			if (htw) {
+				/* Side effect: this will also power up the
+				 * modem, but it's too messy to figure out on which
+				 * ports this controls the tranceiver and on which
+				 * it controls the modem
+				 */
+				if (trans)
+					fcr &= ~HRW_SCC_TRANS_EN_N;
+				MACIO_OUT32(OHARE_FCR, fcr);
+				fcr |= (rmask = HRW_RESET_SCC);
+				MACIO_OUT32(OHARE_FCR, fcr);
+			} else {
+				fcr |= (rmask = OH_SCC_RESET);
+				MACIO_OUT32(OHARE_FCR, fcr);
+			}
+			UNLOCK(flags);
+			(void)MACIO_IN32(OHARE_FCR);
+			mdelay(15);
+			LOCK(flags);
+			fcr &= ~rmask;
+			MACIO_OUT32(OHARE_FCR, fcr);
+		}
+		if (chan_mask & MACIO_FLAG_SCCA_ON)
+			fcr |= OH_SCCA_IO;
+		if (chan_mask & MACIO_FLAG_SCCB_ON)
+			fcr |= OH_SCCB_IO;
+		MACIO_OUT32(OHARE_FCR, fcr);
+		macio->flags |= chan_mask;
+		UNLOCK(flags);
+		if (param & PMAC_SCC_FLAG_XMON)
+			macio->flags |= MACIO_FLAG_SCC_LOCKED;
+	} else {
+		if (macio->flags & MACIO_FLAG_SCC_LOCKED)
+			return -EPERM;
+		LOCK(flags);
+		fcr = MACIO_IN32(OHARE_FCR);
+		if (chan_mask & MACIO_FLAG_SCCA_ON)
+			fcr &= ~OH_SCCA_IO;
+		if (chan_mask & MACIO_FLAG_SCCB_ON)
+			fcr &= ~OH_SCCB_IO;
+		MACIO_OUT32(OHARE_FCR, fcr);
+		if ((fcr & (OH_SCCA_IO | OH_SCCB_IO)) == 0) {
+			fcr &= ~OH_SCC_ENABLE;
+			if (htw && trans)
+				fcr |= HRW_SCC_TRANS_EN_N;
+			MACIO_OUT32(OHARE_FCR, fcr);
+		}
+		macio->flags &= ~(chan_mask);
+		UNLOCK(flags);
+		mdelay(10);
+#ifdef CONFIG_ADB_PMU
+		if ((param & 0xfff) == PMAC_SCC_IRDA)
+			pmu_enable_irled(0);
+#endif /* CONFIG_ADB_PMU */		
+	}
+	return 0;
+}
+
+static int __pmac
+ohare_floppy_enable(struct device_node* node, int param, int value)
+{
+	return simple_feature_tweak(node, macio_ohare,
+		OHARE_FCR, OH_FLOPPY_ENABLE, value);
+}
+
+static int __pmac
+ohare_mesh_enable(struct device_node* node, int param, int value)
+{
+	return simple_feature_tweak(node, macio_ohare,
+		OHARE_FCR, OH_MESH_ENABLE, value);
+}
+
+static int __pmac
+ohare_ide_enable(struct device_node* node, int param, int value)
+{
+	switch(param) {
+	    case 0:
+	    	/* For some reason, setting the bit in set_initial_features()
+	    	 * doesn't stick. I'm still investigating... --BenH.
+	    	 */
+	    	if (value)
+	    		simple_feature_tweak(node, macio_ohare,
+				OHARE_FCR, OH_IOBUS_ENABLE, 1);
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_IDE0_ENABLE, value);
+	    case 1:
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_BAY_IDE_ENABLE, value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static int __pmac
+ohare_ide_reset(struct device_node* node, int param, int value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_IDE0_RESET_N, !value);
+	    case 1:
+		return simple_feature_tweak(node, macio_ohare,
+			OHARE_FCR, OH_IDE1_RESET_N, !value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static int __pmac
+ohare_sleep_state(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio = &macio_chips[0];
+
+	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+		return -EPERM;
+	if (value == 1) {
+		MACIO_BIC(OHARE_FCR, OH_IOBUS_ENABLE);
+	} else if (value == 0) {
+		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+	}
+	
+	return 0;
+}
+
+static int __pmac
+heathrow_modem_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	u8			gpio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, macio_unknown);
+	if (!macio)
+		return -ENODEV;
+	gpio = MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1;
+	if (!value) {
+		LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
+		UNLOCK(flags);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+		mdelay(250);
+	}
+	if (pmac_mb.model_id != PMAC_TYPE_YOSEMITE &&
+	    pmac_mb.model_id != PMAC_TYPE_YIKES) {
+	    	LOCK(flags);
+	    	if (value)
+	    		MACIO_BIC(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+	    	else
+	    		MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+	    	UNLOCK(flags);
+	    	(void)MACIO_IN32(HEATHROW_FCR);
+		mdelay(250);
+	}
+	if (value) {
+		LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(HRW_GPIO_MODEM_RESET, gpio | 1);
+		(void)MACIO_IN8(HRW_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250);
+	}
+	return 0;
+}
+
+static int __pmac
+heathrow_floppy_enable(struct device_node* node, int param, int value)
+{
+	return simple_feature_tweak(node, macio_unknown,
+		HEATHROW_FCR,
+		HRW_SWIM_ENABLE|HRW_BAY_FLOPPY_ENABLE,
+		value);
+}
+
+static int __pmac
+heathrow_mesh_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, macio_unknown);
+	if (!macio)
+		return -ENODEV;
+	LOCK(flags);
+	/* Set clear mesh cell enable */
+	if (value)
+		MACIO_BIS(HEATHROW_FCR, HRW_MESH_ENABLE);
+	else
+		MACIO_BIC(HEATHROW_FCR, HRW_MESH_ENABLE);
+	(void)MACIO_IN32(HEATHROW_FCR);
+	udelay(10);
+	/* Set/Clear termination power (todo: test ! the bit value
+	 * used by Darwin doesn't seem to match what we used so
+	 * far. If you experience problems, turn #if 1 into #if 0
+	 * and tell me about it --BenH.
+	 */
+#if 1
+	if (value)
+		MACIO_BIC(HEATHROW_MBCR, 0x00000004);
+	else
+		MACIO_BIS(HEATHROW_MBCR, 0x00000004);
+#else
+	if (value)
+		MACIO_BIC(HEATHROW_MBCR, 0x00040000);
+	else
+		MACIO_BIS(HEATHROW_MBCR, 0x00040000);
+#endif		
+	(void)MACIO_IN32(HEATHROW_MBCR);
+	udelay(10);
+	UNLOCK(flags);
+
+	return 0;
+}
+
+static int __pmac
+heathrow_ide_enable(struct device_node* node, int param, int value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_IDE0_ENABLE, value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_BAY_IDE_ENABLE, value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static int __pmac
+heathrow_ide_reset(struct device_node* node, int param, int value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_IDE0_RESET_N, !value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			HEATHROW_FCR, HRW_IDE1_RESET_N, !value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static int __pmac
+heathrow_bmac_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (value) {
+		LOCK(flags);
+		MACIO_BIS(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
+		MACIO_BIS(HEATHROW_FCR, HRW_BMAC_RESET);
+		UNLOCK(flags);
+		(void)MACIO_IN32(HEATHROW_FCR);
+		mdelay(10);
+		LOCK(flags);
+		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_RESET);
+		UNLOCK(flags);
+		(void)MACIO_IN32(HEATHROW_FCR);
+		mdelay(10);
+	} else {
+		LOCK(flags);
+		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE);
+		UNLOCK(flags);
+	}
+	return 0;
+}
+
+static int __pmac
+heathrow_sound_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+
+	/* B&W G3 and Yikes don't support that properly (the
+	 * sound appear to never come back after beeing shut down).
+	 */
+	if (pmac_mb.model_id == PMAC_TYPE_YOSEMITE ||
+	    pmac_mb.model_id == PMAC_TYPE_YIKES)
+		return 0;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (value) {
+		LOCK(flags);
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+		UNLOCK(flags);
+		(void)MACIO_IN32(HEATHROW_FCR);
+	} else {
+		LOCK(flags);
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		UNLOCK(flags);
+	}
+	return 0;
+}
+
+static u32 save_fcr[5] __pmacdata;
+static u32 save_mbcr __pmacdata;
+static u32 save_gpio_levels[2] __pmacdata;
+static u8 save_gpio_extint[KEYLARGO_GPIO_EXTINT_CNT] __pmacdata;
+static u8 save_gpio_normal[KEYLARGO_GPIO_CNT] __pmacdata;
+static u32 save_unin_clock_ctl __pmacdata;
+static struct dbdma_regs save_dbdma[13] __pmacdata;
+static struct dbdma_regs save_alt_dbdma[13] __pmacdata;
+
+static void __pmac
+dbdma_save(struct macio_chip* macio, struct dbdma_regs* save)
+{
+	int i;
+	
+	/* Save state & config of DBDMA channels */
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
+			(macio->base + ((0x8000+i*0x100)>>2));
+		save[i].cmdptr_hi = in_le32(&chan->cmdptr_hi);
+		save[i].cmdptr = in_le32(&chan->cmdptr);
+		save[i].intr_sel = in_le32(&chan->intr_sel);
+		save[i].br_sel = in_le32(&chan->br_sel);
+		save[i].wait_sel = in_le32(&chan->wait_sel);
+	}
+}
+
+static void __pmac
+dbdma_restore(struct macio_chip* macio, struct dbdma_regs* save)
+{
+	int i;
+	
+	/* Save state & config of DBDMA channels */
+	for (i=0; i<13; i++) {
+		volatile struct dbdma_regs* chan = (volatile struct dbdma_regs*)
+			(macio->base + ((0x8000+i*0x100)>>2));
+		out_le32(&chan->control, (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);
+		while (in_le32(&chan->status) & ACTIVE)
+			mb();
+		out_le32(&chan->cmdptr_hi, save[i].cmdptr_hi);
+		out_le32(&chan->cmdptr, save[i].cmdptr);
+		out_le32(&chan->intr_sel, save[i].intr_sel);
+		out_le32(&chan->br_sel, save[i].br_sel);
+		out_le32(&chan->wait_sel, save[i].wait_sel);
+	}
+}
+
+static void __pmac
+heathrow_sleep(struct macio_chip* macio, int secondary)
+{
+	if (secondary) {
+		dbdma_save(macio, save_alt_dbdma);
+		save_fcr[2] = MACIO_IN32(0x38);
+		save_fcr[3] = MACIO_IN32(0x3c);
+	} else {
+		dbdma_save(macio, save_dbdma);
+		save_fcr[0] = MACIO_IN32(0x38);
+		save_fcr[1] = MACIO_IN32(0x3c);
+		save_mbcr = MACIO_IN32(0x34);
+		/* Make sure sound is shut down */
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_POWER_N);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		/* This seems to be necessary as well or the fan
+		 * keeps coming up and battery drains fast */
+		MACIO_BIC(HEATHROW_FCR, HRW_IOBUS_ENABLE);
+		/* Make sure eth is down even if module or sleep
+		 * won't work properly */
+		MACIO_BIC(HEATHROW_FCR, HRW_BMAC_IO_ENABLE | HRW_BMAC_RESET);
+	}
+	/* Make sure modem is shut down */
+	MACIO_OUT8(HRW_GPIO_MODEM_RESET,
+		MACIO_IN8(HRW_GPIO_MODEM_RESET) & ~1);
+	MACIO_BIS(HEATHROW_FCR, HRW_SCC_TRANS_EN_N);
+	MACIO_BIC(HEATHROW_FCR, OH_SCCA_IO|OH_SCCB_IO|HRW_SCC_ENABLE);
+
+	/* Let things settle */
+	(void)MACIO_IN32(HEATHROW_FCR);
+	mdelay(1);
+}
+
+static void __pmac
+heathrow_wakeup(struct macio_chip* macio, int secondary)
+{
+	if (secondary) {
+		MACIO_OUT32(0x38, save_fcr[2]);
+		(void)MACIO_IN32(0x38);
+		mdelay(1);
+		MACIO_OUT32(0x3c, save_fcr[3]);
+		(void)MACIO_IN32(0x38);
+		mdelay(10);
+		dbdma_restore(macio, save_alt_dbdma);
+	} else {
+		MACIO_OUT32(0x38, save_fcr[0] | HRW_IOBUS_ENABLE);
+		(void)MACIO_IN32(0x38);
+		mdelay(1);
+		MACIO_OUT32(0x3c, save_fcr[1]);
+		(void)MACIO_IN32(0x38);
+		mdelay(1);
+		MACIO_OUT32(0x34, save_mbcr);
+		(void)MACIO_IN32(0x38);
+		mdelay(10);
+		dbdma_restore(macio, save_dbdma);
+	}
+}
+
+static int __pmac
+heathrow_sleep_state(struct device_node* node, int param, int value)
+{
+	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+		return -EPERM;
+	if (value == 1) {
+		if (macio_chips[1].type == macio_gatwick)
+			heathrow_sleep(&macio_chips[0], 1);
+		heathrow_sleep(&macio_chips[0], 0);
+	} else if (value == 0) {
+		heathrow_wakeup(&macio_chips[0], 0);
+		if (macio_chips[1].type == macio_gatwick)
+			heathrow_wakeup(&macio_chips[0], 1);
+	}
+	return 0;
+}
+
+static int __pmac
+core99_scc_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	unsigned long		chan_mask;
+	u32			fcr;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	if (!strcmp(node->name, "ch-a"))
+		chan_mask = MACIO_FLAG_SCCA_ON;
+	else if (!strcmp(node->name, "ch-b"))
+		chan_mask = MACIO_FLAG_SCCB_ON;
+	else
+		return -ENODEV;
+
+	if (value) {
+		int need_reset_scc = 0;
+		int need_reset_irda = 0;
+		
+		LOCK(flags);
+		fcr = MACIO_IN32(KEYLARGO_FCR0);
+		/* Check if scc cell need enabling */
+		if (!(fcr & KL0_SCC_CELL_ENABLE)) {
+			fcr |= KL0_SCC_CELL_ENABLE;
+			need_reset_scc = 1;
+		}
+		if (chan_mask & MACIO_FLAG_SCCA_ON) {
+			fcr |= KL0_SCCA_ENABLE;
+			/* Don't enable line drivers for I2S modem */
+			if ((param & 0xfff) == PMAC_SCC_I2S1)
+				fcr &= ~KL0_SCC_A_INTF_ENABLE;
+			else
+				fcr |= KL0_SCC_A_INTF_ENABLE;
+		}
+		if (chan_mask & MACIO_FLAG_SCCB_ON) {
+			fcr |= KL0_SCCB_ENABLE;
+			/* Perform irda specific inits */
+			if ((param & 0xfff) == PMAC_SCC_IRDA) {
+				fcr &= ~KL0_SCC_B_INTF_ENABLE;
+				fcr |= KL0_IRDA_ENABLE;
+				fcr |= KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE;
+				fcr |= KL0_IRDA_SOURCE1_SEL;
+				fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
+				fcr &= ~(KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
+				need_reset_irda = 1;
+			} else
+				fcr |= KL0_SCC_B_INTF_ENABLE;
+		}
+		MACIO_OUT32(KEYLARGO_FCR0, fcr);
+		macio->flags |= chan_mask;
+		if (need_reset_scc)  {
+			MACIO_BIS(KEYLARGO_FCR0, KL0_SCC_RESET);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			UNLOCK(flags);
+			mdelay(15);
+			LOCK(flags);
+			MACIO_BIC(KEYLARGO_FCR0, KL0_SCC_RESET);
+		}
+		if (need_reset_irda)  {
+			MACIO_BIS(KEYLARGO_FCR0, KL0_IRDA_RESET);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			UNLOCK(flags);
+			mdelay(15);
+			LOCK(flags);
+			MACIO_BIC(KEYLARGO_FCR0, KL0_IRDA_RESET);
+		}
+		UNLOCK(flags);
+		if (param & PMAC_SCC_FLAG_XMON)
+			macio->flags |= MACIO_FLAG_SCC_LOCKED;
+	} else {
+		if (macio->flags & MACIO_FLAG_SCC_LOCKED)
+			return -EPERM;
+		LOCK(flags);
+		fcr = MACIO_IN32(KEYLARGO_FCR0);
+		if (chan_mask & MACIO_FLAG_SCCA_ON)
+			fcr &= ~KL0_SCCA_ENABLE;
+		if (chan_mask & MACIO_FLAG_SCCB_ON) {
+			fcr &= ~KL0_SCCB_ENABLE;
+			/* Perform irda specific clears */
+			if ((param & 0xfff) == PMAC_SCC_IRDA) {
+				fcr &= ~KL0_IRDA_ENABLE;
+				fcr &= ~(KL0_IRDA_CLK32_ENABLE | KL0_IRDA_CLK19_ENABLE);
+				fcr &= ~(KL0_IRDA_FAST_CONNECT|KL0_IRDA_DEFAULT1|KL0_IRDA_DEFAULT0);
+				fcr &= ~(KL0_IRDA_SOURCE1_SEL|KL0_IRDA_SOURCE2_SEL|KL0_IRDA_HIGH_BAND);
+			}
+		}
+		MACIO_OUT32(KEYLARGO_FCR0, fcr);
+		if ((fcr & (KL0_SCCA_ENABLE | KL0_SCCB_ENABLE)) == 0) {
+			fcr &= ~KL0_SCC_CELL_ENABLE;
+			MACIO_OUT32(KEYLARGO_FCR0, fcr);
+		}
+		macio->flags &= ~(chan_mask);
+		UNLOCK(flags);
+		mdelay(10);
+	}
+	return 0;
+}
+
+static int __pmac
+core99_modem_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	u8			gpio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+	gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+	gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+	
+	if (!value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		UNLOCK(flags);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+		mdelay(250);
+	}
+    	LOCK(flags);
+    	if (value) {
+    		MACIO_BIC(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+	    	UNLOCK(flags);
+	    	(void)MACIO_IN32(KEYLARGO_FCR2);
+		mdelay(250);
+    	} else {
+    		MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+	    	UNLOCK(flags);
+    	}
+	if (value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250);
+	}
+	return 0;
+}
+
+static int __pmac
+core99_ide_enable(struct device_node* node, int param, int value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE0_ENABLE, value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE1_ENABLE, value);
+	    case 2:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_UIDE_ENABLE, value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static int __pmac
+core99_ide_reset(struct device_node* node, int param, int value)
+{
+	switch(param) {
+	    case 0:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE0_RESET_N, !value);
+	    case 1:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_EIDE1_RESET_N, !value);
+	    case 2:
+		return simple_feature_tweak(node, macio_unknown,
+			KEYLARGO_FCR1, KL1_UIDE_RESET_N, !value);
+	    default:
+	    	return -ENODEV;
+	}
+}
+
+static int __pmac
+core99_gmac_enable(struct device_node* node, int param, int value)
+{
+	unsigned long flags;
+
+	LOCK(flags);
+	if (value)
+		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+	else
+		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_GMAC);
+	(void)UN_IN(UNI_N_CLOCK_CNTL);
+	UNLOCK(flags);
+	udelay(20);
+
+	return 0;
+}
+
+static int __pmac
+core99_gmac_phy_reset(struct device_node* node, int param, int value)
+{
+	unsigned long flags;
+	struct macio_chip* macio;
+	
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+
+	LOCK(flags);
+	MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE);
+	(void)MACIO_IN8(KL_GPIO_ETH_PHY_RESET);
+	UNLOCK(flags);
+	mdelay(10);
+	LOCK(flags);
+	MACIO_OUT8(KL_GPIO_ETH_PHY_RESET, KEYLARGO_GPIO_OUTPUT_ENABLE
+		| KEYLARGO_GPIO_OUTOUT_DATA);
+	UNLOCK(flags);
+	mdelay(10);
+
+	return 0;
+}
+
+static int __pmac
+core99_sound_chip_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+
+	/* Do a better probe code, screamer G4 desktops &
+	 * iMacs can do that too, add a recalibrate  in
+	 * the driver as well
+	 */
+	if (pmac_mb.model_id == PMAC_TYPE_PISMO ||
+	    pmac_mb.model_id == PMAC_TYPE_TITANIUM) {
+		LOCK(flags);
+		if (value)
+	    		MACIO_OUT8(KL_GPIO_SOUND_POWER,
+	    			KEYLARGO_GPIO_OUTPUT_ENABLE |
+	    			KEYLARGO_GPIO_OUTOUT_DATA);
+	    	else
+	    		MACIO_OUT8(KL_GPIO_SOUND_POWER,
+	    			KEYLARGO_GPIO_OUTPUT_ENABLE);
+	    	(void)MACIO_IN8(KL_GPIO_SOUND_POWER);
+	    	UNLOCK(flags);
+	}
+	return 0;
+}
+
+static int __pmac
+core99_airport_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	unsigned long		flags;
+	int			state;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	
+	/* Hint: we allow passing of macio itself for the sake of the
+	 * sleep code
+	 */
+	if (node != macio->of_node &&
+	    (!node->parent || node->parent != macio->of_node))
+		return -ENODEV;
+	state = (macio->flags & MACIO_FLAG_AIRPORT_ON) != 0;
+	if (value == state)
+		return 0;
+	if (value) {
+		/* This code is a reproduction of OF enable-cardslot
+		 * and init-wireless methods, slightly hacked until
+		 * I got it working.
+		 */
+		LOCK(flags);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 5);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
+		UNLOCK(flags);
+		mdelay(10);
+		LOCK(flags);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xf, 4);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xf);
+		UNLOCK(flags);
+
+		mdelay(10);
+
+		LOCK(flags);
+		MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
+		(void)MACIO_IN32(KEYLARGO_FCR2);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xb, 0);
+		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xb);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xa, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xa);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+0xd, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+0xd);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xd, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xd);
+		udelay(10);
+		MACIO_OUT8(KEYLARGO_GPIO_0+0xe, 0x28);
+		(void)MACIO_IN8(KEYLARGO_GPIO_0+0xe);
+		UNLOCK(flags);
+		udelay(10);
+		MACIO_OUT32(0x1c000, 0);
+		mdelay(1);
+		MACIO_OUT8(0x1a3e0, 0x41);
+		(void)MACIO_IN8(0x1a3e0);
+		udelay(10);
+		LOCK(flags);
+		MACIO_BIS(KEYLARGO_FCR2, KL2_CARDSEL_16);
+		(void)MACIO_IN32(KEYLARGO_FCR2);
+		UNLOCK(flags);
+		mdelay(100);
+
+		macio->flags |= MACIO_FLAG_AIRPORT_ON;
+	} else {
+		LOCK(flags);
+		MACIO_BIC(KEYLARGO_FCR2, KL2_CARDSEL_16);
+		(void)MACIO_IN32(KEYLARGO_FCR2);
+		MACIO_OUT8(KL_GPIO_AIRPORT_0, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_1, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_2, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_3, 0);
+		MACIO_OUT8(KL_GPIO_AIRPORT_4, 0);
+		(void)MACIO_IN8(KL_GPIO_AIRPORT_4);
+		UNLOCK(flags);
+
+		macio->flags &= ~MACIO_FLAG_AIRPORT_ON;
+	}
+	return 0;
+}
+
+#ifdef CONFIG_SMP
+static int __pmac
+core99_reset_cpu(struct device_node* node, int param, int value)
+{
+	const int reset_lines[] = {	KL_GPIO_RESET_CPU0,
+					KL_GPIO_RESET_CPU1,
+					KL_GPIO_RESET_CPU2,
+					KL_GPIO_RESET_CPU3 };
+	int reset_io;
+	unsigned long flags;
+	struct macio_chip* macio;
+	
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+	if (param > 3 || param < 0)
+		return -ENODEV;
+
+	reset_io = reset_lines[param];
+	
+	LOCK(flags);
+	MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE);
+	(void)MACIO_IN8(reset_io);
+	udelay(1);
+	MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+	(void)MACIO_IN8(reset_io);
+	UNLOCK(flags);
+
+	return 0;
+}
+#endif /* CONFIG_SMP */
+
+static int __pmac
+core99_usb_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip* macio;
+	unsigned long flags;
+	char* prop;
+	int number;
+	u32 reg;
+	
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+	
+	prop = (char *)get_property(node, "AAPL,clock-id", NULL);
+	if (!prop)
+		return -ENODEV;
+	if (strncmp(prop, "usb0u048", strlen("usb0u048")) == 0)
+		number = 0;
+	else if (strncmp(prop, "usb1u148", strlen("usb1u148")) == 0)
+		number = 2;
+	else
+		return -ENODEV;
+
+	/* Sorry for the brute-force locking, but this is only used during
+	 * sleep and the timing seem to be critical
+	 */
+	LOCK(flags);
+	if (value) {
+		/* Turn ON */
+		if (number == 0) {
+			MACIO_BIC(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			UNLOCK(flags);
+			mdelay(1);
+			LOCK(flags);
+			MACIO_BIS(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+		} else {
+			MACIO_BIC(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			UNLOCK(flags);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			mdelay(1);
+			LOCK(flags);
+			MACIO_BIS(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+		}
+		reg = MACIO_IN32(KEYLARGO_FCR4);
+		reg &=	~(KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
+			KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number));
+		reg &=	~(KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
+			KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1));
+		MACIO_OUT32(KEYLARGO_FCR4, reg);
+		(void)MACIO_IN32(KEYLARGO_FCR4);
+		udelay(10);
+	} else {
+		/* Turn OFF */
+		reg = MACIO_IN32(KEYLARGO_FCR4);
+		reg |=	KL4_PORT_WAKEUP_ENABLE(number) | KL4_PORT_RESUME_WAKE_EN(number) |
+			KL4_PORT_CONNECT_WAKE_EN(number) | KL4_PORT_DISCONNECT_WAKE_EN(number);
+		reg |=	KL4_PORT_WAKEUP_ENABLE(number+1) | KL4_PORT_RESUME_WAKE_EN(number+1) |
+			KL4_PORT_CONNECT_WAKE_EN(number+1) | KL4_PORT_DISCONNECT_WAKE_EN(number+1);
+		MACIO_OUT32(KEYLARGO_FCR4, reg);
+		(void)MACIO_IN32(KEYLARGO_FCR4);
+		udelay(1);
+		if (number == 0) {
+			MACIO_BIC(KEYLARGO_FCR0, KL0_USB0_CELL_ENABLE);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			udelay(1);
+			MACIO_BIS(KEYLARGO_FCR0, (KL0_USB0_PAD_SUSPEND0 | KL0_USB0_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+		} else {
+			MACIO_BIC(KEYLARGO_FCR0, KL0_USB1_CELL_ENABLE);
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+			udelay(1);
+			MACIO_BIS(KEYLARGO_FCR0, (KL0_USB1_PAD_SUSPEND0 | KL0_USB1_PAD_SUSPEND1));
+			(void)MACIO_IN32(KEYLARGO_FCR0);
+		}
+		udelay(1);
+	}
+	UNLOCK(flags);
+
+	return 0;
+}
+
+static int __pmac
+core99_firewire_enable(struct device_node* node, int param, int value)
+{
+	unsigned long flags;
+	struct macio_chip* macio;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+	if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
+		return -ENODEV;
+	
+	LOCK(flags);
+	if (value) {
+		UN_BIS(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+		(void)UN_IN(UNI_N_CLOCK_CNTL);
+	} else {
+		UN_BIC(UNI_N_CLOCK_CNTL, UNI_N_CLOCK_CNTL_FW);
+		(void)UN_IN(UNI_N_CLOCK_CNTL);
+	}
+	UNLOCK(flags);
+	mdelay(1);
+
+	return 0;
+}
+
+static int __pmac
+core99_firewire_cable_power(struct device_node* node, int param, int value)
+{
+	unsigned long flags;
+	struct macio_chip* macio;
+
+	/* Trick: we allow NULL node */
+	if ((pmac_mb.board_flags & PMAC_MB_HAS_FW_POWER) == 0)
+	    	return -ENODEV;
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+	if (!(macio->flags & MACIO_FLAG_FW_SUPPORTED))
+		return -ENODEV;
+	
+	LOCK(flags);
+	if (value) {
+		MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 0);
+		MACIO_IN8(KL_GPIO_FW_CABLE_POWER);
+		udelay(10);
+	} else {
+		MACIO_OUT8(KL_GPIO_FW_CABLE_POWER , 4);
+		MACIO_IN8(KL_GPIO_FW_CABLE_POWER); udelay(10);
+	}
+	UNLOCK(flags);
+	mdelay(1);
+
+	return 0;
+}
+
+static int __pmac
+core99_read_gpio(struct device_node* node, int param, int value)
+{
+	struct macio_chip* macio = &macio_chips[0];
+	
+	return MACIO_IN8(param);
+}
+
+
+static int __pmac
+core99_write_gpio(struct device_node* node, int param, int value)
+{
+	struct macio_chip* macio = &macio_chips[0];
+
+	MACIO_OUT8(param, (u8)(value & 0xff));
+	return 0;
+}
+
+static void __pmac
+keylargo_shutdown(struct macio_chip* macio, int restart)
+{
+	u32 temp;
+
+	mdelay(1);
+	MACIO_BIS(KEYLARGO_FCR0, KL0_USB_REF_SUSPEND);
+	(void)MACIO_IN32(KEYLARGO_FCR0);
+	mdelay(100);
+
+	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+		      		KL0_IRDA_ENABLE | KL0_IRDA_CLK32_ENABLE |
+		      		KL0_IRDA_CLK19_ENABLE);
+
+	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
+	MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
+	(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+
+	MACIO_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_EIDE0_ENABLE | KL1_EIDE0_RESET_N |
+		KL1_EIDE1_ENABLE | KL1_EIDE1_RESET_N |
+		KL1_UIDE_ENABLE);
+	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
+
+	MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+ 	udelay(10);
+ 	MACIO_BIC(KEYLARGO_FCR2, KL2_IOBUS_ENABLE);
+ 	udelay(10);
+	temp = MACIO_IN32(KEYLARGO_FCR3);
+	if (macio->rev >= 2)
+		temp |= (KL3_SHUTDOWN_PLL2X | KL3_SHUTDOWN_PLL_TOTAL);
+		
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35 | KL3_SHUTDOWN_PLLKW12;
+	temp &= ~(KL3_CLK66_ENABLE | KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	MACIO_OUT32(KEYLARGO_FCR3, temp);
+	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+}
+
+static void __pmac
+pangea_shutdown(struct macio_chip* macio, int restart)
+{
+	u32 temp;
+
+	MACIO_BIC(KEYLARGO_FCR0,KL0_SCCA_ENABLE | KL0_SCCB_ENABLE |
+				KL0_SCC_CELL_ENABLE |
+				KL0_USB0_CELL_ENABLE | KL0_USB1_CELL_ENABLE);
+
+	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
+	MACIO_BIC(KEYLARGO_MBCR, KL_MBCR_MB0_DEV_MASK);
+	(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+
+	MACIO_BIC(KEYLARGO_FCR1,
+		KL1_AUDIO_SEL_22MCLK | KL1_AUDIO_CLK_ENABLE_BIT |
+		KL1_AUDIO_CLK_OUT_ENABLE | KL1_AUDIO_CELL_ENABLE |
+		KL1_I2S0_CELL_ENABLE | KL1_I2S0_CLK_ENABLE_BIT |
+		KL1_I2S0_ENABLE | KL1_I2S1_CELL_ENABLE |
+		KL1_I2S1_CLK_ENABLE_BIT | KL1_I2S1_ENABLE |
+		KL1_UIDE_ENABLE);
+	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
+
+	MACIO_BIS(KEYLARGO_FCR2, KL2_ALT_DATA_OUT);
+ 	udelay(10);
+	temp = MACIO_IN32(KEYLARGO_FCR3);
+	temp |= KL3_SHUTDOWN_PLLKW6 | KL3_SHUTDOWN_PLLKW4 |
+		KL3_SHUTDOWN_PLLKW35;
+	temp &= ~(KL3_CLK49_ENABLE | KL3_CLK45_ENABLE
+		| KL3_CLK31_ENABLE | KL3_TIMER_CLK18_ENABLE | KL3_I2S1_CLK18_ENABLE
+		| KL3_I2S0_CLK18_ENABLE | KL3_VIA_CLK16_ENABLE);
+	MACIO_OUT32(KEYLARGO_FCR3, temp);
+	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+}
+
+static int __pmac
+core99_sleep(void)
+{
+	struct macio_chip* macio;
+	int i;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+	
+	/* We power off the wireless slot in case it was not done
+	 * by the driver. We don't power it on automatically however
+	 */
+	if (macio->flags & MACIO_FLAG_AIRPORT_ON)
+		core99_airport_enable(macio->of_node, 0, 0);
+
+	/* We power off the FW cable. Should be done by the driver... */
+	if (macio->flags & MACIO_FLAG_FW_SUPPORTED) {
+		core99_firewire_enable(NULL, 0, 0);
+		core99_firewire_cable_power(NULL, 0, 0);
+	}
+
+	/* We make sure int. modem is off (in case driver lost it) */
+	core99_modem_enable(macio->of_node, 0, 0);
+	/* We make sure the sound is off as well */
+	core99_sound_chip_enable(macio->of_node, 0, 0);
+	 
+	/*
+	 * Save various bits of KeyLargo
+	 */
+
+	/* Save the state of the various GPIOs */
+	save_gpio_levels[0] = MACIO_IN32(KEYLARGO_GPIO_LEVELS0);
+	save_gpio_levels[1] = MACIO_IN32(KEYLARGO_GPIO_LEVELS1);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		save_gpio_extint[i] = MACIO_IN8(KEYLARGO_GPIO_EXTINT_0+i);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		save_gpio_normal[i] = MACIO_IN8(KEYLARGO_GPIO_0+i);
+
+	/* Save the FCRs */
+	save_mbcr = MACIO_IN32(KEYLARGO_MBCR);
+	save_fcr[0] = MACIO_IN32(KEYLARGO_FCR0);
+	save_fcr[1] = MACIO_IN32(KEYLARGO_FCR1);
+	save_fcr[2] = MACIO_IN32(KEYLARGO_FCR2);
+	save_fcr[3] = MACIO_IN32(KEYLARGO_FCR3);
+	save_fcr[4] = MACIO_IN32(KEYLARGO_FCR4);
+
+	/* Save state & config of DBDMA channels */
+	dbdma_save(macio, save_dbdma);
+	
+	/*
+	 * Turn off as much as we can
+	 */
+	if (macio->type == macio_pangea)
+		pangea_shutdown(macio, 0);
+	else if (macio->type == macio_keylargo)
+		keylargo_shutdown(macio, 0);
+	
+	/* 
+	 * Put the host bridge to sleep
+	 */
+
+	save_unin_clock_ctl = UN_IN(UNI_N_CLOCK_CNTL);
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl &
+		~(UNI_N_CLOCK_CNTL_GMAC|UNI_N_CLOCK_CNTL_FW/*|UNI_N_CLOCK_CNTL_PCI*/));
+	udelay(100);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_SLEEPING);
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_SLEEP);
+
+	/*
+	 * FIXME: A bit of black magic with OpenPIC (don't ask me why)
+	 */
+	if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
+		MACIO_BIS(0x506e0, 0x00400000);
+		MACIO_BIS(0x506e0, 0x80000000);
+	}
+	return 0;
+}
+
+static int __pmac
+core99_wake_up(void)
+{
+	struct macio_chip* macio;
+	int i;
+
+	macio = &macio_chips[0];
+	if (macio->type != macio_keylargo && macio->type != macio_pangea)
+		return -ENODEV;
+
+	/*
+	 * Wakeup the host bridge
+	 */
+	UN_OUT(UNI_N_POWER_MGT, UNI_N_POWER_MGT_NORMAL);
+	udelay(10);
+	UN_OUT(UNI_N_HWINIT_STATE, UNI_N_HWINIT_STATE_RUNNING);
+	udelay(10);
+	
+	/*
+	 * Restore KeyLargo
+	 */
+	 
+	MACIO_OUT32(KEYLARGO_MBCR, save_mbcr);
+	(void)MACIO_IN32(KEYLARGO_MBCR); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR0, save_fcr[0]);
+	(void)MACIO_IN32(KEYLARGO_FCR0); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR1, save_fcr[1]);
+	(void)MACIO_IN32(KEYLARGO_FCR1); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR2, save_fcr[2]);
+	(void)MACIO_IN32(KEYLARGO_FCR2); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR3, save_fcr[3]);
+	(void)MACIO_IN32(KEYLARGO_FCR3); udelay(10);
+	MACIO_OUT32(KEYLARGO_FCR4, save_fcr[4]);
+	(void)MACIO_IN32(KEYLARGO_FCR4); udelay(10);
+
+	dbdma_restore(macio, save_dbdma);
+
+	MACIO_OUT32(KEYLARGO_GPIO_LEVELS0, save_gpio_levels[0]);
+	MACIO_OUT32(KEYLARGO_GPIO_LEVELS1, save_gpio_levels[1]);
+	for (i=0; i<KEYLARGO_GPIO_EXTINT_CNT; i++)
+		MACIO_OUT8(KEYLARGO_GPIO_EXTINT_0+i, save_gpio_extint[i]);
+	for (i=0; i<KEYLARGO_GPIO_CNT; i++)
+		MACIO_OUT8(KEYLARGO_GPIO_0+i, save_gpio_normal[i]);
+
+	/* FIXME more black magic with OpenPIC ... */
+	if (pmac_mb.model_id == PMAC_TYPE_SAWTOOTH) {
+		MACIO_BIC(0x506e0, 0x00400000);
+		MACIO_BIC(0x506e0, 0x80000000);
+	}
+
+	UN_OUT(UNI_N_CLOCK_CNTL, save_unin_clock_ctl);
+	udelay(100);
+
+	return 0;
+}
+
+static int __pmac
+core99_sleep_state(struct device_node* node, int param, int value)
+{
+	if ((pmac_mb.board_flags & PMAC_MB_CAN_SLEEP) == 0)
+		return -EPERM;
+	if (value == 1)
+		return core99_sleep();
+	else if (value == 0)
+		return core99_wake_up();
+	return 0;
+}
+
+static int __pmac
+pangea_modem_enable(struct device_node* node, int param, int value)
+{
+	struct macio_chip*	macio;
+	u8			gpio;
+	unsigned long		flags;
+	
+	macio = macio_find(node, 0);
+	if (!macio)
+		return -ENODEV;
+	gpio = MACIO_IN8(KL_GPIO_MODEM_RESET);
+	gpio |= KEYLARGO_GPIO_OUTPUT_ENABLE;
+	gpio &= ~KEYLARGO_GPIO_OUTOUT_DATA;
+	
+	if (!value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		UNLOCK(flags);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+		mdelay(250);
+	}
+    	LOCK(flags);
+	if (value) {
+		MACIO_OUT8(KL_GPIO_MODEM_POWER,
+			KEYLARGO_GPIO_OUTPUT_ENABLE);
+    		UNLOCK(flags);
+	    	(void)MACIO_IN32(KEYLARGO_FCR2);
+		mdelay(250);
+	} else {
+		MACIO_OUT8(KL_GPIO_MODEM_POWER,
+			KEYLARGO_GPIO_OUTPUT_ENABLE | KEYLARGO_GPIO_OUTOUT_DATA);
+    		UNLOCK(flags);
+	}
+	if (value) {
+		LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250); LOCK(flags);
+		MACIO_OUT8(KL_GPIO_MODEM_RESET, gpio | KEYLARGO_GPIO_OUTOUT_DATA);
+		(void)MACIO_IN8(KL_GPIO_MODEM_RESET);
+	    	UNLOCK(flags); mdelay(250);
+	}
+	return 0;
+}
+
+
+static int __pmac
+generic_get_mb_info(struct device_node* node, int param, int value)
+{
+	switch(param) {
+		case PMAC_MB_INFO_MODEL:
+			return pmac_mb.model_id;
+		case PMAC_MB_INFO_FLAGS:
+			return pmac_mb.board_flags;
+		case PMAC_MB_INFO_NAME:	
+			/* hack hack hack... but should work */
+			*((const char **)value) = pmac_mb.model_name;
+			break;
+	}
+	return 0;
+}
+
+
+/* 
+ * Table definitions
+ */
+ 
+/* Used on any machine
+ */
+static struct feature_table_entry any_features[]  __pmacdata = {
+	{ PMAC_FTR_GET_MB_INFO,		generic_get_mb_info },
+	{ 0, NULL }
+};
+
+/* OHare based motherboards. Currently, we only use these on the
+ * 2400,3400 and 3500 series powerbooks. Some older desktops seem
+ * to have issues with turning on/off those asic cells
+ */
+static struct feature_table_entry ohare_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
+	{ PMAC_FTR_SWIM3_ENABLE,	ohare_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		ohare_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		ohare_ide_enable},
+	{ PMAC_FTR_IDE_RESET,		ohare_ide_reset},
+	{ PMAC_FTR_SLEEP_STATE,		ohare_sleep_state },
+	{ 0, NULL }
+};
+
+/* Heathrow desktop machines (Beige G3).
+ * Separated as some features couldn't be properly tested
+ * and the serial port control bits appear to confuse it.
+ */
+static struct feature_table_entry heathrow_desktop_features[]  __pmacdata = {
+	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
+	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
+	{ 0, NULL }
+};
+
+/* Heathrow based laptop, that is the Wallstreet and mainstreet
+ * powerbooks.
+ */
+static struct feature_table_entry heathrow_laptop_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	heathrow_modem_enable },
+	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
+	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	heathrow_sound_enable },
+	{ PMAC_FTR_SLEEP_STATE,		heathrow_sleep_state },
+	{ 0, NULL }
+};
+
+/* Paddington based machines
+ * The lombard (101) powerbook, first iMac models, B&W G3 and Yikes G4.
+ */
+static struct feature_table_entry paddington_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		ohare_htw_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	heathrow_modem_enable },
+	{ PMAC_FTR_SWIM3_ENABLE,	heathrow_floppy_enable },
+	{ PMAC_FTR_MESH_ENABLE,		heathrow_mesh_enable },
+	{ PMAC_FTR_IDE_ENABLE,		heathrow_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		heathrow_ide_reset },
+	{ PMAC_FTR_BMAC_ENABLE,		heathrow_bmac_enable },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	heathrow_sound_enable },
+	{ PMAC_FTR_SLEEP_STATE,		heathrow_sleep_state },
+	{ 0, NULL }
+};
+
+/* Core99 & MacRISC 2 machines (all machines released since the
+ * iBook (included), that is all AGP machines, except pangea
+ * chipset. The pangea chipset is the "combo" UniNorth/KeyLargo
+ * used on iBook2 & iMac "flow power".
+ */
+static struct feature_table_entry core99_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	core99_modem_enable },
+	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
+	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
+	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
+	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
+	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
+	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
+	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
+	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
+#ifdef CONFIG_SMP
+	{ PMAC_FTR_RESET_CPU,		core99_reset_cpu },
+#endif /* CONFIG_SMP */
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ 0, NULL }
+};
+
+/* Pangea features
+ */
+static struct feature_table_entry pangea_features[]  __pmacdata = {
+	{ PMAC_FTR_SCC_ENABLE,		core99_scc_enable },
+	{ PMAC_FTR_MODEM_ENABLE,	pangea_modem_enable },
+	{ PMAC_FTR_IDE_ENABLE,		core99_ide_enable },
+	{ PMAC_FTR_IDE_RESET,		core99_ide_reset },
+	{ PMAC_FTR_GMAC_ENABLE,		core99_gmac_enable },
+	{ PMAC_FTR_GMAC_PHY_RESET,	core99_gmac_phy_reset },
+	{ PMAC_FTR_SOUND_CHIP_ENABLE,	core99_sound_chip_enable },
+	{ PMAC_FTR_AIRPORT_ENABLE,	core99_airport_enable },
+	{ PMAC_FTR_USB_ENABLE,		core99_usb_enable },
+	{ PMAC_FTR_1394_ENABLE,		core99_firewire_enable },
+	{ PMAC_FTR_1394_CABLE_POWER,	core99_firewire_cable_power },
+	{ PMAC_FTR_SLEEP_STATE,		core99_sleep_state },
+	{ PMAC_FTR_READ_GPIO,		core99_read_gpio },
+	{ PMAC_FTR_WRITE_GPIO,		core99_write_gpio },
+	{ 0, NULL }
+};
+	
+static struct pmac_mb_def pmac_mb_defs[] __pmacdata = {
+	/* Warning: ordering is important as some models may claim
+	 * beeing compatible with several types
+	 */
+	{	"AAPL,8500",			"PowerMac 8500/8600",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,9500",			"PowerMac 9500/9600",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,7500",			"PowerMac 7500",
+		PMAC_TYPE_PSURGE,		NULL,
+		0
+	},
+	{	"AAPL,ShinerESB",		"Apple Network Server",
+		PMAC_TYPE_ANS,			NULL,
+		0
+	},
+	{	"AAPL,e407",			"Alchemy",
+		PMAC_TYPE_ALCHEMY,		NULL,
+		0
+	},
+	{	"AAPL,e411",			"Gazelle",
+		PMAC_TYPE_GAZELLE,		NULL,
+		0
+	},
+	{	"AAPL,3400/2400",		"PowerBook 3400",
+		PMAC_TYPE_HOOPER,		ohare_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"AAPL,3500",			"PowerBook 3500",
+		PMAC_TYPE_KANGA,		ohare_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"AAPL,Gossamer",		"PowerMac G3 (Gossamer)",
+		PMAC_TYPE_GOSSAMER,		heathrow_desktop_features,
+		0
+	},
+	{	"AAPL,PowerMac G3",		"PowerMac G3 (Silk)",
+		PMAC_TYPE_SILK,			heathrow_desktop_features,
+		0
+	},
+	{	"AAPL,PowerBook1998",		"PowerBook Wallstreet",
+		PMAC_TYPE_WALLSTREET,		heathrow_laptop_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"AAPL,PowerBook1,1",		"PowerBook 101 (Lombard)",
+		PMAC_TYPE_101_PBOOK,		paddington_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"iMac,1",			"iMac (first generation)",
+		PMAC_TYPE_ORIG_IMAC,		paddington_features,
+		0
+	},
+	{	"PowerMac4,1",			"iMac \"Flower Power\"",
+		PMAC_TYPE_PANGEA_IMAC,		pangea_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"PowerBook4,3",			"iBook 2 with 14\" LCD",
+		PMAC_TYPE_IBOOK2,		pangea_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerBook4,2",			"iBook 2 with 14\" LCD",
+		PMAC_TYPE_IBOOK2,		pangea_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerBook4,1",			"iBook 2",
+		PMAC_TYPE_IBOOK2,		pangea_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerMac4,2",			"Flat panel iMac",
+		PMAC_TYPE_FLAT_PANEL_IMAC,	pangea_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"PowerMac1,1",			"Blue&White G3",
+		PMAC_TYPE_YOSEMITE,		paddington_features,
+		0
+	},
+	{	"PowerMac1,2",			"PowerMac G4 PCI Graphics",
+		PMAC_TYPE_YIKES,		paddington_features,
+		0
+	},
+	{	"PowerBook2,1",			"iBook (first generation)",
+		PMAC_TYPE_ORIG_IBOOK,		core99_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"PowerMac3,1",			"PowerMac G4 AGP Graphics",
+		PMAC_TYPE_SAWTOOTH,		core99_features,
+		0
+	},
+	{	"PowerMac3,2",			"PowerMac G4 AGP Graphics",
+		PMAC_TYPE_SAWTOOTH,		core99_features,
+		0
+	},
+	{	"PowerMac3,3",			"PowerMac G4 AGP Graphics",
+		PMAC_TYPE_SAWTOOTH,		core99_features,
+		0
+	},
+	{	"PowerMac2,1",			"iMac FireWire",
+		PMAC_TYPE_FW_IMAC,		core99_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"PowerMac2,2",			"iMac FireWire",
+		PMAC_TYPE_FW_IMAC,		core99_features,
+		PMAC_MB_CAN_SLEEP
+	},
+	{	"PowerBook2,2",			"iBook FireWire",
+		PMAC_TYPE_FW_IBOOK,		core99_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerMac5,1",			"PowerMac G4 Cube",
+		PMAC_TYPE_CUBE,			core99_features,
+	},
+	{	"PowerMac3,4",			"PowerMac G4 Silver",
+		PMAC_TYPE_QUICKSILVER,		core99_features,
+		0
+	},
+	{	"PowerMac3,5",			"PowerMac G4 Silver",
+		PMAC_TYPE_QUICKSILVER,		core99_features,
+		0
+	},
+	{	"PowerBook3,1",			"PowerBook Pismo",
+		PMAC_TYPE_PISMO,		core99_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerBook3,2",			"PowerBook Titanium",
+		PMAC_TYPE_TITANIUM,		core99_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerBook3,3",			"PowerBook Titanium II",
+		PMAC_TYPE_TITANIUM2,		core99_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+	{	"PowerBook3,4",			"PowerBook Titanium III",
+		PMAC_TYPE_TITANIUM3,		core99_features,
+		PMAC_MB_CAN_SLEEP | PMAC_MB_HAS_FW_POWER
+	},
+};
+
+/*
+ * The toplevel feature_call callback
+ */
+int __pmac
+pmac_do_feature_call(unsigned int selector, ...)
+{
+	struct device_node* node;
+	int param, value, i;
+	feature_call func = NULL;
+	va_list args;
+	
+	if (pmac_mb.features)
+		for (i=0; pmac_mb.features[i].function; i++)
+			if (pmac_mb.features[i].selector == selector) {
+				func = pmac_mb.features[i].function;
+				break;
+			}
+	if (!func)
+		for (i=0; any_features[i].function; i++)
+			if (any_features[i].selector == selector) {
+				func = any_features[i].function;
+				break;
+			}
+	if (!func)
+		return -ENODEV;
+
+	va_start(args, selector);
+	node = (struct device_node*)va_arg(args, void*);
+	param = va_arg(args, int);
+	value = va_arg(args, int);
+	va_end(args);
+
+	return func(node, param, value);
+}
+
+static int __init
+probe_motherboard(void)
+{
+	int i;
+	struct macio_chip* macio = &macio_chips[0];
+
+	/* Lookup known motherboard type in device-tree */
+	for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) {
+	    if (machine_is_compatible(pmac_mb_defs[i].model_string)) {
+		pmac_mb = pmac_mb_defs[i];
+		goto found;
+	    }
+	}
+
+	/* Fallback to selection depending on mac-io chip type */
+	switch(macio->type) {
+	    case macio_grand_central:
+		pmac_mb.model_id = PMAC_TYPE_PSURGE;
+		pmac_mb.model_name = "Unknown PowerSurge";
+		break;
+	    case macio_ohare:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_OHARE;
+		pmac_mb.model_name = "Unknown OHare-based";
+	    	break;
+	    case macio_heathrow:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_HEATHROW;
+		pmac_mb.model_name = "Unknown Heathrow-based";
+		pmac_mb.features = heathrow_desktop_features;
+		break;
+	    case macio_paddington:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PADDINGTON;
+		pmac_mb.model_name = "Unknown Paddington-based";
+	    	pmac_mb.features = paddington_features;
+		break;
+	    case macio_keylargo:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_CORE99;
+		pmac_mb.model_name = "Unknown Keylargo-based";
+	    	pmac_mb.features = core99_features;
+		break;
+	    case macio_pangea:
+		pmac_mb.model_id = PMAC_TYPE_UNKNOWN_PANGEA;
+		pmac_mb.model_name = "Unknown Pangea-based";
+	    	pmac_mb.features = pangea_features;
+		break;
+	    default:
+	    	return -ENODEV;
+	}
+found:
+	/* Fixup Hooper vs. Comet */
+	if (pmac_mb.model_id == PMAC_TYPE_HOOPER) {
+		u32* mach_id_ptr = (u32*)ioremap(0xf3000034, 4);
+		if (!mach_id_ptr)
+			return -ENODEV;
+		/* Here, I used to disable the media-bay on comet. It
+		 * appears this is wrong, the floppy connector is actually
+		 * a kind of media-bay and works with the current driver.
+		 */
+		if ((*mach_id_ptr) & 0x20000000UL)
+			pmac_mb.model_id = PMAC_TYPE_COMET;
+		iounmap(mach_id_ptr);
+	}
+
+	/* Set default value of powersave_nap on machines that support it.
+	 * It appears that uninorth rev 3 has a problem with it, we don't
+	 * enable it on those. In theory, the flush-on-lock property is
+	 * supposed to be set when not supported, but I'm not very confident
+	 * that all Apple OF revs did it properly, I do it the paranoid way.
+	 */
+	while (uninorth_base && uninorth_rev > 3) {
+		struct device_node* np = find_path_device("/cpus");
+		u32 pvr = mfspr(PVR);
+		if (!np || !np->child) {
+			printk(KERN_WARNING "Can't find CPU(s) in device tree !\n");
+			break;
+		}
+		np = np->child;
+		/* Nap mode not supported on SMP */
+		if (np->sibling)
+			break;
+		/* Nap mode not supported if flush-on-lock property is present */
+		if (get_property(np, "flush-on-lock", NULL))
+			break;
+		/* Some 7450 may have problem with NAP mode too ... */
+		if (((pvr >> 16) == 0x8000) && ((pvr & 0xffff) < 0x0201))
+			break;
+		powersave_nap = 1;
+		printk(KERN_INFO "Processor NAP mode on idle enabled.\n");
+		break;
+	}
+
+	printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name);
+	return 0;
+}
+
+/* Initialize the Core99 UniNorth host bridge and memory controller
+ */
+static void __init
+probe_uninorth(void)
+{
+	unsigned long actrl;
+	
+	/* Locate core99 Uni-N */
+	uninorth_node = find_devices("uni-n");
+	if (uninorth_node && uninorth_node->n_addrs > 0) {
+		uninorth_base = ioremap(uninorth_node->addrs[0].address, 0x1000);
+		uninorth_rev = in_be32(UN_REG(UNI_N_VERSION));
+	} else
+		uninorth_node = NULL;
+		
+	if (!uninorth_node)
+		return;
+	
+	printk(KERN_INFO "Found Uninorth memory controller & host bridge, revision: %d\n",
+			uninorth_rev);
+
+	/* Set the arbitrer QAck delay according to what Apple does
+	 */
+	if (uninorth_rev < 0x10) {
+		actrl = UN_IN(UNI_N_ARB_CTRL) & ~UNI_N_ARB_CTRL_QACK_DELAY_MASK;
+		actrl |= ((uninorth_rev < 3) ? UNI_N_ARB_CTRL_QACK_DELAY105 :
+			UNI_N_ARB_CTRL_QACK_DELAY) << UNI_N_ARB_CTRL_QACK_DELAY_SHIFT;
+		UN_OUT(UNI_N_ARB_CTRL, actrl);
+	}
+}	
+
+static void __init
+probe_one_macio(const char* name, const char* compat, int type)
+{
+	struct device_node*	node;
+	int			i;
+	volatile u32*		base;
+	u32*			revp;
+	
+	node = find_devices(name);
+	if (!node || !node->n_addrs)
+		return;
+	if (compat)
+		do {
+			if (device_is_compatible(node, compat))
+				break;
+			node = node->next;
+		} while (node);
+	if (!node)
+		return;
+	for(i=0; i<MAX_MACIO_CHIPS; i++) {
+		if (!macio_chips[i].of_node)
+			break;
+		if (macio_chips[i].of_node == node)
+			return;
+	}
+	if (i >= MAX_MACIO_CHIPS) {
+		printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n");
+		printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name);
+		return;
+	}
+	base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size);
+	if (!base) {
+		printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n");
+		return;
+	}
+	if (type == macio_keylargo) {
+		u32* did = (u32 *)get_property(node, "device-id", NULL);
+		if (*did == 0x00000025)
+			type = macio_pangea;
+	}
+	macio_chips[i].of_node	= node;
+	macio_chips[i].type	= type;
+	macio_chips[i].base	= base;
+	macio_chips[i].flags	= MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON;
+	revp = (u32 *)get_property(node, "revision-id", NULL);
+	if (revp)
+		macio_chips[i].rev = *revp;
+	printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n",
+		macio_names[type], macio_chips[i].rev, macio_chips[i].base);
+}
+
+static int __init
+probe_macios(void)
+{
+	/* Warning, ordering is important */
+	probe_one_macio("gc", NULL, macio_grand_central);
+	probe_one_macio("ohare", NULL, macio_ohare);
+	probe_one_macio("pci106b,7", NULL, macio_ohareII);
+	probe_one_macio("mac-io", "keylargo", macio_keylargo);
+	probe_one_macio("mac-io", "paddington", macio_paddington);
+	probe_one_macio("mac-io", "gatwick", macio_gatwick);
+	probe_one_macio("mac-io", "heathrow", macio_heathrow);
+
+	/* Make sure the "main" macio chip appear first */
+	if (macio_chips[0].type == macio_gatwick
+	    && macio_chips[1].type == macio_heathrow) {
+		struct macio_chip temp = macio_chips[0];
+		macio_chips[0] = macio_chips[1];
+		macio_chips[1] = temp;
+	}
+	if (macio_chips[0].type == macio_ohareII
+	    && macio_chips[1].type == macio_ohare) {
+		struct macio_chip temp = macio_chips[0];
+		macio_chips[0] = macio_chips[1];
+		macio_chips[1] = temp;
+	}
+
+	return (macio_chips[0].of_node == NULL) ? -ENODEV : 0;
+}
+
+static void __init
+initial_serial_shutdown(struct device_node* np)
+{
+	int len;
+	struct slot_names_prop {
+		int	count;
+		char	name[1];
+	} *slots;
+	char *conn;
+	int port_type = PMAC_SCC_ASYNC;
+	int modem = 0;
+	
+	slots = (struct slot_names_prop *)get_property(np, "slot-names", &len);
+	conn = get_property(np, "AAPL,connector", &len);
+	if (conn && (strcmp(conn, "infrared") == 0))
+		port_type = PMAC_SCC_IRDA;
+	else if (device_is_compatible(np, "cobalt"))
+		modem = 1;
+	else if (slots && slots->count > 0) {
+		if (strcmp(slots->name, "IrDA") == 0)
+			port_type = PMAC_SCC_IRDA;
+		else if (strcmp(slots->name, "Modem") == 0)
+			modem = 1;
+	}
+	if (modem)
+		pmac_call_feature(PMAC_FTR_MODEM_ENABLE, np, 0, 0);
+	pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, port_type, 0);
+}
+
+static void __init
+set_initial_features(void)
+{
+	struct device_node* np;
+	
+	/* That hack appears to be necessary for some StarMax motherboards
+	 * but I'm not too sure it was audited for side-effects on other
+	 * ohare based machines...
+	 * Since I still have difficulties figuring the right way to
+	 * differenciate them all and since that hack was there for a long
+	 * time, I'll keep it around
+	 */
+	if (macio_chips[0].type == macio_ohare && !find_devices("via-pmu")) {
+		struct macio_chip* macio = &macio_chips[0];
+		MACIO_OUT32(OHARE_FCR, STARMAX_FEATURES);
+	} else if (macio_chips[0].type == macio_ohare) {
+		struct macio_chip* macio = &macio_chips[0];
+		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+	} else if (macio_chips[1].type == macio_ohare) {
+		struct macio_chip* macio = &macio_chips[1];
+		MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE);
+	}
+
+	if (macio_chips[0].type == macio_keylargo ||
+	    macio_chips[0].type == macio_pangea) {
+		/* Enable GMAC for now for PCI probing. It will be disabled
+		 * later on after PCI probe
+		 */
+		np = find_devices("ethernet");
+		while(np) {
+			if (np->parent
+			    && device_is_compatible(np->parent, "uni-north")
+			    && device_is_compatible(np, "gmac"))
+				core99_gmac_enable(np, 0, 1);
+			np = np->next;
+		}
+
+		/* Enable FW before PCI probe. Will be disabled later on
+		 * Note: We should have a batter way to check that we are
+		 * dealing with uninorth internal cell and not a PCI cell
+		 * on the external PCI. The code below works though.
+		 */
+		np = find_devices("firewire");
+		while(np) {
+			if (np->parent
+			    && device_is_compatible(np->parent, "uni-north")
+			    && (device_is_compatible(np, "pci106b,18") || 
+	     		        device_is_compatible(np, "pci106b,30") ||
+	     		        device_is_compatible(np, "pci11c1,5811"))) {
+				macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED;
+				core99_firewire_enable(np, 0, 1);
+			}
+			np = np->next;
+		}
+		
+		/* Switch airport off */
+		np = find_devices("radio");
+		while(np) {
+			if (np && np->parent == macio_chips[0].of_node) {
+				macio_chips[0].flags |= MACIO_FLAG_AIRPORT_ON;
+				core99_airport_enable(np, 0, 0);
+			}
+			np = np->next;
+		}
+	}
+
+	/* On all machines that support sound PM, switch sound off */
+	if (macio_chips[0].of_node)
+		pmac_do_feature_call(PMAC_FTR_SOUND_CHIP_ENABLE,
+			macio_chips[0].of_node, 0, 0);
+
+	/* While on some desktop G3s, we turn it back on */
+	if (macio_chips[0].of_node && macio_chips[0].type == macio_heathrow
+		&& (pmac_mb.model_id == PMAC_TYPE_GOSSAMER ||
+		    pmac_mb.model_id == PMAC_TYPE_SILK)) {
+		struct macio_chip* macio = &macio_chips[0];
+		MACIO_BIS(HEATHROW_FCR, HRW_SOUND_CLK_ENABLE);
+		MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N);
+	}
+
+
+	/* On all machines, switch modem & serial ports off */
+	np = find_devices("ch-a");
+	while(np) {
+		initial_serial_shutdown(np);
+		np = np->next;
+	}
+	np = find_devices("ch-b");
+	while(np) {
+		initial_serial_shutdown(np);
+		np = np->next;
+	}
+	
+	/* Let hardware settle down */
+	mdelay(10);
+}
+
+void __init
+pmac_feature_init(void)
+{
+	/* Detect the UniNorth memory controller */
+	probe_uninorth();
+
+	/* Probe mac-io controllers */
+	if (probe_macios()) {
+		printk(KERN_WARNING "No mac-io chip found\n");
+		return;
+	}
+
+	/* Probe machine type */
+	if (probe_motherboard())
+		printk(KERN_WARNING "Unknown PowerMac !\n");
+
+	/* Set some initial features (turn off some chips that will
+	 * be later turned on)
+	 */
+	set_initial_features();
+}
+
+void __init
+pmac_feature_late_init(void)
+{
+	struct device_node* np;
+	
+	/* Request some resources late */
+	if (uninorth_node)
+		request_OF_resource(uninorth_node, 0, NULL);
+	np = find_devices("hammerhead");
+	if (np)
+		request_OF_resource(np, 0, NULL);
+	np = find_devices("interrupt-controller");
+	if (np)
+		request_OF_resource(np, 0, NULL);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_nvram.c linux/arch/ppc/platforms/pmac_nvram.c
--- linux.orig/arch/ppc/platforms/pmac_nvram.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_nvram.c	2002-08-12 22:14:17.000000000 +0000
@@ -0,0 +1,402 @@
+/*
+ * BK Id: SCCS/s.pmac_nvram.c 1.17 12/01/01 20:09:06 benh
+ */
+/*
+ * Miscellaneous procedures for dealing with the PowerMac hardware.
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/nvram.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+#include <asm/nvram.h>
+#include <linux/adb.h>
+#include <linux/pmu.h>
+
+#undef DEBUG
+
+#define NVRAM_SIZE		0x2000	/* 8kB of non-volatile RAM */
+
+#define CORE99_SIGNATURE	0x5a
+#define CORE99_ADLER_START	0x14
+
+/* Core99 nvram is a flash */
+#define CORE99_FLASH_STATUS_DONE	0x80
+#define CORE99_FLASH_STATUS_ERR		0x38
+#define CORE99_FLASH_CMD_ERASE_CONFIRM	0xd0
+#define CORE99_FLASH_CMD_ERASE_SETUP	0x20
+#define CORE99_FLASH_CMD_RESET		0xff
+#define CORE99_FLASH_CMD_WRITE_SETUP	0x40
+
+/* CHRP NVRAM header */
+struct chrp_header {
+  u8		signature;
+  u8		cksum;
+  u16		len;
+  char          name[12];
+  u8		data[0];
+};
+
+struct core99_header {
+  struct chrp_header	hdr;
+  u32			adler;
+  u32			generation;
+  u32			reserved[2];
+};
+
+/*
+ * Read and write the non-volatile RAM on PowerMacs and CHRP machines.
+ */
+static int nvram_naddrs;
+static volatile unsigned char *nvram_addr;
+static volatile unsigned char *nvram_data;
+static int nvram_mult, is_core_99;
+static int core99_bank = 0;
+static int nvram_partitions[3];
+
+/* FIXME: kmalloc fails to allocate the image now that I had to move it
+ *        before time_init(). For now, I allocate a static buffer here
+ *        but it's a waste of space on all but core99 machines
+ */
+#if 0
+static char* nvram_image;
+#else
+static char nvram_image[NVRAM_SIZE] __pmacdata;
+#endif
+
+extern int pmac_newworld;
+
+static u8 __openfirmware
+chrp_checksum(struct chrp_header* hdr)
+{
+	u8 *ptr;
+	u16 sum = hdr->signature;
+	for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++)
+		sum += *ptr;
+	while (sum > 0xFF)
+		sum = (sum & 0xFF) + (sum>>8);
+	return sum;
+}
+
+static u32 __pmac
+core99_calc_adler(u8 *buffer)
+{
+	int cnt;
+	u32 low, high;
+
+   	buffer += CORE99_ADLER_START;
+	low = 1;
+	high = 0;
+	for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) {
+		if ((cnt % 5000) == 0) {
+			high  %= 65521UL;
+			high %= 65521UL;
+		}
+		low += buffer[cnt];
+		high += low;
+	}
+	low  %= 65521UL;
+	high %= 65521UL;
+  
+	return (high << 16) | low;
+}
+
+static u32 __pmac
+core99_check(u8* datas)
+{
+	struct core99_header* hdr99 = (struct core99_header*)datas;
+
+	if (hdr99->hdr.signature != CORE99_SIGNATURE) {
+#ifdef DEBUG
+		printk("Invalid signature\n");
+#endif		
+		return 0;
+	}
+	if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) {
+#ifdef DEBUG
+		printk("Invalid checksum\n");
+#endif
+		return 0;
+	}
+	if (hdr99->adler != core99_calc_adler(datas)) {
+#ifdef DEBUG
+		printk("Invalid adler\n");
+#endif
+		return 0;
+	}
+	return hdr99->generation;
+}
+
+static int __pmac
+core99_erase_bank(int bank)
+{
+	int stat, i;
+	
+	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+	
+	out_8(base, CORE99_FLASH_CMD_ERASE_SETUP);
+	out_8(base, CORE99_FLASH_CMD_ERASE_CONFIRM);
+	do { stat = in_8(base); }
+	while(!(stat & CORE99_FLASH_STATUS_DONE));
+	out_8(base, CORE99_FLASH_CMD_RESET);
+	if (stat & CORE99_FLASH_STATUS_ERR) {
+		printk("nvram: flash error 0x%02x on erase !\n", stat);
+		return -ENXIO;
+	}
+	for (i=0; i<NVRAM_SIZE; i++)
+		if (base[i] != 0xff) {
+			printk("nvram: flash erase failed !\n");
+			return -ENXIO;
+		}
+	return 0;
+}
+
+static int __pmac
+core99_write_bank(int bank, u8* datas)
+{
+	int i, stat = 0;
+	
+	u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE;
+	
+	for (i=0; i<NVRAM_SIZE; i++) {
+		out_8(base+i, CORE99_FLASH_CMD_WRITE_SETUP);
+		out_8(base+i, datas[i]);
+		do { stat = in_8(base); }
+		while(!(stat & CORE99_FLASH_STATUS_DONE));
+		if (stat & CORE99_FLASH_STATUS_ERR)
+			break;
+	}
+	out_8(base, CORE99_FLASH_CMD_RESET);
+	if (stat & CORE99_FLASH_STATUS_ERR) {
+		printk("nvram: flash error 0x%02x on write !\n", stat);
+		return -ENXIO;
+	}
+	for (i=0; i<NVRAM_SIZE; i++)
+		if (base[i] != datas[i]) {
+			printk("nvram: flash write failed !\n");
+			return -ENXIO;
+		}
+	return 0;	
+}
+
+static void __init
+lookup_partitions(void)
+{
+	u8 buffer[17];
+	int i, offset;
+	struct chrp_header* hdr;
+
+	if (pmac_newworld) {
+		nvram_partitions[pmac_nvram_OF] = -1;
+		nvram_partitions[pmac_nvram_XPRAM] = -1;
+		nvram_partitions[pmac_nvram_NR] = -1;
+		hdr = (struct chrp_header *)buffer;
+	
+		offset = 0;
+		buffer[16] = 0;
+		do {
+			for (i=0;i<16;i++)
+				buffer[i] = nvram_read_byte(offset+i);
+			if (!strcmp(hdr->name, "common"))
+				nvram_partitions[pmac_nvram_OF] = offset + 0x10;
+			if (!strcmp(hdr->name, "APL,MacOS75")) {
+				nvram_partitions[pmac_nvram_XPRAM] = offset + 0x10;
+				nvram_partitions[pmac_nvram_NR] = offset + 0x110;
+			}
+			offset += (hdr->len * 0x10);
+		} while(offset < NVRAM_SIZE);
+	} else {
+		nvram_partitions[pmac_nvram_OF] = 0x1800;
+		nvram_partitions[pmac_nvram_XPRAM] = 0x1300;
+		nvram_partitions[pmac_nvram_NR] = 0x1400;
+	}	
+#ifdef DEBUG
+	printk("nvram: OF partition at 0x%x\n", nvram_partitions[pmac_nvram_OF]);
+	printk("nvram: XP partition at 0x%x\n", nvram_partitions[pmac_nvram_XPRAM]);
+	printk("nvram: NR partition at 0x%x\n", nvram_partitions[pmac_nvram_NR]);
+#endif	
+}
+
+void __init
+pmac_nvram_init(void)
+{
+	struct device_node *dp;
+
+	nvram_naddrs = 0;
+
+	dp = find_devices("nvram");
+	if (dp == NULL) {
+		printk(KERN_ERR "Can't find NVRAM device\n");
+		return;
+	}
+	nvram_naddrs = dp->n_addrs;
+	is_core_99 = device_is_compatible(dp, "nvram,flash");
+	if (is_core_99) {
+		int i;
+		u32 gen_bank0, gen_bank1;
+		
+		if (nvram_naddrs < 1) {
+			printk(KERN_ERR "nvram: no address\n");
+			return;
+		}
+#if 0
+		nvram_image = kmalloc(NVRAM_SIZE, GFP_KERNEL);
+		if (!nvram_image) {
+			printk(KERN_ERR "nvram: can't allocate image\n");
+			return;
+		}
+#endif
+		nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2);
+#ifdef DEBUG
+		printk("nvram: Checking bank 0...\n");
+#endif
+		gen_bank0 = core99_check((u8 *)nvram_data);
+		gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE);
+		core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0;
+#ifdef DEBUG
+		printk("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1);
+		printk("nvram: Active bank is: %d\n", core99_bank);
+#endif
+		for (i=0; i<NVRAM_SIZE; i++)
+			nvram_image[i] = nvram_data[i + core99_bank*NVRAM_SIZE];
+	} else if (_machine == _MACH_chrp && nvram_naddrs == 1) {
+		nvram_data = ioremap(dp->addrs[0].address + isa_mem_base,
+				     dp->addrs[0].size);
+		nvram_mult = 1;
+	} else if (nvram_naddrs == 1) {
+		nvram_data = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+		nvram_mult = (dp->addrs[0].size + NVRAM_SIZE - 1) / NVRAM_SIZE;
+	} else if (nvram_naddrs == 2) {
+		nvram_addr = ioremap(dp->addrs[0].address, dp->addrs[0].size);
+		nvram_data = ioremap(dp->addrs[1].address, dp->addrs[1].size);
+	} else if (nvram_naddrs == 0 && sys_ctrler == SYS_CTRLER_PMU) {
+		nvram_naddrs = -1;
+	} else {
+		printk(KERN_ERR "Don't know how to access NVRAM with %d addresses\n",
+		       nvram_naddrs);
+	}
+	lookup_partitions();
+}
+
+void __pmac
+pmac_nvram_update(void)
+{
+	struct core99_header* hdr99;
+	
+	if (!is_core_99 || !nvram_data || !nvram_image)
+		return;
+	if (!memcmp(nvram_image, (u8*)nvram_data + core99_bank*NVRAM_SIZE,
+		NVRAM_SIZE))
+		return;
+#ifdef DEBUG
+	printk("Updating nvram...\n");
+#endif
+	hdr99 = (struct core99_header*)nvram_image;
+	hdr99->generation++;
+	hdr99->hdr.signature = CORE99_SIGNATURE;
+	hdr99->hdr.cksum = chrp_checksum(&hdr99->hdr);
+	hdr99->adler = core99_calc_adler(nvram_image);
+	core99_bank = core99_bank ? 0 : 1;
+	if (core99_erase_bank(core99_bank)) {
+		printk("nvram: Error erasing bank %d\n", core99_bank);
+		return;
+	}
+	if (core99_write_bank(core99_bank, nvram_image))
+		printk("nvram: Error writing bank %d\n", core99_bank);
+}
+
+unsigned char __openfirmware
+nvram_read_byte(int addr)
+{
+	switch (nvram_naddrs) {
+#ifdef CONFIG_ADB_PMU
+	case -1: {
+		struct adb_request req;
+
+		if (pmu_request(&req, NULL, 3, PMU_READ_NVRAM,
+				(addr >> 8) & 0xff, addr & 0xff))
+			break;
+		while (!req.complete)
+			pmu_poll();
+		return req.reply[0];
+	}
+#endif
+	case 1:
+		if (is_core_99)
+			return nvram_image[addr];
+		return nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult];
+	case 2:
+		*nvram_addr = addr >> 5;
+		eieio();
+		return nvram_data[(addr & 0x1f) << 4];
+	}
+	return 0;
+}
+
+void __openfirmware
+nvram_write_byte(unsigned char val, int addr)
+{
+	switch (nvram_naddrs) {
+#ifdef CONFIG_ADB_PMU
+	case -1: {
+		struct adb_request req;
+
+		if (pmu_request(&req, NULL, 4, PMU_WRITE_NVRAM,
+				(addr >> 8) & 0xff, addr & 0xff, val))
+			break;
+		while (!req.complete)
+			pmu_poll();
+		break;
+	}
+#endif
+	case 1:
+		if (is_core_99) {
+			nvram_image[addr] = val;
+			break;
+		}
+		nvram_data[(addr & (NVRAM_SIZE - 1)) * nvram_mult] = val;
+		break;
+	case 2:
+		*nvram_addr = addr >> 5;
+		eieio();
+		nvram_data[(addr & 0x1f) << 4] = val;
+		break;
+	}
+	eieio();
+}
+
+int __pmac
+pmac_get_partition(int partition)
+{
+	return nvram_partitions[partition];
+}
+
+u8 __pmac
+pmac_xpram_read(int xpaddr)
+{
+	int offset = nvram_partitions[pmac_nvram_XPRAM];
+	
+	if (offset < 0)
+		return 0;
+		
+	return nvram_read_byte(xpaddr + offset);
+}
+
+void __pmac
+pmac_xpram_write(int xpaddr, u8 data)
+{
+	int offset = nvram_partitions[pmac_nvram_XPRAM];
+	
+	if (offset < 0)
+		return;
+		
+	nvram_write_byte(xpaddr + offset, data);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_pci.c linux/arch/ppc/platforms/pmac_pci.c
--- linux.orig/arch/ppc/platforms/pmac_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_pci.c	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,613 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * Support for PCI bridges found on Power Macintoshes.
+ * At present the "bandit" and "chaos" bridges are supported.
+ * Fortunately you access configuration space in the same
+ * way with either bridge.
+ *
+ * Copyright (C) 1997 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+
+#undef DEBUG
+
+static void add_bridges(struct device_node *dev);
+
+/* XXX Could be per-controller, but I don't think we risk anything by
+ * assuming we won't have both UniNorth and Bandit */
+static int has_uninorth;
+
+/*
+ * Magic constants for enabling cache coherency in the bandit/PSX bridge.
+ */
+#define BANDIT_DEVID_2	8
+#define BANDIT_REVID	3
+
+#define BANDIT_DEVNUM	11
+#define BANDIT_MAGIC	0x50
+#define BANDIT_COHERENT	0x40
+
+static int __init
+fixup_one_level_bus_range(struct device_node *node, int higher)
+{
+	for (; node != 0;node = node->sibling) {
+		int * bus_range;
+		unsigned int *class_code;			
+		int len;
+
+		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		class_code = (unsigned int *) get_property(node, "class-code", 0);
+		if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+			continue;
+		bus_range = (int *) get_property(node, "bus-range", &len);
+		if (bus_range != NULL && len > 2 * sizeof(int)) {
+			if (bus_range[1] > higher)
+				higher = bus_range[1];
+		}
+		higher = fixup_one_level_bus_range(node->child, higher);
+	}
+	return higher;
+}
+
+/* This routine fixes the "bus-range" property of all bridges in the
+ * system since they tend to have their "last" member wrong on macs
+ * 
+ * Note that the bus numbers manipulated here are OF bus numbers, they
+ * are not Linux bus numbers.
+ */
+static void __init
+fixup_bus_range(struct device_node *bridge)
+{
+	int * bus_range;
+	int len;
+	
+	/* Lookup the "bus-range" property for the hose */		
+	bus_range = (int *) get_property(bridge, "bus-range", &len);
+	if (bus_range == NULL || len < 2 * sizeof(int)) {
+		printk(KERN_WARNING "Can't get bus-range for %s\n",
+			       bridge->full_name);
+		return;
+	}
+	bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]);
+}
+
+/*
+ * Apple MacRISC (UniNorth, Bandit, Chaos) PCI controllers.
+ * 
+ * The "Bandit" version is present in all early PCI PowerMacs,
+ * and up to the first ones using Grackle. Some machines may
+ * have 2 bandit controllers (2 PCI busses).
+ * 
+ * "Chaos" is used in some "Bandit"-type machines as a bridge
+ * for the separate display bus. It is accessed the same
+ * way as bandit, but cannot be probed for devices. It therefore
+ * has its own config access functions.
+ *
+ * The "UniNorth" version is present in all Core99 machines
+ * (iBook, G4, new IMacs, and all the recent Apple machines).
+ * It contains 3 controllers in one ASIC.
+ */
+
+#define MACRISC_CFA0(devfn, off)	\
+	((1 << (unsigned long)PCI_SLOT(dev_fn)) \
+	| (((unsigned long)PCI_FUNC(dev_fn)) << 8) \
+	| (((unsigned long)(off)) & 0xFCUL))
+
+#define MACRISC_CFA1(bus, devfn, off)	\
+	((((unsigned long)(bus)) << 16) \
+	|(((unsigned long)(devfn)) << 8) \
+	|(((unsigned long)(off)) & 0xFCUL) \
+	|1UL)
+	
+static unsigned int __pmac
+macrisc_cfg_access(struct pci_controller* hose, u8 bus, u8 dev_fn, u8 offset)
+{
+	unsigned int caddr;
+	
+	if (bus == hose->first_busno) {
+		if (dev_fn < (11 << 3))
+			return 0;
+		caddr = MACRISC_CFA0(dev_fn, offset);
+	} else
+		caddr = MACRISC_CFA1(bus, dev_fn, offset);
+	
+	/* Uninorth will return garbage if we don't read back the value ! */
+	do {
+		out_le32(hose->cfg_addr, caddr);
+	} while(in_le32(hose->cfg_addr) != caddr);
+
+	offset &= has_uninorth ? 0x07 : 0x03;
+	return (unsigned int)(hose->cfg_data) + (unsigned int)offset;
+}
+
+#define cfg_read(val, addr, type, op, op2)	\
+	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op, op2)	\
+	op((type *)(addr), (val)); (void) op2((type *)(addr))
+
+#define cfg_read_bad(val, size)		*val = bad_##size;
+#define cfg_write_bad(val, size)
+
+#define bad_byte	0xff
+#define bad_word	0xffff
+#define bad_dword	0xffffffffU
+
+#define MACRISC_PCI_OP(rw, size, type, op, op2)				    \
+static int __pmac							    \
+macrisc_##rw##_config_##size(struct pci_dev *dev, int off, type val)	    \
+{									    \
+	struct pci_controller *hose = dev->sysdata;			    \
+	unsigned int addr;						    \
+									    \
+	addr = macrisc_cfg_access(hose, dev->bus->number, dev->devfn, off); \
+	if (!addr) {							    \
+		cfg_##rw##_bad(val, size)				    \
+		return PCIBIOS_DEVICE_NOT_FOUND;			    \
+	}								    \
+	cfg_##rw(val, addr, type, op, op2);				    \
+	return PCIBIOS_SUCCESSFUL;					    \
+}
+
+MACRISC_PCI_OP(read, byte, u8 *, in_8, x)
+MACRISC_PCI_OP(read, word, u16 *, in_le16, x)
+MACRISC_PCI_OP(read, dword, u32 *, in_le32, x)
+MACRISC_PCI_OP(write, byte, u8, out_8, in_8)
+MACRISC_PCI_OP(write, word, u16, out_le16, in_le16)
+MACRISC_PCI_OP(write, dword, u32, out_le32, in_le32)
+
+static struct pci_ops macrisc_pci_ops =
+{
+	macrisc_read_config_byte,
+	macrisc_read_config_word,
+	macrisc_read_config_dword,
+	macrisc_write_config_byte,
+	macrisc_write_config_word,
+	macrisc_write_config_dword
+};
+
+/*
+ * Verifiy that a specific (bus, dev_fn) exists on chaos
+ */
+static int __pmac
+chaos_validate_dev(struct pci_dev *dev, int offset)
+{
+	if(pci_device_to_OF_node(dev) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	if((dev->vendor == 0x106b) && (dev->device == 3) && (offset >= 0x10) &&
+	    (offset != 0x14) && (offset != 0x18) && (offset <= 0x24)) {
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#define CHAOS_PCI_OP(rw, size, type)					\
+static int __pmac							\
+chaos_##rw##_config_##size(struct pci_dev *dev, int off, type val)	\
+{									\
+	int result = chaos_validate_dev(dev, off);			\
+	if(result == PCIBIOS_BAD_REGISTER_NUMBER) {			\
+		cfg_##rw##_bad(val, size)				\
+		return PCIBIOS_BAD_REGISTER_NUMBER;			\
+	}								\
+	if(result == PCIBIOS_SUCCESSFUL)				\
+		return macrisc_##rw##_config_##size(dev, off, val);	\
+	return result;							\
+}
+
+CHAOS_PCI_OP(read, byte, u8 *)
+CHAOS_PCI_OP(read, word, u16 *)
+CHAOS_PCI_OP(read, dword, u32 *)
+CHAOS_PCI_OP(write, byte, u8)
+CHAOS_PCI_OP(write, word, u16)
+CHAOS_PCI_OP(write, dword, u32) 
+
+static struct pci_ops chaos_pci_ops =
+{
+	chaos_read_config_byte,
+	chaos_read_config_word,
+	chaos_read_config_dword,
+	chaos_write_config_byte,
+	chaos_write_config_word,
+	chaos_write_config_dword
+};
+
+
+/*
+ * For a bandit bridge, turn on cache coherency if necessary.
+ * N.B. we could clean this up using the hose ops directly.
+ */
+static void __init
+init_bandit(struct pci_controller *bp)
+{
+	unsigned int vendev, magic;
+	int rev;
+
+	/* read the word at offset 0 in config space for device 11 */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
+	udelay(2);
+	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
+	if (vendev == (PCI_DEVICE_ID_APPLE_BANDIT << 16) + 
+			PCI_VENDOR_ID_APPLE) {
+		/* read the revision id */
+		out_le32(bp->cfg_addr,
+			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
+		udelay(2);
+		rev = in_8(bp->cfg_data);
+		if (rev != BANDIT_REVID)
+			printk(KERN_WARNING
+			       "Unknown revision %d for bandit\n", rev);
+	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
+		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
+		return;
+	}
+
+	/* read the word at offset 0x50 */
+	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + BANDIT_MAGIC);
+	udelay(2);
+	magic = in_le32((volatile unsigned int *)bp->cfg_data);
+	if ((magic & BANDIT_COHERENT) != 0)
+		return;
+	magic |= BANDIT_COHERENT;
+	udelay(2);
+	out_le32((volatile unsigned int *)bp->cfg_data, magic);
+	printk(KERN_INFO "Cache coherency enabled for bandit/PSX\n");
+}
+
+
+/*
+ * Tweak the PCI-PCI bridge chip on the blue & white G3s.
+ */
+static void __init
+init_p2pbridge(void)
+{
+	struct device_node *p2pbridge;
+	struct pci_controller* hose;
+	u8 bus, devfn;
+	u16 val;
+
+	/* XXX it would be better here to identify the specific
+	   PCI-PCI bridge chip we have. */
+	if ((p2pbridge = find_devices("pci-bridge")) == 0
+	    || p2pbridge->parent == NULL
+	    || strcmp(p2pbridge->parent->name, "pci") != 0)
+		return;
+	if (pci_device_from_OF_node(p2pbridge, &bus, &devfn) < 0) {
+#ifdef DEBUG
+		printk("Can't find PCI infos for PCI<->PCI bridge\n");
+#endif		
+		return;
+	}
+	/* Warning: At this point, we have not yet renumbered all busses. 
+	 * So we must use OF walking to find out hose
+	 */
+	hose = pci_find_hose_for_OF_device(p2pbridge);
+	if (!hose) {
+#ifdef DEBUG
+		printk("Can't find hose for PCI<->PCI bridge\n");
+#endif		
+		return;
+	}
+	if (early_read_config_word(hose, bus, devfn,
+				   PCI_BRIDGE_CONTROL, &val) < 0) {
+		printk(KERN_ERR "init_p2pbridge: couldn't read bridge control\n");
+		return;
+	}
+	val &= ~PCI_BRIDGE_CTL_MASTER_ABORT;
+	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, val);
+}
+
+void __init
+pmac_find_bridges(void)
+{
+	add_bridges(find_devices("bandit"));
+	add_bridges(find_devices("chaos"));
+	add_bridges(find_devices("pci"));
+	init_p2pbridge();
+}
+
+#define GRACKLE_CFA(b, d, o)	(0x80 | ((b) << 8) | ((d) << 16) \
+				 | (((o) & ~3) << 24))
+
+#define GRACKLE_PICR1_STG		0x00000040
+#define GRACKLE_PICR1_LOOPSNOOP		0x00000010
+
+/* N.B. this is called before bridges is initialized, so we can't
+   use grackle_pcibios_{read,write}_config_dword. */
+static inline void grackle_set_stg(struct pci_controller* bp, int enable)
+{
+	unsigned int val;
+
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	val = in_le32((volatile unsigned int *)bp->cfg_data);
+	val = enable? (val | GRACKLE_PICR1_STG) :
+		(val & ~GRACKLE_PICR1_STG);
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	out_le32((volatile unsigned int *)bp->cfg_data, val);
+	(void)in_le32((volatile unsigned int *)bp->cfg_data);
+}
+
+static inline void grackle_set_loop_snoop(struct pci_controller *bp, int enable)
+{
+	unsigned int val;
+
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	val = in_le32((volatile unsigned int *)bp->cfg_data);
+	val = enable? (val | GRACKLE_PICR1_LOOPSNOOP) :
+		(val & ~GRACKLE_PICR1_LOOPSNOOP);
+	out_be32(bp->cfg_addr, GRACKLE_CFA(0, 0, 0xa8));
+	out_le32((volatile unsigned int *)bp->cfg_data, val);
+	(void)in_le32((volatile unsigned int *)bp->cfg_data);
+}
+
+static int __init
+setup_uninorth(struct pci_controller* hose, struct reg_property* addr)
+{
+	pci_assign_all_busses = 1;
+	has_uninorth = 1;
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = ioremap(addr->address + 0xc00000, 0x1000);
+	/* We "know" that the bridge at f2000000 has the PCI slots. */
+	return addr->address == 0xf2000000;
+}
+
+static void __init
+setup_bandit(struct pci_controller* hose, struct reg_property* addr)
+{
+	hose->ops = &macrisc_pci_ops;
+	hose->cfg_addr = (volatile unsigned int *)
+		ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = (volatile unsigned char *)
+		ioremap(addr->address + 0xc00000, 0x1000);
+	init_bandit(hose);
+}
+
+static void __init
+setup_chaos(struct pci_controller* hose, struct reg_property* addr)
+{
+	/* assume a `chaos' bridge */
+	hose->ops = &chaos_pci_ops;
+	hose->cfg_addr = (volatile unsigned int *)
+		ioremap(addr->address + 0x800000, 0x1000);
+	hose->cfg_data = (volatile unsigned char *)
+		ioremap(addr->address + 0xc00000, 0x1000);
+}
+
+void __init
+setup_grackle(struct pci_controller *hose)
+{
+	setup_indirect_pci(hose, 0xfec00000, 0xfee00000);
+	if (machine_is_compatible("AAPL,PowerBook1998"))
+		grackle_set_loop_snoop(hose, 1);
+#if 0	/* Disabled for now, HW problems ??? */
+	grackle_set_stg(hose, 1);
+#endif
+}
+
+/*
+ * We assume that if we have a G3 powermac, we have one bridge called
+ * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise,
+ * if we have one or more bandit or chaos bridges, we don't have a MPC106.
+ */
+static void __init
+add_bridges(struct device_node *dev)
+{
+	int len;
+	struct pci_controller *hose;
+	struct reg_property *addr;
+	char* disp_name;
+	int *bus_range;
+	int first = 1, primary;
+	
+	for (; dev != NULL; dev = dev->next) {
+		addr = (struct reg_property *) get_property(dev, "reg", &len);
+		if (addr == NULL || len < sizeof(*addr)) {
+			printk(KERN_WARNING "Can't use %s: no address\n",
+			       dev->full_name);
+			continue;
+		}
+		bus_range = (int *) get_property(dev, "bus-range", &len);
+		if (bus_range == NULL || len < 2 * sizeof(int)) {
+			printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n",
+				       dev->full_name);
+		}
+		
+		hose = pcibios_alloc_controller();
+		if (!hose)
+			continue;
+		hose->arch_data = dev;
+		hose->first_busno = bus_range ? bus_range[0] : 0;
+		hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+		disp_name = NULL;
+		primary = first;
+		if (device_is_compatible(dev, "uni-north")) {
+			primary = setup_uninorth(hose, addr);
+			disp_name = "UniNorth";
+		} else if (strcmp(dev->name, "pci") == 0) {
+			/* XXX assume this is a mpc106 (grackle) */
+			setup_grackle(hose);
+			disp_name = "Grackle (MPC106)";
+		} else if (strcmp(dev->name, "bandit") == 0) {
+			setup_bandit(hose, addr);
+			disp_name = "Bandit";
+		} else if (strcmp(dev->name, "chaos") == 0) {
+			setup_chaos(hose, addr);
+			disp_name = "Chaos";
+			primary = 0;
+		}
+		printk(KERN_INFO "Found %s PCI host bridge at 0x%08x. Firmware bus number: %d->%d\n",
+			disp_name, addr->address, hose->first_busno, hose->last_busno);
+#ifdef DEBUG
+		printk(" ->Hose at 0x%08lx, cfg_addr=0x%08lx,cfg_data=0x%08lx\n",
+			hose, hose->cfg_addr, hose->cfg_data);
+#endif		
+		
+		/* Interpret the "ranges" property */
+		/* This also maps the I/O region and sets isa_io/mem_base */
+		pci_process_bridge_OF_ranges(hose, dev, primary);
+
+		/* Fixup "bus-range" OF property */
+		fixup_bus_range(dev);
+
+		first &= !primary;
+	}
+}
+
+static void __init
+pcibios_fixup_OF_interrupts(void)
+{	
+	struct pci_dev* dev;
+	
+	/*
+	 * Open Firmware often doesn't initialize the
+	 * PCI_INTERRUPT_LINE config register properly, so we
+	 * should find the device node and apply the interrupt
+	 * obtained from the OF device-tree
+	 */
+	pci_for_each_dev(dev) {
+		struct device_node* node = pci_device_to_OF_node(dev);
+		/* this is the node, see if it has interrupts */
+		if (node && node->n_intrs > 0)
+			dev->irq = node->intrs[0].line;
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	}
+}
+
+void __init
+pmac_pcibios_fixup(void)
+{
+	/* Fixup interrupts according to OF tree */
+	pcibios_fixup_OF_interrupts();
+}
+
+int __pmac
+pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
+{
+	struct device_node* node;
+	int updatecfg = 0;
+	int uninorth_child;
+
+	node = pci_device_to_OF_node(dev);
+
+	/* We don't want to enable USB controllers absent from the OF tree
+	 * (iBook second controller)
+	 */
+	if (dev->vendor == PCI_VENDOR_ID_APPLE
+	    && dev->device == PCI_DEVICE_ID_APPLE_KL_USB && !node)
+		return -EINVAL;
+
+	if (!node)
+		return 0;
+
+	uninorth_child = node->parent &&
+		device_is_compatible(node->parent, "uni-north");
+		
+	/* Firewire & GMAC were disabled after PCI probe, the driver is
+	 * claiming them, we must re-enable them now.
+	 */
+	if (uninorth_child && !strcmp(node->name, "firewire") && 
+	    (device_is_compatible(node, "pci106b,18") || 
+	     device_is_compatible(node, "pci106b,30") ||
+	     device_is_compatible(node, "pci11c1,5811"))) {
+		pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, node, 0, 1);
+		pmac_call_feature(PMAC_FTR_1394_ENABLE, node, 0, 1);
+		updatecfg = 1;
+	}
+	if (uninorth_child && !strcmp(node->name, "ethernet") && 
+	    device_is_compatible(node, "gmac")) {
+		pmac_call_feature(PMAC_FTR_GMAC_ENABLE, node, 0, 1);
+		updatecfg = 1;
+	}
+
+	if (updatecfg) {
+		u16 cmd;
+		
+		/*
+		 * Make sure PCI is correctly configured
+		 *
+		 * We use old pci_bios versions of the function since, by
+		 * default, gmac is not powered up, and so will be absent
+		 * from the kernel initial PCI lookup. 
+		 * 
+		 * Should be replaced by 2.4 new PCI mecanisms and really
+		 * regiser the device.
+		 */
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE;
+    		pci_write_config_word(dev, PCI_COMMAND, cmd);
+    		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 16);
+    		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 8);
+	}
+	
+	return 0;
+}
+
+/* We power down some devices after they have been probed. They'll
+ * be powered back on later on
+ */
+void __init
+pmac_pcibios_after_init(void)
+{
+	struct device_node* nd;
+
+#ifdef CONFIG_BLK_DEV_IDE
+	struct pci_dev *dev;
+
+	/* OF fails to initialize IDE controllers on macs
+	 * (and maybe other machines)
+	 * 
+	 * Ideally, this should be moved to the IDE layer, but we need
+	 * to check specifically with Andre Hedrick how to do it cleanly
+	 * since the common IDE code seem to care about the fact that the
+	 * BIOS may have disabled a controller.
+	 * 
+	 * -- BenH
+	 */
+	pci_for_each_dev(dev) {
+		if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
+			pci_enable_device(dev);
+	}
+#endif /* CONFIG_BLK_DEV_IDE */
+
+	nd = find_devices("firewire");
+	while (nd) {
+		if (nd->parent && (device_is_compatible(nd, "pci106b,18") ||
+				   device_is_compatible(nd, "pci106b,30") ||
+				   device_is_compatible(nd, "pci11c1,5811"))
+		    && device_is_compatible(nd->parent, "uni-north")) {
+			pmac_call_feature(PMAC_FTR_1394_ENABLE, nd, 0, 0);
+			pmac_call_feature(PMAC_FTR_1394_CABLE_POWER, nd, 0, 0);
+		}
+		nd = nd->next;
+	}
+	nd = find_devices("ethernet");
+	while (nd) {
+		if (nd->parent && device_is_compatible(nd, "gmac")
+		    && device_is_compatible(nd->parent, "uni-north"))
+			pmac_call_feature(PMAC_FTR_GMAC_ENABLE, nd, 0, 0);
+		nd = nd->next;
+	}
+}
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_pic.c linux/arch/ppc/platforms/pmac_pic.c
--- linux.orig/arch/ppc/platforms/pmac_pic.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_pic.c	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,528 @@
+/*
+ * BK Id: SCCS/s.pmac_pic.c 1.24 12/19/01 10:53:01 paulus
+ */
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/pci.h>
+
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/smp.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+
+#include "pmac_pic.h"
+
+struct pmac_irq_hw {
+        unsigned int    event;
+        unsigned int    enable;
+        unsigned int    ack;
+        unsigned int    level;
+};
+
+/* Default addresses */
+static volatile struct pmac_irq_hw *pmac_irq_hw[4] __pmacdata = {
+        (struct pmac_irq_hw *) 0xf3000020,
+        (struct pmac_irq_hw *) 0xf3000010,
+        (struct pmac_irq_hw *) 0xf4000020,
+        (struct pmac_irq_hw *) 0xf4000010,
+};
+
+#define GC_LEVEL_MASK		0x3ff00000
+#define OHARE_LEVEL_MASK	0x1ff00000
+#define HEATHROW_LEVEL_MASK	0x1ff00000
+
+static int max_irqs __pmacdata;
+static int max_real_irqs __pmacdata;
+static u32 level_mask[4] __pmacdata;
+
+static spinlock_t pmac_pic_lock __pmacdata = SPIN_LOCK_UNLOCKED;
+
+
+#define GATWICK_IRQ_POOL_SIZE        10
+static struct interrupt_info gatwick_int_pool[GATWICK_IRQ_POOL_SIZE] __pmacdata;
+
+/*
+ * Mark an irq as "lost".  This is only used on the pmac
+ * since it can lose interrupts (see pmac_set_irq_mask).
+ * -- Cort
+ */
+void __pmac
+__set_lost(unsigned long irq_nr, int nokick)
+{
+	if (!test_and_set_bit(irq_nr, ppc_lost_interrupts)) {
+		atomic_inc(&ppc_n_lost_interrupts);
+		if (!nokick)
+			set_dec(1);
+	}
+}
+
+static void __pmac
+pmac_mask_and_ack_irq(unsigned int irq_nr)
+{
+        unsigned long bit = 1UL << (irq_nr & 0x1f);
+        int i = irq_nr >> 5;
+        unsigned long flags;
+
+        if ((unsigned)irq_nr >= max_irqs)
+                return;
+
+        clear_bit(irq_nr, ppc_cached_irq_mask);
+        if (test_and_clear_bit(irq_nr, ppc_lost_interrupts))
+                atomic_dec(&ppc_n_lost_interrupts);
+	spin_lock_irqsave(&pmac_pic_lock, flags);
+        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+        out_le32(&pmac_irq_hw[i]->ack, bit);
+        do {
+                /* make sure ack gets to controller before we enable
+                   interrupts */
+                mb();
+        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+                != (ppc_cached_irq_mask[i] & bit));
+	spin_unlock_irqrestore(&pmac_pic_lock, flags);
+}
+
+static void __pmac pmac_set_irq_mask(unsigned int irq_nr, int nokicklost)
+{
+        unsigned long bit = 1UL << (irq_nr & 0x1f);
+        int i = irq_nr >> 5;
+        unsigned long flags;
+
+        if ((unsigned)irq_nr >= max_irqs)
+                return;
+
+	spin_lock_irqsave(&pmac_pic_lock, flags);
+        /* enable unmasked interrupts */
+        out_le32(&pmac_irq_hw[i]->enable, ppc_cached_irq_mask[i]);
+
+        do {
+                /* make sure mask gets to controller before we
+                   return to user */
+                mb();
+        } while((in_le32(&pmac_irq_hw[i]->enable) & bit)
+                != (ppc_cached_irq_mask[i] & bit));
+
+        /*
+         * Unfortunately, setting the bit in the enable register
+         * when the device interrupt is already on *doesn't* set
+         * the bit in the flag register or request another interrupt.
+         */
+        if (bit & ppc_cached_irq_mask[i] & in_le32(&pmac_irq_hw[i]->level))
+		__set_lost((ulong)irq_nr, nokicklost);
+	spin_unlock_irqrestore(&pmac_pic_lock, flags);
+}
+
+static void __pmac pmac_mask_irq(unsigned int irq_nr)
+{
+        clear_bit(irq_nr, ppc_cached_irq_mask);
+        pmac_set_irq_mask(irq_nr, 0);
+        mb();
+}
+
+static void __pmac pmac_unmask_irq(unsigned int irq_nr)
+{
+        set_bit(irq_nr, ppc_cached_irq_mask);
+        pmac_set_irq_mask(irq_nr, 0);
+}
+
+static void __pmac pmac_end_irq(unsigned int irq_nr)
+{
+	if (!(irq_desc[irq_nr].status & (IRQ_DISABLED|IRQ_INPROGRESS))) {
+        	set_bit(irq_nr, ppc_cached_irq_mask);
+	        pmac_set_irq_mask(irq_nr, 1);
+	}
+}
+
+
+struct hw_interrupt_type pmac_pic = {
+        " PMAC-PIC ",
+        NULL,
+        NULL,
+        pmac_unmask_irq,
+        pmac_mask_irq,
+        pmac_mask_and_ack_irq,
+        pmac_end_irq,
+        NULL
+};
+
+struct hw_interrupt_type gatwick_pic = {
+	" GATWICK  ",
+	NULL,
+	NULL,
+	pmac_unmask_irq,
+	pmac_mask_irq,
+	pmac_mask_and_ack_irq,
+	pmac_end_irq,
+	NULL
+};
+
+static void gatwick_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+	int irq, bits;
+	
+	for (irq = max_irqs; (irq -= 32) >= max_real_irqs; ) {
+		int i = irq >> 5;
+		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
+		/* We must read level interrupts from the level register */
+		bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+		bits &= ppc_cached_irq_mask[i];
+		if (bits == 0)
+			continue;
+		irq += __ilog2(bits);
+		break;
+	}
+	/* The previous version of this code allowed for this case, we
+	 * don't.  Put this here to check for it.
+	 * -- Cort
+	 */
+	if ( irq_desc[irq].handler != &gatwick_pic )
+		printk("gatwick irq not from gatwick pic\n");
+	else
+		ppc_irq_dispatch_handler( regs, irq );
+}
+
+int
+pmac_get_irq(struct pt_regs *regs)
+{
+	int irq;
+	unsigned long bits = 0;
+
+#ifdef CONFIG_SMP
+	void psurge_smp_message_recv(struct pt_regs *);
+	
+       	/* IPI's are a hack on the powersurge -- Cort */
+       	if ( smp_processor_id() != 0 ) {
+		psurge_smp_message_recv(regs);
+		return -2;	/* ignore, already handled */
+        }
+#endif /* CONFIG_SMP */
+	for (irq = max_real_irqs; (irq -= 32) >= 0; ) {
+		int i = irq >> 5;
+		bits = in_le32(&pmac_irq_hw[i]->event) | ppc_lost_interrupts[i];
+		/* We must read level interrupts from the level register */
+		bits |= (in_le32(&pmac_irq_hw[i]->level) & level_mask[i]);
+		bits &= ppc_cached_irq_mask[i];
+		if (bits == 0)
+			continue;
+		irq += __ilog2(bits);
+		break;
+	}
+
+	return irq;
+}
+
+/* This routine will fix some missing interrupt values in the device tree
+ * on the gatwick mac-io controller used by some PowerBooks
+ */
+static void __init
+pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+{
+	struct device_node *node;
+	int count;
+	
+	memset(gatwick_int_pool, 0, sizeof(gatwick_int_pool));
+	node = gw->child;
+	count = 0;
+	while(node)
+	{
+		/* Fix SCC */
+		if (strcasecmp(node->name, "escc") == 0)
+			if (node->child) {
+				if (node->child->n_intrs < 3) {
+					node->child->intrs = &gatwick_int_pool[count];
+					count += 3;
+				}
+				node->child->n_intrs = 3;				
+				node->child->intrs[0].line = 15+irq_base;
+				node->child->intrs[1].line =  4+irq_base;
+				node->child->intrs[2].line =  5+irq_base;
+				printk(KERN_INFO "irq: fixed SCC on second controller (%d,%d,%d)\n",
+					node->child->intrs[0].line,
+					node->child->intrs[1].line,
+					node->child->intrs[2].line);
+			}
+		/* Fix media-bay & left SWIM */
+		if (strcasecmp(node->name, "media-bay") == 0) {
+			struct device_node* ya_node;
+
+			if (node->n_intrs == 0)
+				node->intrs = &gatwick_int_pool[count++];
+			node->n_intrs = 1;
+			node->intrs[0].line = 29+irq_base;
+			printk(KERN_INFO "irq: fixed media-bay on second controller (%d)\n",
+					node->intrs[0].line);
+			
+			ya_node = node->child;
+			while(ya_node)
+			{
+				if (strcasecmp(ya_node->name, "floppy") == 0) {
+					if (ya_node->n_intrs < 2) {
+						ya_node->intrs = &gatwick_int_pool[count];
+						count += 2;
+					}
+					ya_node->n_intrs = 2;
+					ya_node->intrs[0].line = 19+irq_base;
+					ya_node->intrs[1].line =  1+irq_base;
+					printk(KERN_INFO "irq: fixed floppy on second controller (%d,%d)\n",
+						ya_node->intrs[0].line, ya_node->intrs[1].line);
+				} 
+				if (strcasecmp(ya_node->name, "ata4") == 0) {
+					if (ya_node->n_intrs < 2) {
+						ya_node->intrs = &gatwick_int_pool[count];
+						count += 2;
+					}
+					ya_node->n_intrs = 2;
+					ya_node->intrs[0].line = 14+irq_base;
+					ya_node->intrs[1].line =  3+irq_base;
+					printk(KERN_INFO "irq: fixed ide on second controller (%d,%d)\n",
+						ya_node->intrs[0].line, ya_node->intrs[1].line);
+				} 
+				ya_node = ya_node->sibling;
+			}
+		}
+		node = node->sibling;
+	}
+	if (count > 10) {
+		printk("WARNING !! Gatwick interrupt pool overflow\n");
+		printk("  GATWICK_IRQ_POOL_SIZE = %d\n", GATWICK_IRQ_POOL_SIZE);
+		printk("              requested = %d\n", count);
+	}
+}
+
+/*
+ * The PowerBook 3400/2400/3500 can have a combo ethernet/modem
+ * card which includes an ohare chip that acts as a second interrupt
+ * controller.  If we find this second ohare, set it up and fix the
+ * interrupt value in the device tree for the ethernet chip.
+ */
+static int __init enable_second_ohare(void)
+{
+	unsigned char bus, devfn;
+	unsigned short cmd;
+        unsigned long addr;
+	struct device_node *irqctrler = find_devices("pci106b,7");
+	struct device_node *ether;
+
+	if (irqctrler == NULL || irqctrler->n_addrs <= 0)
+		return -1;
+	addr = (unsigned long) ioremap(irqctrler->addrs[0].address, 0x40);
+	pmac_irq_hw[1] = (volatile struct pmac_irq_hw *)(addr + 0x20);
+	max_irqs = 64;
+	if (pci_device_from_OF_node(irqctrler, &bus, &devfn) == 0) {
+		struct pci_controller* hose = pci_find_hose_for_OF_device(irqctrler);
+		if (!hose)
+		    printk(KERN_ERR "Can't find PCI hose for OHare2 !\n");
+		else {
+		    early_read_config_word(hose, bus, devfn, PCI_COMMAND, &cmd);
+		    cmd |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
+	  	    cmd &= ~PCI_COMMAND_IO;
+		    early_write_config_word(hose, bus, devfn, PCI_COMMAND, cmd);
+		}
+	}
+
+	/* Fix interrupt for the modem/ethernet combo controller. The number
+	   in the device tree (27) is bogus (correct for the ethernet-only
+	   board but not the combo ethernet/modem board).
+	   The real interrupt is 28 on the second controller -> 28+32 = 60.
+	*/
+	ether = find_devices("pci1011,14");
+	if (ether && ether->n_intrs > 0) {
+		ether->intrs[0].line = 60;
+		printk(KERN_INFO "irq: Fixed ethernet IRQ to %d\n",
+		       ether->intrs[0].line);
+	}
+
+	/* Return the interrupt number of the cascade */
+	return irqctrler->intrs[0].line;
+}
+
+void __init
+pmac_pic_init(void)
+{
+        int i;
+        struct device_node *irqctrler;
+        unsigned long addr;
+	int irq_cascade = -1;
+	
+	/* We first try to detect Apple's new Core99 chipset, since mac-io
+	 * is quite different on those machines and contains an IBM MPIC2.
+	 */
+	irqctrler = find_type_devices("open-pic");
+	if (irqctrler != NULL)
+	{
+		printk("PowerMac using OpenPIC irq controller\n");
+		if (irqctrler->n_addrs > 0)
+		{
+			int nmi_irq = -1;
+			unsigned char senses[NR_IRQS];
+#ifdef CONFIG_XMON
+			struct device_node* pswitch;
+
+			pswitch = find_devices("programmer-switch");
+			if (pswitch && pswitch->n_intrs)
+				nmi_irq = pswitch->intrs[0].line;
+#endif /* CONFIG_XMON */
+			prom_get_irq_senses(senses, 0, NR_IRQS);
+			OpenPIC_InitSenses = senses;
+			OpenPIC_NumInitSenses = NR_IRQS;
+			ppc_md.get_irq = openpic_get_irq;
+			OpenPIC_Addr = ioremap(irqctrler->addrs[0].address,
+					       irqctrler->addrs[0].size);
+			openpic_init(1, 0, 0, nmi_irq);
+#ifdef CONFIG_XMON
+			if (nmi_irq >= 0)
+				request_irq(nmi_irq, xmon_irq, 0,
+					    "NMI - XMON", 0);
+#endif	/* CONFIG_XMON */
+			return;
+		}
+		irqctrler = NULL;
+	}
+
+	/* Get the level/edge settings, assume if it's not
+	 * a Grand Central nor an OHare, then it's an Heathrow
+	 * (or Paddington).
+	 */
+	if (find_devices("gc"))
+		level_mask[0] = GC_LEVEL_MASK;
+	else if (find_devices("ohare")) {
+		level_mask[0] = OHARE_LEVEL_MASK;
+		/* We might have a second cascaded ohare */
+		level_mask[1] = OHARE_LEVEL_MASK;
+	} else {
+		level_mask[0] = HEATHROW_LEVEL_MASK;
+		level_mask[1] = 0;
+		/* We might have a second cascaded heathrow */
+		level_mask[2] = HEATHROW_LEVEL_MASK;
+		level_mask[3] = 0;
+	}
+
+	/*
+	 * G3 powermacs and 1999 G3 PowerBooks have 64 interrupts,
+	 * 1998 G3 Series PowerBooks have 128, 
+	 * other powermacs have 32.
+	 * The combo ethernet/modem card for the Powerstar powerbooks
+	 * (2400/3400/3500, ohare based) has a second ohare chip
+	 * effectively making a total of 64.
+	 */
+	max_irqs = max_real_irqs = 32;
+	irqctrler = find_devices("mac-io");
+	if (irqctrler)
+	{
+		max_real_irqs = 64;
+		if (irqctrler->next)
+			max_irqs = 128;
+		else
+			max_irqs = 64;
+	}
+	for ( i = 0; i < max_real_irqs ; i++ )
+		irq_desc[i].handler = &pmac_pic;
+
+	/* get addresses of first controller */
+	if (irqctrler) {
+		if  (irqctrler->n_addrs > 0) {
+			addr = (unsigned long) 
+				ioremap(irqctrler->addrs[0].address, 0x40);
+			for (i = 0; i < 2; ++i)
+				pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+					(addr + (2 - i) * 0x10);
+		}
+		
+		/* get addresses of second controller */
+		irqctrler = irqctrler->next;
+		if (irqctrler && irqctrler->n_addrs > 0) {
+			addr = (unsigned long) 
+				ioremap(irqctrler->addrs[0].address, 0x40);
+			for (i = 2; i < 4; ++i)
+				pmac_irq_hw[i] = (volatile struct pmac_irq_hw*)
+					(addr + (4 - i) * 0x10);
+			irq_cascade = irqctrler->intrs[0].line;
+			if (device_is_compatible(irqctrler, "gatwick"))
+				pmac_fix_gatwick_interrupts(irqctrler, max_real_irqs);
+		}
+	} else {
+		/* older powermacs have a GC (grand central) or ohare at
+		   f3000000, with interrupt control registers at f3000020. */
+		addr = (unsigned long) ioremap(0xf3000000, 0x40);
+		pmac_irq_hw[0] = (volatile struct pmac_irq_hw *) (addr + 0x20);
+	}
+
+	/* PowerBooks 3400 and 3500 can have a second controller in a second
+	   ohare chip, on the combo ethernet/modem card */
+	if (machine_is_compatible("AAPL,3400/2400")
+	     || machine_is_compatible("AAPL,3500"))
+		irq_cascade = enable_second_ohare();
+
+	/* disable all interrupts in all controllers */
+	for (i = 0; i * 32 < max_irqs; ++i)
+		out_le32(&pmac_irq_hw[i]->enable, 0);
+	/* mark level interrupts */
+	for (i = 0; i < max_irqs; i++)
+		if (level_mask[i >> 5] & (1UL << (i & 0x1f)))
+			irq_desc[i].status = IRQ_LEVEL;
+	
+	/* get interrupt line of secondary interrupt controller */
+	if (irq_cascade >= 0) {
+		printk(KERN_INFO "irq: secondary controller on irq %d\n",
+			(int)irq_cascade);
+		for ( i = max_real_irqs ; i < max_irqs ; i++ )
+			irq_desc[i].handler = &gatwick_pic;
+		request_irq( irq_cascade, gatwick_action, SA_INTERRUPT,
+			     "cascade", 0 );
+	}
+	printk("System has %d possible interrupts\n", max_irqs);
+	if (max_irqs != max_real_irqs)
+		printk(KERN_DEBUG "%d interrupts on main controller\n",
+			max_real_irqs);
+
+#ifdef CONFIG_XMON
+	request_irq(20, xmon_irq, 0, "NMI - XMON", 0);
+#endif	/* CONFIG_XMON */
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * These procedures are used in implementing sleep on the powerbooks.
+ * sleep_save_intrs() saves the states of all interrupt enables
+ * and disables all interrupts except for the nominated one.
+ * sleep_restore_intrs() restores the states of all interrupt enables.
+ */
+unsigned int sleep_save_mask[2];
+
+void __pmac
+pmac_sleep_save_intrs(int viaint)
+{
+	sleep_save_mask[0] = ppc_cached_irq_mask[0];
+	sleep_save_mask[1] = ppc_cached_irq_mask[1];
+	ppc_cached_irq_mask[0] = 0;
+	ppc_cached_irq_mask[1] = 0;
+	if (viaint > 0)
+		set_bit(viaint, ppc_cached_irq_mask);
+	out_le32(&pmac_irq_hw[0]->enable, ppc_cached_irq_mask[0]);
+	if (max_real_irqs > 32)
+		out_le32(&pmac_irq_hw[1]->enable, ppc_cached_irq_mask[1]);
+	(void)in_le32(&pmac_irq_hw[0]->event);
+	/* make sure mask gets to controller before we return to caller */
+	mb();
+        (void)in_le32(&pmac_irq_hw[0]->enable);
+}
+
+void __pmac
+pmac_sleep_restore_intrs(void)
+{
+	int i;
+
+	out_le32(&pmac_irq_hw[0]->enable, 0);
+	if (max_real_irqs > 32)
+		out_le32(&pmac_irq_hw[1]->enable, 0);
+	mb();
+	for (i = 0; i < max_real_irqs; ++i)
+		if (test_bit(i, sleep_save_mask))
+			pmac_unmask_irq(i);
+}
+#endif /* CONFIG_PMAC_PBOOK */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_pic.h linux/arch/ppc/platforms/pmac_pic.h
--- linux.orig/arch/ppc/platforms/pmac_pic.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_pic.h	2002-08-12 22:13:59.000000000 +0000
@@ -0,0 +1,14 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+#ifndef __PPC_PLATFORMS_PMAC_PIC_H
+#define __PPC_PLATFORMS_PMAC_PIC_H
+
+#include <linux/irq.h>
+
+extern struct hw_interrupt_type pmac_pic;
+
+void pmac_pic_init(void);
+int pmac_get_irq(struct pt_regs *regs);
+
+#endif /* __PPC_PLATFORMS_PMAC_PIC_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_setup.c linux/arch/ppc/platforms/pmac_setup.c
--- linux.orig/arch/ppc/platforms/pmac_setup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_setup.c	2002-08-12 22:14:04.000000000 +0000
@@ -0,0 +1,955 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platforms/setup.c
+ *
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Adapted for Power Macintosh by Paul Mackerras
+ *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
+ *
+ *  Derived from "arch/alpha/kernel/setup.c"
+ *    Copyright (C) 1995 Linus Torvalds
+ *
+ *  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.
+ *
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/init.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/slab.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/major.h>
+#include <linux/blk.h>
+#include <linux/vt_kern.h>
+#include <linux/console.h>
+#include <linux/ide.h>
+#include <linux/pci.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <linux/blkdev.h>
+#include <linux/genhd.h>
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/ohare.h>
+#include <asm/mediabay.h>
+#include <asm/machdep.h>
+#include <asm/keyboard.h>
+#include <asm/dma.h>
+#include <asm/bootx.h>
+#include <asm/cputable.h>
+#include <asm/btext.h>
+#include <asm/pmac_feature.h>
+#include <asm/time.h>
+
+#include "pmac_pic.h"
+#include "mem_pieces.h"
+#include "scsi.h" /* sd_find_target */
+#include "sd.h"
+#include "mac.h"
+
+extern long pmac_time_init(void);
+extern unsigned long pmac_get_rtc_time(void);
+extern int pmac_set_rtc_time(unsigned long nowtime);
+extern void pmac_read_rtc_time(void);
+extern void pmac_calibrate_decr(void);
+extern void pmac_pcibios_fixup(void);
+extern void pmac_find_bridges(void);
+extern int pmac_ide_check_base(ide_ioreg_t base);
+extern ide_ioreg_t pmac_ide_get_base(int index);
+extern void pmac_ide_init_hwif_ports(hw_regs_t *hw,
+	ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq);
+
+extern int mackbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int mackbd_getkeycode(unsigned int scancode);
+extern int mackbd_translate(unsigned char keycode, unsigned char *keycodep,
+		     char raw_mode);
+extern char mackbd_unexpected_up(unsigned char keycode);
+extern void mackbd_leds(unsigned char leds);
+extern void __init mackbd_init_hw(void);
+extern int mac_hid_kbd_translate(unsigned char scancode, unsigned char *keycode,
+				 char raw_mode);
+extern char mac_hid_kbd_unexpected_up(unsigned char keycode);
+extern void mac_hid_init_hw(void);
+extern unsigned char mac_hid_kbd_sysrq_xlate[];
+extern unsigned char pckbd_sysrq_xlate[];
+extern unsigned char mackbd_sysrq_xlate[];
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern int keyboard_sends_linux_keycodes;
+extern void pmac_nvram_update(void);
+
+extern int pmac_pci_enable_device_hook(struct pci_dev *dev, int initial);
+extern void pmac_pcibios_after_init(void);
+
+struct device_node *memory_node;
+
+unsigned char drive_info;
+
+int ppc_override_l2cr = 0;
+int ppc_override_l2cr_value;
+int has_l2cache = 0;
+
+static int current_root_goodness = -1;
+
+extern char saved_command_line[];
+
+extern int pmac_newworld;
+
+#define DEFAULT_ROOT_DEVICE 0x0801	/* sda1 - slightly silly choice */
+
+extern void zs_kgdb_hook(int tty_num);
+static void ohare_init(void);
+#ifdef CONFIG_BOOTX_TEXT
+void pmac_progress(char *s, unsigned short hex);
+#endif
+
+sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN;
+
+#ifdef CONFIG_SMP
+extern struct smp_ops_t psurge_smp_ops;
+extern struct smp_ops_t core99_smp_ops;
+#endif /* CONFIG_SMP */
+
+/*
+ * Assume here that all clock rates are the same in a
+ * smp system.  -- Cort
+ */
+int __openfirmware
+of_show_percpuinfo(struct seq_file *m, int i)
+{
+	struct device_node *cpu_node;
+	int *fp, s;
+			
+	cpu_node = find_type_devices("cpu");
+	if (!cpu_node)
+		return 0;
+	for (s = 0; s < i && cpu_node->next; s++)
+		cpu_node = cpu_node->next;
+	fp = (int *) get_property(cpu_node, "clock-frequency", NULL);
+	if (fp)
+		seq_printf(m, "clock\t\t: %dMHz\n", *fp / 1000000);
+	return 0;
+}
+
+int __pmac
+pmac_show_cpuinfo(struct seq_file *m)
+{
+	struct device_node *np;
+	char *pp;
+	int plen;
+	int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+		NULL, PMAC_MB_INFO_MODEL, 0);
+	unsigned int mbflags = (unsigned int)pmac_call_feature(PMAC_FTR_GET_MB_INFO,
+		NULL, PMAC_MB_INFO_FLAGS, 0);
+	char* mbname;
+
+	if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, (int)&mbname) != 0)
+		mbname = "Unknown";
+		
+	/* find motherboard type */
+	seq_printf(m, "machine\t\t: ");
+	np = find_devices("device-tree");
+	if (np != NULL) {
+		pp = (char *) get_property(np, "model", NULL);
+		if (pp != NULL)
+			seq_printf(m, "%s\n", pp);
+		else
+			seq_printf(m, "PowerMac\n");
+		pp = (char *) get_property(np, "compatible", &plen);
+		if (pp != NULL) {
+			seq_printf(m, "motherboard\t:");
+			while (plen > 0) {
+				int l = strlen(pp) + 1;
+				seq_printf(m, " %s", pp);
+				plen -= l;
+				pp += l;
+			}
+			seq_printf(m, "\n");
+		}
+	} else
+		seq_printf(m, "PowerMac\n");
+
+	/* print parsed model */
+	seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname);
+	seq_printf(m, "pmac flags\t: %08x\n", mbflags);
+	
+	/* find l2 cache info */
+	np = find_devices("l2-cache");
+	if (np == 0)
+		np = find_type_devices("cache");
+	if (np != 0) {
+		unsigned int *ic = (unsigned int *)
+			get_property(np, "i-cache-size", NULL);
+		unsigned int *dc = (unsigned int *)
+			get_property(np, "d-cache-size", NULL);
+		seq_printf(m, "L2 cache\t:");
+		has_l2cache = 1;
+		if (get_property(np, "cache-unified", NULL) != 0 && dc) {
+			seq_printf(m, " %dK unified", *dc / 1024);
+		} else {
+			if (ic)
+				seq_printf(m, " %dK instruction", *ic / 1024);
+			if (dc)
+				seq_printf(m, "%s %dK data",
+					   (ic? " +": ""), *dc / 1024);
+		}
+		pp = get_property(np, "ram-type", NULL);
+		if (pp)
+			seq_printf(m, " %s", pp);
+		seq_printf(m, "\n");
+	}
+
+	/* find ram info */
+	np = find_devices("memory");
+	if (np != 0) {
+		int n;
+		struct reg_property *reg = (struct reg_property *)
+			get_property(np, "reg", &n);
+		
+		if (reg != 0) {
+			unsigned long total = 0;
+
+			for (n /= sizeof(struct reg_property); n > 0; --n)
+				total += (reg++)->size;
+			seq_printf(m, "memory\t\t: %luMB\n", total >> 20);
+		}
+	}
+
+	/* Checks "l2cr-value" property in the registry */
+	np = find_devices("cpus");		
+	if (np == 0)
+		np = find_type_devices("cpu");		
+	if (np != 0) {
+		unsigned int *l2cr = (unsigned int *)
+			get_property(np, "l2cr-value", NULL);
+		if (l2cr != 0) {
+			seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr);
+		}
+	}
+	
+	/* Indicate newworld/oldworld */
+	seq_printf(m, "pmac-generation\t: %s\n",
+		   pmac_newworld ? "NewWorld" : "OldWorld");
+	
+
+	return 0;
+}
+
+#ifdef CONFIG_VT
+/*
+ * Dummy mksound function that does nothing.
+ * The real one is in the dmasound driver.
+ */
+static void __pmac
+pmac_mksound(unsigned int hz, unsigned int ticks)
+{
+}
+#endif /* CONFIG_VT */
+
+static volatile u32 *sysctrl_regs;
+
+void __init
+pmac_setup_arch(void)
+{
+	struct device_node *cpu;
+	int *fp;
+	unsigned long pvr;
+	
+	pvr = PVR_VER(mfspr(PVR));
+
+	/* Set loops_per_jiffy to a half-way reasonable value,
+	   for use until calibrate_delay gets called. */
+	cpu = find_type_devices("cpu");
+	if (cpu != 0) {
+		fp = (int *) get_property(cpu, "clock-frequency", NULL);
+		if (fp != 0) {
+			if (pvr == 4 || pvr >= 8)
+				/* 604, G3, G4 etc. */
+				loops_per_jiffy = *fp / HZ;
+			else
+				/* 601, 603, etc. */
+				loops_per_jiffy = *fp / (2*HZ);
+		} else
+			loops_per_jiffy = 50000000 / HZ;
+	}
+
+	/* this area has the CPU identification register
+	   and some registers used by smp boards */
+	sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000);
+	ohare_init();
+
+	/* Lookup PCI hosts */
+	pmac_find_bridges();
+	
+	/* Checks "l2cr-value" property in the registry */
+	if (cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR) {
+		struct device_node *np = find_devices("cpus");		
+		if (np == 0)
+			np = find_type_devices("cpu");		
+		if (np != 0) {
+			unsigned int *l2cr = (unsigned int *)
+				get_property(np, "l2cr-value", NULL);
+			if (l2cr != 0) {
+				ppc_override_l2cr = 1;
+				ppc_override_l2cr_value = *l2cr;
+				_set_L2CR(0);
+				_set_L2CR(ppc_override_l2cr_value);
+			}
+		}
+	}
+
+	if (ppc_override_l2cr)
+		printk(KERN_INFO "L2CR overriden (0x%x), backside cache is %s\n",
+			ppc_override_l2cr_value, (ppc_override_l2cr_value & 0x80000000)
+				? "enabled" : "disabled");
+	
+#ifdef CONFIG_KGDB
+	zs_kgdb_hook(0);
+#endif
+
+#ifdef CONFIG_ADB_CUDA
+	find_via_cuda();
+#else
+	if (find_devices("via-cuda")) {
+		printk("WARNING ! Your machine is Cuda based but your kernel\n");
+		printk("          wasn't compiled with CONFIG_ADB_CUDA option !\n");
+	}
+#endif	
+#ifdef CONFIG_ADB_PMU
+	find_via_pmu();
+#else
+	if (find_devices("via-pmu")) {
+		printk("WARNING ! Your machine is PMU based but your kernel\n");
+		printk("          wasn't compiled with CONFIG_ADB_PMU option !\n");
+	}
+#endif	
+#ifdef CONFIG_NVRAM
+	pmac_nvram_init();
+#endif
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+#ifdef CONFIG_VT
+	kd_mksound = pmac_mksound;
+#endif
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (initrd_start)
+		ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	else
+#endif
+		ROOT_DEV = to_kdev_t(DEFAULT_ROOT_DEVICE);
+
+#ifdef CONFIG_SMP
+	/* Check for Core99 */
+	if (find_devices("uni-n"))
+		ppc_md.smp_ops = &core99_smp_ops;
+	else
+		ppc_md.smp_ops = &psurge_smp_ops;
+#endif /* CONFIG_SMP */
+}
+
+static void __init ohare_init(void)
+{
+	/*
+	 * Turn on the L2 cache.
+	 * We assume that we have a PSX memory controller iff
+	 * we have an ohare I/O controller.
+	 */
+	if (find_devices("ohare") != NULL) {
+		if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) {
+			if (sysctrl_regs[4] & 0x10)
+				sysctrl_regs[4] |= 0x04000020;
+			else
+				sysctrl_regs[4] |= 0x04000000;
+			if(has_l2cache)
+				printk(KERN_INFO "Level 2 cache enabled\n");
+		}
+	}
+}
+
+extern char *bootpath;
+extern char *bootdevice;
+void *boot_host;
+int boot_target;
+int boot_part;
+extern kdev_t boot_dev;
+
+void __init
+pmac_init2(void)
+{
+#ifdef CONFIG_ADB_PMU
+	via_pmu_start();
+#endif
+#ifdef CONFIG_ADB_CUDA
+	via_cuda_start();
+#endif
+#ifdef CONFIG_PMAC_PBOOK
+	media_bay_init();
+#endif
+	pmac_feature_late_init();
+}
+
+/* Borrowed from fs/partition/check.c */
+static unsigned char* __init
+read_one_block(struct block_device *bdev, unsigned long n, struct page **v)
+{
+	struct address_space *mapping = bdev->bd_inode->i_mapping;
+	int sect = PAGE_CACHE_SIZE / 512;
+	struct page *page;
+
+	page = read_cache_page(mapping, n/sect,
+			(filler_t *)mapping->a_ops->readpage, NULL);
+	if (!IS_ERR(page)) {
+		wait_on_page(page);
+		if (!Page_Uptodate(page))
+			goto fail;
+		if (PageError(page))
+			goto fail;
+		*v = page;
+		return (unsigned char *)page_address(page) + 512 * (n % sect);
+fail:
+		page_cache_release(page);
+	}
+	*v = NULL;
+	return NULL;
+}
+
+#ifdef CONFIG_SCSI
+void __init
+note_scsi_host(struct device_node *node, void *host)
+{
+	int l;
+	char *p;
+
+	l = strlen(node->full_name);
+	if (bootpath != NULL && bootdevice != NULL
+	    && strncmp(node->full_name, bootdevice, l) == 0
+	    && (bootdevice[l] == '/' || bootdevice[l] == 0)) {
+		boot_host = host;
+		/*
+		 * There's a bug in OF 1.0.5.  (Why am I not surprised.)
+		 * If you pass a path like scsi/sd@1:0 to canon, it returns
+		 * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0
+		 * That is, the scsi target number doesn't get preserved.
+		 * So we pick the target number out of bootpath and use that.
+		 */
+		p = strstr(bootpath, "/sd@");
+		if (p != NULL) {
+			p += 4;
+			boot_target = simple_strtoul(p, NULL, 10);
+			p = strchr(p, ':');
+			if (p != NULL)
+				boot_part = simple_strtoul(p + 1, NULL, 10);
+		}
+	}
+}
+#endif /* CONFIG_SCSI */
+
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+kdev_t __init
+find_ide_boot(void)
+{
+	char *p;
+	int n;
+	kdev_t __init pmac_find_ide_boot(char *bootdevice, int n);
+
+	if (bootdevice == NULL)
+		return 0;
+	p = strrchr(bootdevice, '/');
+	if (p == NULL)
+		return 0;
+	n = p - bootdevice;
+
+	return pmac_find_ide_boot(bootdevice, n);
+}
+#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */
+
+void __init
+find_boot_device(void)
+{
+#if defined(CONFIG_SCSI) && defined(CONFIG_BLK_DEV_SD)
+	if (boot_host != NULL) {
+		boot_dev = sd_find_target(boot_host, boot_target);
+		if (boot_dev != 0)
+			return;
+	}
+#endif
+#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC)
+	boot_dev = find_ide_boot();
+#endif
+}
+
+static void __init
+check_bootable_part(kdev_t dev, int blk, struct mac_partition *part)
+{
+	int goodness = 0;
+
+	macpart_fix_string(part->processor, 16);
+	macpart_fix_string(part->name, 32);
+	macpart_fix_string(part->type, 32);					
+    
+	if ((be32_to_cpu(part->status) & MAC_STATUS_BOOTABLE)
+	    && strcasecmp(part->processor, "powerpc") == 0)
+		goodness++;
+
+	if (strcasecmp(part->type, "Apple_UNIX_SVR2") == 0
+	    || (strnicmp(part->type, "Linux", 5) == 0
+	    && strcasecmp(part->type, "Linux_swap") != 0)) {
+		int i, l;
+
+		goodness++;
+		l = strlen(part->name);
+		if (strcmp(part->name, "/") == 0)
+			goodness++;
+		for (i = 0; i <= l - 4; ++i) {
+			if (strnicmp(part->name + i, "root",
+				     4) == 0) {
+				goodness += 2;
+				break;
+			}
+		}
+		if (strnicmp(part->name, "swap", 4) == 0)
+			goodness--;
+	}
+
+	if (goodness > current_root_goodness) {
+		ROOT_DEV = MKDEV(MAJOR(dev), MINOR(dev) + blk);
+		current_root_goodness = goodness;
+	}
+}
+
+static void __init
+check_bootable_disk(kdev_t dev, struct block_device *bdev)
+{
+	struct mac_partition *part;
+	struct mac_driver_desc *md;
+	struct page* pg;
+	unsigned secsize, blocks_in_map, blk;
+	unsigned char* data;
+	
+	/* Check driver descriptor */
+	md = (struct mac_driver_desc *) read_one_block(bdev, 0, &pg);
+	if (!md)
+		return;
+	if (be16_to_cpu(md->signature) != MAC_DRIVER_MAGIC)
+		goto fail;
+	secsize = be16_to_cpu(md->block_size);
+	page_cache_release(pg);
+	
+	/* Check if it looks like a mac partition map */
+	data = read_one_block(bdev, secsize/512, &pg);
+	if (!data)
+		goto fail;
+	part = (struct mac_partition *) (data + secsize%512);
+	if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+		goto fail;
+
+	/* Iterate the partition map */
+	blocks_in_map = be32_to_cpu(part->map_count);
+	for (blk = 1; blk <= blocks_in_map; ++blk) {
+		int pos = blk * secsize;
+		page_cache_release(pg);
+		data = read_one_block(bdev, pos/512, &pg);
+		if (!data)
+			break;
+		part = (struct mac_partition *) (data + pos%512);
+		if (be16_to_cpu(part->signature) != MAC_PARTITION_MAGIC)
+			break;
+		check_bootable_part(dev, blk, part);
+	}
+fail:
+	if (pg)	
+		page_cache_release(pg);
+}
+
+static int __init
+walk_bootable(struct gendisk *hd, void *data)
+{
+	int drive;
+	
+	for (drive=0; drive<hd->nr_real; drive++) {
+		kdev_t dev;
+		struct block_device *bdev;
+		int rc;
+
+		dev = MKDEV(hd->major, drive << hd->minor_shift);
+		if (boot_dev && boot_dev != dev)
+			continue;
+		bdev = bdget(kdev_t_to_nr(dev));
+		if (bdev == NULL)
+			continue;
+		rc = blkdev_get(bdev, FMODE_READ, 0, BDEV_RAW);
+		if (rc == 0) {
+			check_bootable_disk(dev, bdev);
+			blkdev_put(bdev, BDEV_RAW);
+		}
+	}
+
+	return 0;
+}
+
+void __init
+pmac_discover_root(void)
+{
+	char* p;
+
+	/* Check if root devices already got selected by other ways */
+	if (ROOT_DEV != to_kdev_t(DEFAULT_ROOT_DEVICE))
+		return;
+	p = strstr(saved_command_line, "root=");
+	if (p != NULL && (p == saved_command_line || p[-1] == ' '))
+		return;
+
+	/* Find the device used for booting if we can */
+	find_boot_device();
+
+	/* Try to locate a partition */
+	walk_gendisk(walk_bootable, NULL);
+}
+
+void __pmac
+pmac_restart(char *cmd)
+{
+#ifdef CONFIG_ADB_CUDA
+	struct adb_request req;
+#endif /* CONFIG_ADB_CUDA */
+
+#ifdef CONFIG_NVRAM
+	pmac_nvram_update();
+#endif
+	
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		cuda_request(&req, NULL, 2, CUDA_PACKET,
+			     CUDA_RESET_SYSTEM);
+		for (;;)
+			cuda_poll();
+		break;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU		
+	case SYS_CTRLER_PMU:
+		pmu_restart();
+		break;
+#endif /* CONFIG_ADB_PMU */		
+	default: ;
+	}
+}
+
+void __pmac
+pmac_power_off(void)
+{
+#ifdef CONFIG_ADB_CUDA
+	struct adb_request req;
+#endif /* CONFIG_ADB_CUDA */
+
+#ifdef CONFIG_NVRAM
+	pmac_nvram_update();
+#endif
+	
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		cuda_request(&req, NULL, 2, CUDA_PACKET,
+			     CUDA_POWERDOWN);
+		for (;;)
+			cuda_poll();
+		break;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		pmu_shutdown();
+		break;
+#endif /* CONFIG_ADB_PMU */
+	default: ;
+	}
+}
+
+void __pmac
+pmac_halt(void)
+{
+   pmac_power_off();
+}
+
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int __pmac
+pmac_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+	if (pmac_ide_check_base(from) >= 0)
+		return 0;
+#endif
+	return check_region(from, extent);
+}
+
+static void __pmac
+pmac_ide_request_region(ide_ioreg_t from,
+			unsigned int extent,
+			const char *name)
+{
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+	if (pmac_ide_check_base(from) >= 0)
+		return;
+#endif
+	request_region(from, extent, name);
+}
+
+static void __pmac
+pmac_ide_release_region(ide_ioreg_t from,
+			unsigned int extent)
+{
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+	if (pmac_ide_check_base(from) >= 0)
+		return;
+#endif
+	release_region(from, extent);
+}
+
+#ifndef CONFIG_BLK_DEV_IDE_PMAC
+/*
+ * This is only used if we have a PCI IDE controller, not
+ * for the IDE controller in the ohare/paddington/heathrow/keylargo.
+ */
+static void __pmac
+pmac_ide_pci_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;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+}
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+/*
+ * Read in a property describing some pieces of memory.
+ */
+
+static int __init
+get_mem_prop(char *name, struct mem_pieces *mp)
+{
+	struct reg_property *rp;
+	int i, s;
+	unsigned int *ip;
+	int nac = prom_n_addr_cells(memory_node);
+	int nsc = prom_n_size_cells(memory_node);
+
+	ip = (unsigned int *) get_property(memory_node, name, &s);
+	if (ip == NULL) {
+		printk(KERN_ERR "error: couldn't get %s property on /memory\n",
+		       name);
+		return 0;
+	}
+	s /= (nsc + nac) * 4;
+	rp = mp->regions;
+	for (i = 0; i < s; ++i, ip += nac+nsc) {
+		if (nac >= 2 && ip[nac-2] != 0)
+			continue;
+		rp->address = ip[nac-1];
+		if (nsc >= 2 && ip[nac+nsc-2] != 0)
+			rp->size = ~0U;
+		else
+			rp->size = ip[nac+nsc-1];
+		++rp;
+	}
+	mp->n_regions = rp - mp->regions;
+
+	/* Make sure the pieces are sorted. */
+	mem_pieces_sort(mp);
+	mem_pieces_coalesce(mp);
+	return 1;
+}
+
+/*
+ * On systems with Open Firmware, collect information about
+ * physical RAM and which pieces are already in use.
+ * At this point, we have (at least) the first 8MB mapped with a BAT.
+ * Our text, data, bss use something over 1MB, starting at 0.
+ * Open Firmware may be using 1MB at the 4MB point.
+ */
+unsigned long __init
+pmac_find_end_of_memory(void)
+{
+	unsigned long a, total;
+	struct mem_pieces phys_mem;
+
+	/*
+	 * Find out where physical memory is, and check that it
+	 * starts at 0 and is contiguous.  It seems that RAM is
+	 * always physically contiguous on Power Macintoshes.
+	 *
+	 * Supporting discontiguous physical memory isn't hard,
+	 * it just makes the virtual <-> physical mapping functions
+	 * more complicated (or else you end up wasting space
+	 * in mem_map).
+	 */
+	memory_node = find_devices("memory");
+	if (memory_node == NULL || !get_mem_prop("reg", &phys_mem)
+	    || phys_mem.n_regions == 0)
+		panic("No RAM??");
+	a = phys_mem.regions[0].address;
+	if (a != 0)
+		panic("RAM doesn't start at physical address 0");
+	total = phys_mem.regions[0].size;
+
+	if (phys_mem.n_regions > 1) {
+		printk("RAM starting at 0x%x is not contiguous\n",
+		       phys_mem.regions[1].address);
+		printk("Using RAM from 0 to 0x%lx\n", total-1);
+	}
+
+	return total;
+}
+
+void __init
+select_adb_keyboard(void)
+{
+#ifdef CONFIG_VT
+#ifdef CONFIG_INPUT
+	ppc_md.kbd_init_hw       = mac_hid_init_hw;
+	ppc_md.kbd_translate     = mac_hid_kbd_translate;
+	ppc_md.kbd_unexpected_up = mac_hid_kbd_unexpected_up;
+	ppc_md.kbd_setkeycode    = 0;
+	ppc_md.kbd_getkeycode    = 0;
+	ppc_md.kbd_leds		 = 0;
+#ifdef CONFIG_MAGIC_SYSRQ
+#ifdef CONFIG_MAC_ADBKEYCODES
+	if (!keyboard_sends_linux_keycodes) {
+		ppc_md.ppc_kbd_sysrq_xlate = mac_hid_kbd_sysrq_xlate;
+		SYSRQ_KEY = 0x69;
+	} else
+#endif /* CONFIG_MAC_ADBKEYCODES */
+	{
+		ppc_md.ppc_kbd_sysrq_xlate = pckbd_sysrq_xlate;
+		SYSRQ_KEY = 0x54;
+	}
+#endif /* CONFIG_MAGIC_SYSRQ */
+#elif defined(CONFIG_ADB_KEYBOARD)
+	ppc_md.kbd_setkeycode       = mackbd_setkeycode;
+	ppc_md.kbd_getkeycode       = mackbd_getkeycode;
+	ppc_md.kbd_translate        = mackbd_translate;
+	ppc_md.kbd_unexpected_up    = mackbd_unexpected_up;
+	ppc_md.kbd_leds             = mackbd_leds;
+	ppc_md.kbd_init_hw          = mackbd_init_hw;
+#ifdef CONFIG_MAGIC_SYSRQ
+	ppc_md.ppc_kbd_sysrq_xlate  = mackbd_sysrq_xlate;
+	SYSRQ_KEY = 0x69;
+#endif /* CONFIG_MAGIC_SYSRQ */
+#endif /* CONFIG_INPUT_ADBHID/CONFIG_ADB_KEYBOARD */
+#endif /* CONFIG_VT */
+}
+
+void __init
+pmac_init(unsigned long r3, unsigned long r4, unsigned long r5,
+	  unsigned long r6, unsigned long r7)
+{
+	/* isa_io_base gets set in pmac_find_bridges */
+	isa_mem_base = PMAC_ISA_MEM_BASE;
+	pci_dram_offset = PMAC_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = ~0L;
+	DMA_MODE_READ = 1;
+	DMA_MODE_WRITE = 2;
+
+	ppc_md.setup_arch     = pmac_setup_arch;
+	ppc_md.show_cpuinfo   = pmac_show_cpuinfo;
+	ppc_md.show_percpuinfo = of_show_percpuinfo;
+	ppc_md.irq_cannonicalize = NULL;
+	ppc_md.init_IRQ       = pmac_pic_init;
+	ppc_md.get_irq        = pmac_get_irq; /* Changed later on ... */
+	ppc_md.init           = pmac_init2;
+	
+	ppc_md.pcibios_fixup  = pmac_pcibios_fixup;
+	ppc_md.pcibios_enable_device_hook = pmac_pci_enable_device_hook;
+	ppc_md.pcibios_after_init = pmac_pcibios_after_init;
+
+	ppc_md.discover_root  = pmac_discover_root;
+
+	ppc_md.restart        = pmac_restart;
+	ppc_md.power_off      = pmac_power_off;
+	ppc_md.halt           = pmac_halt;
+
+	ppc_md.time_init      = pmac_time_init;
+	ppc_md.set_rtc_time   = pmac_set_rtc_time;
+	ppc_md.get_rtc_time   = pmac_get_rtc_time;
+	ppc_md.calibrate_decr = pmac_calibrate_decr;
+
+	ppc_md.find_end_of_memory = pmac_find_end_of_memory;
+
+	ppc_md.feature_call   = pmac_do_feature_call;
+
+	select_adb_keyboard();
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+        ppc_ide_md.ide_check_region	= pmac_ide_check_region;
+        ppc_ide_md.ide_request_region	= pmac_ide_request_region;
+        ppc_ide_md.ide_release_region	= pmac_ide_release_region;
+#ifdef CONFIG_BLK_DEV_IDE_PMAC
+        ppc_ide_md.ide_init_hwif	= pmac_ide_init_hwif_ports;
+        ppc_ide_md.default_io_base	= pmac_ide_get_base;
+#else /* CONFIG_BLK_DEV_IDE_PMAC */
+        ppc_ide_md.ide_init_hwif	= pmac_ide_pci_init_hwif_ports;
+#endif /* CONFIG_BLK_DEV_IDE_PMAC */
+#endif /* defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) */
+
+#ifdef CONFIG_BOOTX_TEXT
+	ppc_md.progress = pmac_progress;
+#endif /* CONFIG_BOOTX_TEXT */
+
+	if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0);
+	
+}
+
+#ifdef CONFIG_BOOTX_TEXT
+void __init
+pmac_progress(char *s, unsigned short hex)
+{
+	if (boot_text_mapped) {
+		btext_drawstring(s);
+		btext_drawchar('\n');
+	}
+}
+#endif /* CONFIG_BOOTX_TEXT */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_smp.c linux/arch/ppc/platforms/pmac_smp.c
--- linux.orig/arch/ppc/platforms/pmac_smp.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_smp.c	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,623 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * SMP support for power macintosh.
+ *
+ * We support both the old "powersurge" SMP architecture
+ * and the current Core99 (G4 PowerMac) machines.
+ *
+ * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net)
+ * and Ben Herrenschmidt <benh@kernel.crashing.org>.
+ *
+ * Support for DayStar quad CPU cards
+ * Copyright (C) XLR8, Inc. 1994-2000
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/delay.h>
+#define __KERNEL_SYSCALLS__
+#include <linux/unistd.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/stringify.h>
+
+#include <asm/ptrace.h>
+#include <asm/atomic.h>
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <asm/sections.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/smp.h>
+#include <asm/residual.h>
+#include <asm/machdep.h>
+#include <asm/pmac_feature.h>
+#include <asm/time.h>
+#include <asm/open_pic.h>
+#include <asm/processor.h>
+
+/*
+ * Powersurge (old powermac SMP) support.
+ */
+
+extern void __secondary_start_psurge(void);
+extern void __secondary_start_psurge2(void);	/* Temporary horrible hack */
+extern void __secondary_start_psurge3(void);	/* Temporary horrible hack */
+
+/* Addresses for powersurge registers */
+#define HAMMERHEAD_BASE		0xf8000000
+#define HHEAD_CONFIG		0x90
+#define HHEAD_SEC_INTR		0xc0
+
+/* register for interrupting the primary processor on the powersurge */
+/* N.B. this is actually the ethernet ROM! */
+#define PSURGE_PRI_INTR		0xf3019000
+
+/* register for storing the start address for the secondary processor */
+/* N.B. this is the PCI config space address register for the 1st bridge */
+#define PSURGE_START		0xf2800000
+
+/* Daystar/XLR8 4-CPU card */
+#define PSURGE_QUAD_REG_ADDR	0xf8800000
+
+#define PSURGE_QUAD_IRQ_SET	0
+#define PSURGE_QUAD_IRQ_CLR	1
+#define PSURGE_QUAD_IRQ_PRIMARY	2
+#define PSURGE_QUAD_CKSTOP_CTL	3
+#define PSURGE_QUAD_PRIMARY_ARB	4
+#define PSURGE_QUAD_BOARD_ID	6
+#define PSURGE_QUAD_WHICH_CPU	7
+#define PSURGE_QUAD_CKSTOP_RDBK	8
+#define PSURGE_QUAD_RESET_CTL	11
+
+#define PSURGE_QUAD_OUT(r, v)	(out_8(quad_base + ((r) << 4) + 4, (v)))
+#define PSURGE_QUAD_IN(r)	(in_8(quad_base + ((r) << 4) + 4) & 0x0f)
+#define PSURGE_QUAD_BIS(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) | (v)))
+#define PSURGE_QUAD_BIC(r, v)	(PSURGE_QUAD_OUT((r), PSURGE_QUAD_IN(r) & ~(v)))
+
+/* virtual addresses for the above */
+static volatile u8 *hhead_base;
+static volatile u8 *quad_base;
+static volatile u32 *psurge_pri_intr;
+static volatile u8 *psurge_sec_intr;
+static volatile u32 *psurge_start;
+
+/* what sort of powersurge board we have */
+static int psurge_type;
+
+/* values for psurge_type */
+#define PSURGE_DUAL		0
+#define PSURGE_QUAD_OKEE	1
+#define PSURGE_QUAD_COTTON	2
+#define PSURGE_QUAD_ICEGRASS	3
+
+volatile static long int core99_l2_cache;
+volatile static long int core99_l3_cache;
+
+static void __init
+core99_init_caches(void)
+{
+	int cpu = smp_processor_id();
+
+	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L2CR))
+		return;
+
+	if (cpu == 0){
+		core99_l2_cache = _get_L2CR();
+		printk("CPU0: L2CR is %lx\n", core99_l2_cache);
+	} else {
+		printk("CPU%d: L2CR was %lx\n", cpu, _get_L2CR());
+		_set_L2CR(0);
+		_set_L2CR(core99_l2_cache);
+		printk("CPU%d: L2CR set to %lx\n", cpu, core99_l2_cache);
+	}
+
+	if (!(cur_cpu_spec[0]->cpu_features & CPU_FTR_L3CR))
+		return;
+
+	if (cpu == 0){
+		core99_l3_cache = _get_L3CR();
+		printk("CPU0: L3CR is %lx\n", core99_l3_cache);
+	} else {
+		printk("CPU%d: L3CR was %lx\n", cpu, _get_L3CR());
+		_set_L3CR(0);
+		_set_L3CR(core99_l3_cache);
+		printk("CPU%d: L3CR set to %lx\n", cpu, core99_l3_cache);
+	}
+}
+
+/* Some CPU registers have to be saved from the first CPU and
+ * applied to others. Note that we override what is setup by
+ * the cputable intentionally.
+ */
+
+#define	reg_hid0	0
+#define	reg_hid1	1
+#define	reg_msscr0	2
+#define	reg_msssr0	3
+#define	reg_ictrl	4
+#define	reg_ldstcr	5
+#define	reg_ldstdb	6
+#define	reg_count	7
+
+#define stringify __stringify
+
+static unsigned long cpu_regs[reg_count];
+
+static void __pmac
+cpu_setup_grab(void)
+{
+	unsigned int pvers = mfspr(SPRN_PVR)>>16;
+
+	/* Read cache setting of CPU 0 */
+	core99_init_caches();
+
+	/* 7400/7410/7450 */
+	if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
+		cpu_regs[reg_hid0] = mfspr(SPRN_HID0);
+		cpu_regs[reg_msscr0] = mfspr(SPRN_MSSCR0);
+		cpu_regs[reg_msssr0] = mfspr(SPRN_MSSSR0);
+	}
+	/* 7450 only */
+	if (pvers == 0x8000) {
+		cpu_regs[reg_hid1] = mfspr(SPRN_HID1);
+		cpu_regs[reg_ictrl] = mfspr(SPRN_ICTRL);
+		cpu_regs[reg_ldstcr] = mfspr(SPRN_LDSTCR);
+		cpu_regs[reg_ldstdb] = mfspr(SPRN_LDSTDB);
+	}
+	flush_dcache_range((unsigned long)cpu_regs, (unsigned long)&cpu_regs[reg_count]);
+}
+
+static void __pmac
+cpu_setup_apply(int cpu_nr)
+{
+	unsigned int pvers = mfspr(SPRN_PVR)>>16;
+
+	/* Apply cache setting from CPU 0 */
+	core99_init_caches();
+
+	/* 7400/7410/7450 */
+	if (pvers == 0x8000 || pvers == 0x000c || pvers == 0x800c) {
+		unsigned long tmp;
+		__asm__ __volatile__ (
+			"lwz	%0,4*"stringify(reg_hid0)"(%1)\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_HID0)", %0\n"
+			"isync;sync\n"
+			"lwz	%0, 4*"stringify(reg_msscr0)"(%1)\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_MSSCR0)", %0\n"
+			"isync;sync\n"
+//			"lwz	%0, "stringify(reg_msssr0)"(%1)\n"
+//			"sync\n"
+//			"mtspr	"stringify(SPRN_MSSSR0)", %0\n"
+//			"isync;sync\n"
+		: "=&r" (tmp) : "r" (cpu_regs));			
+	}
+	/* 7410 only */
+	if (pvers == 0x800c) {
+		unsigned long tmp;
+		__asm__ __volatile__ (
+			"li	%0, 0\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_L2CR2)", %0\n"
+			"isync;sync\n"
+		: "=&r" (tmp));		
+	}
+	/* 7450 only */
+	if (pvers == 0x8000) {
+		unsigned long tmp;
+		__asm__ __volatile__ (
+			"lwz	%0, 4*"stringify(reg_hid1)"(%1)\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_HID1)", %0\n"
+			"isync;sync\n"
+			"lwz	%0, 4*"stringify(reg_ictrl)"(%1)\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_ICTRL)", %0\n"
+			"isync;sync\n"
+			"lwz	%0, 4*"stringify(reg_ldstcr)"(%1)\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_LDSTCR)", %0\n"
+			"isync;sync\n"
+			"lwz	%0, 4*"stringify(reg_ldstdb)"(%1)\n"
+			"sync\n"
+			"mtspr	"stringify(SPRN_LDSTDB)", %0\n"
+			"isync;sync\n"
+		: "=&r" (tmp) : "r" (cpu_regs));		
+	}
+}
+
+/*
+ * Set and clear IPIs for powersurge.
+ */
+static inline void psurge_set_ipi(int cpu)
+{
+	if (cpu == 0)
+		in_be32(psurge_pri_intr);
+	else if (psurge_type == PSURGE_DUAL)
+		out_8(psurge_sec_intr, 0);
+	else
+		PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_SET, 1 << cpu);
+}
+
+static inline void psurge_clr_ipi(int cpu)
+{
+	if (cpu > 0) {
+		if (psurge_type == PSURGE_DUAL)
+			out_8(psurge_sec_intr, ~0);
+		else
+			PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, 1 << cpu);
+	}
+}
+
+/*
+ * On powersurge (old SMP powermac architecture) we don't have
+ * separate IPIs for separate messages like openpic does.  Instead
+ * we have a bitmap for each processor, where a 1 bit means that
+ * the corresponding message is pending for that processor.
+ * Ideally each cpu's entry would be in a different cache line.
+ *  -- paulus.
+ */
+static unsigned long psurge_smp_message[NR_CPUS];
+
+void __pmac
+psurge_smp_message_recv(struct pt_regs *regs)
+{
+	int cpu = smp_processor_id();
+	int msg;
+
+	/* clear interrupt */
+	psurge_clr_ipi(cpu);
+
+	if (smp_num_cpus < 2)
+		return;
+
+	/* make sure there is a message there */
+	for (msg = 0; msg < 4; msg++)
+		if (test_and_clear_bit(msg, &psurge_smp_message[cpu]))
+			smp_message_recv(msg, regs);
+}
+
+void __pmac
+psurge_primary_intr(int irq, void *d, struct pt_regs *regs)
+{
+	psurge_smp_message_recv(regs);
+}
+
+static void __pmac
+smp_psurge_message_pass(int target, int msg, unsigned long data, int wait)
+{
+	int i;
+
+	if (smp_num_cpus < 2)
+		return;
+
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (target == MSG_ALL
+		    || (target == MSG_ALL_BUT_SELF && i != smp_processor_id())
+		    || target == i) {
+			set_bit(msg, &psurge_smp_message[i]);
+			psurge_set_ipi(i);
+		}
+	}
+}
+
+/*
+ * Determine a quad card presence. We read the board ID register, we
+ * force the data bus to change to something else, and we read it again.
+ * It it's stable, then the register probably exist (ugh !)
+ */
+static int __init psurge_quad_probe(void)
+{
+	int type;
+	unsigned int i;
+
+	type = PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID);
+	if (type < PSURGE_QUAD_OKEE || type > PSURGE_QUAD_ICEGRASS
+	    || type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+		return PSURGE_DUAL;
+
+	/* looks OK, try a slightly more rigorous test */
+	/* bogus is not necessarily cacheline-aligned,
+	   though I don't suppose that really matters.  -- paulus */
+	for (i = 0; i < 100; i++) {
+		volatile u32 bogus[8];
+		bogus[(0+i)%8] = 0x00000000;
+		bogus[(1+i)%8] = 0x55555555;
+		bogus[(2+i)%8] = 0xFFFFFFFF;
+		bogus[(3+i)%8] = 0xAAAAAAAA;
+		bogus[(4+i)%8] = 0x33333333;
+		bogus[(5+i)%8] = 0xCCCCCCCC;
+		bogus[(6+i)%8] = 0xCCCCCCCC;
+		bogus[(7+i)%8] = 0x33333333;
+		wmb();
+		asm volatile("dcbf 0,%0" : : "r" (bogus) : "memory");
+		mb();
+		if (type != PSURGE_QUAD_IN(PSURGE_QUAD_BOARD_ID))
+			return PSURGE_DUAL;
+	}
+	return type;
+}
+
+static void __init psurge_quad_init(void)
+{
+	int procbits;
+
+	if (ppc_md.progress) ppc_md.progress("psurge_quad_init", 0x351);
+	procbits = ~PSURGE_QUAD_IN(PSURGE_QUAD_WHICH_CPU);
+	if (psurge_type == PSURGE_QUAD_ICEGRASS)
+		PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+	else
+		PSURGE_QUAD_BIC(PSURGE_QUAD_CKSTOP_CTL, procbits);
+	mdelay(33);
+	out_8(psurge_sec_intr, ~0);
+	PSURGE_QUAD_OUT(PSURGE_QUAD_IRQ_CLR, procbits);
+	PSURGE_QUAD_BIS(PSURGE_QUAD_RESET_CTL, procbits);
+	if (psurge_type != PSURGE_QUAD_ICEGRASS)
+		PSURGE_QUAD_BIS(PSURGE_QUAD_CKSTOP_CTL, procbits);
+	PSURGE_QUAD_BIC(PSURGE_QUAD_PRIMARY_ARB, procbits);
+	mdelay(33);
+	PSURGE_QUAD_BIC(PSURGE_QUAD_RESET_CTL, procbits);
+	mdelay(33);
+	PSURGE_QUAD_BIS(PSURGE_QUAD_PRIMARY_ARB, procbits);
+	mdelay(33);
+}
+
+static int __init smp_psurge_probe(void)
+{
+	int i, ncpus;
+
+	/* We don't do SMP on the PPC601 -- paulus */
+	if (PVR_VER(mfspr(PVR)) == 1)
+		return 1;
+
+	/*
+	 * The powersurge cpu board can be used in the generation
+	 * of powermacs that have a socket for an upgradeable cpu card,
+	 * including the 7500, 8500, 9500, 9600.
+	 * The device tree doesn't tell you if you have 2 cpus because
+	 * OF doesn't know anything about the 2nd processor.
+	 * Instead we look for magic bits in magic registers,
+	 * in the hammerhead memory controller in the case of the
+	 * dual-cpu powersurge board.  -- paulus.
+	 */
+	if (find_devices("hammerhead") == NULL)
+		return 1;
+
+	hhead_base = ioremap(HAMMERHEAD_BASE, 0x800);
+	quad_base = ioremap(PSURGE_QUAD_REG_ADDR, 1024);
+	psurge_sec_intr = hhead_base + HHEAD_SEC_INTR;
+
+	psurge_type = psurge_quad_probe();
+	if (psurge_type != PSURGE_DUAL) {
+		psurge_quad_init();
+		/* All released cards using this HW design have 4 CPUs */
+		ncpus = 4;
+	} else {
+		iounmap((void *) quad_base);
+		if ((in_8(hhead_base + HHEAD_CONFIG) & 0x02) == 0) {
+			/* not a dual-cpu card */
+			iounmap((void *) hhead_base);
+			return 1;
+		}
+		ncpus = 2;
+	}
+
+	psurge_start = ioremap(PSURGE_START, 4);
+	psurge_pri_intr = ioremap(PSURGE_PRI_INTR, 4);
+
+	/* this is not actually strictly necessary -- paulus. */
+	for (i = 1; i < ncpus; ++i)
+		smp_hw_index[i] = i;
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_probe - done", 0x352);
+
+	return ncpus;
+}
+
+static void __init smp_psurge_kick_cpu(int nr)
+{
+	void (*start)(void) = __secondary_start_psurge;
+	unsigned long a;
+
+	/* may need to flush here if secondary bats aren't setup */
+	for (a = KERNELBASE; a < KERNELBASE + 0x800000; a += 32)
+		asm volatile("dcbf 0,%0" : : "r" (a) : "memory");
+	asm volatile("sync");
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu", 0x353);
+
+	/* setup entry point of secondary processor */
+	switch (nr) {
+	case 2:
+		start = __secondary_start_psurge2;
+		break;
+	case 3:
+		start = __secondary_start_psurge3;
+		break;
+	}
+
+	out_be32(psurge_start, __pa(start));
+	mb();
+
+	psurge_set_ipi(nr);
+	udelay(10);
+	psurge_clr_ipi(nr);
+
+	if (ppc_md.progress) ppc_md.progress("smp_psurge_kick_cpu - done", 0x354);
+}
+
+/*
+ * With the dual-cpu powersurge board, the decrementers and timebases
+ * of both cpus are frozen after the secondary cpu is started up,
+ * until we give the secondary cpu another interrupt.  This routine
+ * uses this to get the timebases synchronized.
+ *  -- paulus.
+ */
+static void __init psurge_dual_sync_tb(int cpu_nr)
+{
+	static volatile int sec_tb_reset = 0;
+	int t;
+
+	set_dec(tb_ticks_per_jiffy);
+	set_tb(0, 0);
+	last_jiffy_stamp(cpu_nr) = 0;
+
+	if (cpu_nr > 0) {
+		mb();
+		sec_tb_reset = 1;
+		return;
+	}
+
+	/* wait for the secondary to have reset its TB before proceeding */
+	for (t = 10000000; t > 0 && !sec_tb_reset; --t)
+		;
+
+	/* now interrupt the secondary, starting both TBs */
+	psurge_set_ipi(1);
+
+	smp_tb_synchronized = 1;
+}
+
+static void __init
+smp_psurge_setup_cpu(int cpu_nr)
+{
+
+	if (cpu_nr == 0) {
+		if (smp_num_cpus < 2)
+			return;
+		/* reset the entry point so if we get another intr we won't
+		 * try to startup again */
+		out_be32(psurge_start, 0x100);
+		if (request_irq(30, psurge_primary_intr, 0, "primary IPI", 0))
+			printk(KERN_ERR "Couldn't get primary IPI interrupt");
+	}
+
+	if (psurge_type == PSURGE_DUAL)
+		psurge_dual_sync_tb(cpu_nr);
+}
+
+static int __init
+smp_core99_probe(void)
+{
+	struct device_node *cpus;
+	int i, ncpus = 1;
+	extern int powersave_nap;
+
+	if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345);
+	cpus = find_type_devices("cpu");
+	if (cpus)
+		while ((cpus = cpus->next) != NULL)
+			++ncpus;
+	printk("smp_core99_probe: found %d cpus\n", ncpus);
+	if (ncpus > 1) {
+		openpic_request_IPIs();
+		for (i = 1; i < ncpus; ++i)
+			smp_hw_index[i] = i;
+		powersave_nap = 0;
+		cpu_setup_grab();
+	}
+
+	return ncpus;
+}
+
+static void __init
+smp_core99_kick_cpu(int nr)
+{
+	unsigned long save_vector, new_vector;
+	unsigned long flags;
+
+	volatile unsigned long *vector
+		 = ((volatile unsigned long *)(KERNELBASE+0x100));
+	if (nr < 1 || nr > 3)
+		return;
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346);
+
+	local_irq_save(flags);
+	local_irq_disable();
+	
+	/* Save reset vector */
+	save_vector = *vector;
+	
+	/* Setup fake reset vector that does	  
+	 *   b __secondary_start_psurge - KERNELBASE
+	 */  
+	switch(nr) {
+		case 1:
+			new_vector = (unsigned long)__secondary_start_psurge;
+			break;
+		case 2:
+			new_vector = (unsigned long)__secondary_start_psurge2;
+			break;
+		case 3:
+			new_vector = (unsigned long)__secondary_start_psurge3;
+			break;
+	}
+	*vector = 0x48000002 + new_vector - KERNELBASE;
+	
+	/* flush data cache and inval instruction cache */
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+	
+	/* Put some life in our friend */
+	pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0);
+	
+	/* FIXME: We wait a bit for the CPU to take the exception, I should
+	 * instead wait for the entry code to set something for me. Well,
+	 * ideally, all that crap will be done in prom.c and the CPU left
+	 * in a RAM-based wait loop like CHRP.
+	 */
+	mdelay(1);
+	
+	/* Restore our exception vector */
+	*vector = save_vector;
+	flush_icache_range((unsigned long) vector, (unsigned long) vector + 4);
+	
+	local_irq_restore(flags);
+	if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347);
+}
+
+static void __init
+smp_core99_setup_cpu(int cpu_nr)
+{
+	/* Setup some registers */
+	if (cpu_nr != 0)
+		cpu_setup_apply(cpu_nr);
+	
+	/* Setup openpic */
+	do_openpic_setup_cpu();
+
+	/* Setup L2/L3 */
+	if (cpu_nr == 0)
+		if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+}
+
+/* PowerSurge-style Macs */
+struct smp_ops_t psurge_smp_ops __pmacdata = {
+	smp_psurge_message_pass,
+	smp_psurge_probe,
+	smp_psurge_kick_cpu,
+	smp_psurge_setup_cpu,
+};
+
+/* Core99 Macs (dual G4s) */
+struct smp_ops_t core99_smp_ops __pmacdata = {
+	smp_openpic_message_pass,
+	smp_core99_probe,
+	smp_core99_kick_cpu,
+	smp_core99_setup_cpu,
+};
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/pmac_time.c linux/arch/ppc/platforms/pmac_time.c
--- linux.orig/arch/ppc/platforms/pmac_time.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/pmac_time.c	2002-08-12 22:14:11.000000000 +0000
@@ -0,0 +1,282 @@
+/*
+ * BK Id: SCCS/s.pmac_time.c 1.19 12/04/01 01:24:51 benh
+ */
+/*
+ * Support for periodic interrupts (100 per second) and for getting
+ * the current time from the RTC on Power Macintoshes.
+ *
+ * We use the decrementer register for our periodic interrupts.
+ *
+ * Paul Mackerras	August 1996.
+ * Copyright (C) 1996 Paul Mackerras.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/adb.h>
+#include <linux/cuda.h>
+#include <linux/pmu.h>
+
+#include <asm/sections.h>
+#include <asm/prom.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/hardirq.h>
+#include <asm/time.h>
+#include <asm/nvram.h>
+
+extern rwlock_t xtime_lock;
+
+/* Apparently the RTC stores seconds since 1 Jan 1904 */
+#define RTC_OFFSET	2082844800
+
+/*
+ * Calibrate the decrementer frequency with the VIA timer 1.
+ */
+#define VIA_TIMER_FREQ_6	4700000	/* time 1 frequency * 6 */
+
+/* VIA registers */
+#define RS		0x200		/* skip between registers */
+#define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
+#define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
+#define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
+#define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
+#define ACR		(11*RS)		/* Auxiliary control register */
+#define IFR		(13*RS)		/* Interrupt flag register */
+
+/* Bits in ACR */
+#define T1MODE		0xc0		/* Timer 1 mode */
+#define T1MODE_CONT	0x40		/*  continuous interrupts */
+
+/* Bits in IFR and IER */
+#define T1_INT		0x40		/* Timer 1 interrupt */
+
+extern struct timezone sys_tz;
+
+long __init
+pmac_time_init(void)
+{
+#ifdef CONFIG_NVRAM
+	s32 delta = 0;
+	int dst;
+	
+	delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16;
+	delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8;
+	delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb);
+	if (delta & 0x00800000UL)
+		delta |= 0xFF000000UL;
+	dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0);
+	printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60,
+		dst ? "on" : "off");
+	return delta;
+#else
+	return 0;
+#endif
+}
+
+unsigned long __pmac
+pmac_get_rtc_time(void)
+{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+	struct adb_request req;
+	unsigned long now;
+#endif
+
+	/* Get the time from the RTC */
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+		if (req.reply_len != 7)
+			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		now = (req.reply[3] << 24) + (req.reply[4] << 16)
+			+ (req.reply[5] << 8) + req.reply[6];
+		return now - RTC_OFFSET;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 4)
+			printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		now = (req.reply[0] << 24) + (req.reply[1] << 16)
+			+ (req.reply[2] << 8) + req.reply[3];
+		return now - RTC_OFFSET;
+#endif /* CONFIG_ADB_PMU */
+	default: ;
+	}
+	return 0;
+}
+
+int __pmac
+pmac_set_rtc_time(unsigned long nowtime)
+{
+#if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU)
+	struct adb_request req;
+#endif
+
+	nowtime += RTC_OFFSET;
+
+	switch (sys_ctrler) {
+#ifdef CONFIG_ADB_CUDA
+	case SYS_CTRLER_CUDA:
+		if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
+				 nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			cuda_poll();
+		if ((req.reply_len != 3) && (req.reply_len != 7))
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return 1;
+#endif /* CONFIG_ADB_CUDA */
+#ifdef CONFIG_ADB_PMU
+	case SYS_CTRLER_PMU:
+		if (pmu_request(&req, NULL, 5, PMU_SET_RTC,
+				nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0)
+			return 0;
+		while (!req.complete)
+			pmu_poll();
+		if (req.reply_len != 0)
+			printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n",
+			       req.reply_len);
+		return 1;
+#endif /* CONFIG_ADB_PMU */
+	default:
+		return 0;
+	}
+}
+
+/*
+ * Calibrate the decrementer register using VIA timer 1.
+ * This is used both on powermacs and CHRP machines.
+ */
+int __init
+via_calibrate_decr(void)
+{
+	struct device_node *vias;
+	volatile unsigned char *via;
+	int count = VIA_TIMER_FREQ_6 / HZ;
+	unsigned int dstart, dend;
+
+	vias = find_devices("via-cuda");
+	if (vias == 0)
+		vias = find_devices("via-pmu");
+	if (vias == 0)
+		vias = find_devices("via");
+	if (vias == 0 || vias->n_addrs == 0)
+		return 0;
+	via = (volatile unsigned char *)
+		ioremap(vias->addrs[0].address, vias->addrs[0].size);
+
+	/* set timer 1 for continuous interrupts */
+	out_8(&via[ACR], (via[ACR] & ~T1MODE) | T1MODE_CONT);
+	/* set the counter to a small value */
+	out_8(&via[T1CH], 2);
+	/* set the latch to `count' */
+	out_8(&via[T1LL], count);
+	out_8(&via[T1LH], count >> 8);
+	/* wait until it hits 0 */
+	while ((in_8(&via[IFR]) & T1_INT) == 0)
+		;
+	dstart = get_dec();
+	/* clear the interrupt & wait until it hits 0 again */
+	in_8(&via[T1CL]);
+	while ((in_8(&via[IFR]) & T1_INT) == 0)
+		;
+	dend = get_dec();
+
+	tb_ticks_per_jiffy = (dstart - dend) / 6;
+	tb_to_us = mulhwu_scale_factor(dstart - dend, 60000);
+
+	printk(KERN_INFO "via_calibrate_decr: ticks per jiffy = %u (%u ticks)\n",
+	       tb_ticks_per_jiffy, dstart - dend);
+
+	return 1;
+}
+
+#ifdef CONFIG_PMAC_PBOOK
+/*
+ * Reset the time after a sleep.
+ */
+static int __pmac
+time_sleep_notify(struct pmu_sleep_notifier *self, int when)
+{
+	static unsigned long time_diff;
+	unsigned long flags;
+
+	switch (when) {
+	case PBOOK_SLEEP_NOW:
+		read_lock_irqsave(&xtime_lock, flags);
+		time_diff = xtime.tv_sec - pmac_get_rtc_time();
+		read_unlock_irqrestore(&xtime_lock, flags);
+		break;
+	case PBOOK_WAKE:
+		write_lock_irqsave(&xtime_lock, flags);
+		xtime.tv_sec = pmac_get_rtc_time() + time_diff;
+		xtime.tv_usec = 0;
+		last_rtc_update = xtime.tv_sec;
+		write_unlock_irqrestore(&xtime_lock, flags);
+		break;
+	}
+	return PBOOK_SLEEP_OK;
+}
+
+static struct pmu_sleep_notifier time_sleep_notifier __pmacdata = {
+	time_sleep_notify, SLEEP_LEVEL_MISC,
+};
+#endif /* CONFIG_PMAC_PBOOK */
+
+/*
+ * Query the OF and get the decr frequency.
+ * This was taken from the pmac time_init() when merging the prep/pmac
+ * time functions.
+ */
+void __init
+pmac_calibrate_decr(void)
+{
+	struct device_node *cpu;
+	unsigned int freq, *fp;
+
+#ifdef CONFIG_PMAC_PBOOK
+	pmu_register_sleep_notifier(&time_sleep_notifier);
+#endif /* CONFIG_PMAC_PBOOK */
+
+	/* We assume MacRISC2 machines have correct device-tree
+	 * calibration. That's better since the VIA itself seems
+	 * to be slightly off. --BenH
+	 */
+	if (!machine_is_compatible("MacRISC2"))
+		if (via_calibrate_decr())
+			return;
+
+	/*
+	 * The cpu node should have a timebase-frequency property
+	 * to tell us the rate at which the decrementer counts.
+	 */
+	cpu = find_type_devices("cpu");
+	if (cpu == 0)
+		panic("can't find cpu node in time_init");
+	fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL);
+	if (fp == 0)
+		panic("can't get cpu timebase frequency");
+	freq = *fp;
+	printk("time_init: decrementer frequency = %u.%.6u MHz\n",
+	       freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/prep_pci.c linux/arch/ppc/platforms/prep_pci.c
--- linux.orig/arch/ppc/platforms/prep_pci.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/prep_pci.c	2002-08-12 22:14:26.000000000 +0000
@@ -0,0 +1,1269 @@
+/*
+ * BK Id: SCCS/s.prep_pci.c 1.33 12/20/01 15:36:12 trini
+ */
+/*
+ * PReP pci functions.
+ * Originally by Gary Thomas
+ * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
+ *
+ * The motherboard routes/maps will disappear shortly. -- Cort
+ */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/prom.h>
+#include <asm/pci-bridge.h>
+#include <asm/residual.h>
+#include <asm/processor.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/open_pic.h>
+
+#define MAX_DEVNR 22
+
+/* Which PCI interrupt line does a given device [slot] use? */
+/* Note: This really should be two dimensional based in slot/pin used */
+static unsigned char *Motherboard_map;
+unsigned char *Motherboard_map_name;
+
+/* How is the 82378 PIRQ mapping setup? */
+static unsigned char *Motherboard_routes;
+
+static void (*Motherboard_non0)(struct pci_dev *);
+
+static void Powerplus_Map_Non0(struct pci_dev *);
+
+/* Used for Motorola to store system config register */
+static unsigned long	*ProcInfo;
+
+/* Tables for known hardware */   
+
+/* Motorola PowerStackII - Utah */
+static char Utah_pci_IRQ_map[23] __prepdata =
+{
+        0,   /* Slot 0  - unused */
+        0,   /* Slot 1  - unused */
+        5,   /* Slot 2  - SCSI - NCR825A  */
+        0,   /* Slot 3  - unused */
+        1,   /* Slot 4  - Ethernet - DEC2114x */
+        0,   /* Slot 5  - unused */
+        3,   /* Slot 6  - PCI Card slot #1 */
+        4,   /* Slot 7  - PCI Card slot #2 */
+        5,   /* Slot 8  - PCI Card slot #3 */
+        5,   /* Slot 9  - PCI Bridge */
+             /* added here in case we ever support PCI bridges */
+             /* Secondary PCI bus cards are at slot-9,6 & slot-9,7 */
+        0,   /* Slot 10 - unused */
+        0,   /* Slot 11 - unused */
+        5,   /* Slot 12 - SCSI - NCR825A */
+        0,   /* Slot 13 - unused */
+        3,   /* Slot 14 - enet */
+        0,   /* Slot 15 - unused */
+        2,   /* Slot 16 - unused */
+        3,   /* Slot 17 - unused */
+        5,   /* Slot 18 - unused */
+        0,   /* Slot 19 - unused */
+        0,   /* Slot 20 - unused */
+        0,   /* Slot 21 - unused */
+        0,   /* Slot 22 - unused */
+};
+
+static char Utah_pci_IRQ_routes[] __prepdata =
+{
+        0,   /* Line 0 - Unused */
+        9,   /* Line 1 */
+	10,  /* Line 2 */
+        11,  /* Line 3 */
+        14,  /* Line 4 */
+        15,  /* Line 5 */
+};
+
+/* Motorola PowerStackII - Omaha */
+/* no integrated SCSI or ethernet */
+static char Omaha_pci_IRQ_map[23] __prepdata =
+{
+        0,   /* Slot 0  - unused */
+        0,   /* Slot 1  - unused */
+        3,   /* Slot 2  - Winbond EIDE */
+        0,   /* Slot 3  - unused */
+        0,   /* Slot 4  - unused */
+        0,   /* Slot 5  - unused */
+        1,   /* Slot 6  - PCI slot 1 */
+        2,   /* Slot 7  - PCI slot 2  */
+        3,   /* Slot 8  - PCI slot 3 */
+        4,   /* Slot 9  - PCI slot 4 */ /* needs indirect access */
+        0,   /* Slot 10 - unused */
+        0,   /* Slot 11 - unused */
+        0,   /* Slot 12 - unused */
+        0,   /* Slot 13 - unused */
+        0,   /* Slot 14 - unused */
+        0,   /* Slot 15 - unused */
+        1,   /* Slot 16  - PCI slot 1 */
+        2,   /* Slot 17  - PCI slot 2  */
+        3,   /* Slot 18  - PCI slot 3 */
+        4,   /* Slot 19  - PCI slot 4 */ /* needs indirect access */
+        0,
+        0,
+        0,
+};
+
+static char Omaha_pci_IRQ_routes[] __prepdata =
+{
+        0,   /* Line 0 - Unused */
+        9,   /* Line 1 */
+        11,  /* Line 2 */
+        14,  /* Line 3 */
+        15   /* Line 4 */
+};
+
+/* Motorola PowerStack */
+static char Blackhawk_pci_IRQ_map[19] __prepdata =
+{
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+ 	1,	/* Slot P7 */
+ 	2,	/* Slot P6 */
+ 	3,	/* Slot P5 */
+};
+
+static char Blackhawk_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* Line 0 - Unused */
+   	9,	/* Line 1 */
+   	11,	/* Line 2 */
+   	15,	/* Line 3 */
+   	15	/* Line 4 */
+};
+   
+/* Motorola Mesquite */
+static char Mesquite_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	0,	/* Slot 2  - unused */
+	0,	/* Slot 3  - unused */
+	0,	/* Slot 4  - unused */
+	0,	/* Slot 5  - unused */
+	0,	/* Slot 6  - unused */
+	0,	/* Slot 7  - unused */
+	0,	/* Slot 8  - unused */
+	0,	/* Slot 9  - unused */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - unused */
+	0,	/* Slot 12 - unused */
+	0,	/* Slot 13 - unused */
+	2,	/* Slot 14 - Ethernet */
+	0,	/* Slot 15 - unused */
+	3,	/* Slot 16 - PMC */
+	0,	/* Slot 17 - unused */
+	0,	/* Slot 18 - unused */
+	0,	/* Slot 19 - unused */
+	0,	/* Slot 20 - unused */
+	0,	/* Slot 21 - unused */
+	0,	/* Slot 22 - unused */
+};
+
+/* Motorola Sitka */
+static char Sitka_pci_IRQ_map[21] __prepdata =
+{
+	0,      /* Slot 0  - unused */
+	0,      /* Slot 1  - unused */
+	0,      /* Slot 2  - unused */
+	0,      /* Slot 3  - unused */
+	0,      /* Slot 4  - unused */
+	0,      /* Slot 5  - unused */
+	0,      /* Slot 6  - unused */
+	0,      /* Slot 7  - unused */
+	0,      /* Slot 8  - unused */
+	0,      /* Slot 9  - unused */
+	0,      /* Slot 10 - unused */
+	0,      /* Slot 11 - unused */
+	0,      /* Slot 12 - unused */
+	0,      /* Slot 13 - unused */
+	2,      /* Slot 14 - Ethernet */
+	0,      /* Slot 15 - unused */
+	9,      /* Slot 16 - PMC 1  */
+	12,     /* Slot 17 - PMC 2  */
+	0,      /* Slot 18 - unused */
+	0,      /* Slot 19 - unused */
+	4,      /* Slot 20 - NT P2P bridge */
+};
+
+/* Motorola MTX */
+static char MTX_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	0,	/* Slot 2  - unused */
+	0,	/* Slot 3  - unused */
+	0,	/* Slot 4  - unused */
+	0,	/* Slot 5  - unused */
+	0,	/* Slot 6  - unused */
+	0,	/* Slot 7  - unused */
+	0,	/* Slot 8  - unused */
+	0,	/* Slot 9  - unused */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - unused */
+	3,	/* Slot 12 - SCSI */
+	0,	/* Slot 13 - unused */
+	2,	/* Slot 14 - Ethernet */
+	0,	/* Slot 15 - unused */
+	9,      /* Slot 16 - PCI/PMC slot 1 */
+	10,     /* Slot 17 - PCI/PMC slot 2 */
+	11,     /* Slot 18 - PCI slot 3 */
+	0,	/* Slot 19 - unused */
+	0,	/* Slot 20 - unused */
+	0,	/* Slot 21 - unused */
+	0,	/* Slot 22 - unused */
+};
+
+/* Motorola MTX Plus */
+/* Secondary bus interrupt routing is not supported yet */
+static char MTXplus_pci_IRQ_map[23] __prepdata =
+{
+        0,      /* Slot 0  - unused */
+        0,      /* Slot 1  - unused */
+        0,      /* Slot 2  - unused */
+        0,      /* Slot 3  - unused */
+        0,      /* Slot 4  - unused */
+        0,      /* Slot 5  - unused */
+        0,      /* Slot 6  - unused */
+        0,      /* Slot 7  - unused */
+        0,      /* Slot 8  - unused */
+        0,      /* Slot 9  - unused */
+        0,      /* Slot 10 - unused */
+        0,      /* Slot 11 - unused */
+        3,      /* Slot 12 - SCSI */
+        0,      /* Slot 13 - unused */
+        2,      /* Slot 14 - Ethernet 1 */
+        0,      /* Slot 15 - unused */
+        9,      /* Slot 16 - PCI slot 1P */
+        10,     /* Slot 17 - PCI slot 2P */
+        11,     /* Slot 18 - PCI slot 3P */
+        10,     /* Slot 19 - Ethernet 2 */
+        0,      /* Slot 20 - P2P Bridge */
+        0,      /* Slot 21 - unused */
+        0,      /* Slot 22 - unused */
+};
+
+static char Raven_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* This is a dummy structure */
+};
+   
+/* Motorola MVME16xx */
+static char Genesis_pci_IRQ_map[16] __prepdata =
+{
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+};
+
+static char Genesis_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* Line 0 - Unused */
+   	10,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+};
+   
+static char Genesis2_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	0,	/* Slot 2  - unused */
+	0,	/* Slot 3  - unused */
+	0,	/* Slot 4  - unused */
+	0,	/* Slot 5  - unused */
+	0,	/* Slot 6  - unused */
+	0,	/* Slot 7  - unused */
+	0,	/* Slot 8  - unused */
+	0,	/* Slot 9  - unused */
+	0,	/* Slot 10 - Ethernet */
+	0,	/* Slot 11 - Universe PCI - VME Bridge */
+	3,	/* Slot 12 - unused */
+	0,	/* Slot 13 - unused */
+	2,	/* Slot 14 - SCSI */
+	0,	/* Slot 15 - unused */
+	9,	/* Slot 16 - PMC 1 */
+	12,	/* Slot 17 - pci */
+	11,	/* Slot 18 - pci */
+	10,	/* Slot 19 - pci */
+	0,	/* Slot 20 - pci */
+	0,	/* Slot 21 - unused */
+	0,	/* Slot 22 - unused */
+};
+
+/* Motorola Series-E */
+static char Comet_pci_IRQ_map[23] __prepdata =
+{
+  	0,	/* Slot 0  - unused */
+  	0,	/* Slot 1  - unused */
+  	0,	/* Slot 2  - unused */
+  	0,	/* Slot 3  - unused */
+  	0,	/* Slot 4  - unused */
+  	0,	/* Slot 5  - unused */
+  	0,	/* Slot 6  - unused */
+  	0,	/* Slot 7  - unused */
+  	0,	/* Slot 8  - unused */
+  	0,	/* Slot 9  - unused */
+  	0,	/* Slot 10 - unused */
+  	0,	/* Slot 11 - unused */
+  	3,	/* Slot 12 - SCSI */
+  	0,	/* Slot 13 - unused */
+  	1,	/* Slot 14 - Ethernet */
+  	0,	/* Slot 15 - unused */
+	1,	/* Slot 16 - PCI slot 1 */
+	2,	/* Slot 17 - PCI slot 2 */
+	3,	/* Slot 18 - PCI slot 3 */
+	4,	/* Slot 19 - PCI bridge */
+	0,
+	0,
+	0,
+};
+
+static char Comet_pci_IRQ_routes[] __prepdata =
+{
+   	0,	/* Line 0 - Unused */
+   	10,	/* Line 1 */
+   	11,	/* Line 2 */
+   	14,	/* Line 3 */
+   	15	/* Line 4 */
+};
+
+/* Motorola Series-EX */
+static char Comet2_pci_IRQ_map[23] __prepdata =
+{
+	0,	/* Slot 0  - unused */
+	0,	/* Slot 1  - unused */
+	3,	/* Slot 2  - SCSI - NCR825A */
+	0,	/* Slot 3  - unused */
+	1,	/* Slot 4  - Ethernet - DEC2104X */
+	0,	/* Slot 5  - unused */
+	1,	/* Slot 6  - PCI slot 1 */
+	2,	/* Slot 7  - PCI slot 2 */
+	3,	/* Slot 8  - PCI slot 3 */
+	4,	/* Slot 9  - PCI bridge  */
+	0,	/* Slot 10 - unused */
+	0,	/* Slot 11 - unused */
+	3,	/* Slot 12 - SCSI - NCR825A */
+	0,	/* Slot 13 - unused */
+	1,	/* Slot 14 - Ethernet - DEC2104X */
+	0,	/* Slot 15 - unused */
+	1,	/* Slot 16 - PCI slot 1 */
+	2,	/* Slot 17 - PCI slot 2 */
+	3,	/* Slot 18 - PCI slot 3 */
+	4,	/* Slot 19 - PCI bridge */
+	0,
+	0,
+	0,
+};
+
+static char Comet2_pci_IRQ_routes[] __prepdata =
+{
+	0,	/* Line 0 - Unused */
+	10,	/* Line 1 */
+	11,	/* Line 2 */
+	14,	/* Line 3 */
+	15,	/* Line 4 */
+};
+
+/*
+ * ibm 830 (and 850?).
+ * This is actually based on the Carolina motherboard
+ * -- Cort
+ */
+static char ibm8xx_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 - FireCoral */
+        4, /* Slot 12 - Ethernet  PCIINTD# */
+        2, /* Slot 13 - PCI Slot #2 */
+        2, /* Slot 14 - S3 Video PCIINTD# */
+        0, /* Slot 15 - onboard SCSI (INDI) [1] */
+        3, /* Slot 16 - NCR58C810 RS6000 Only PCIINTC# */
+        0, /* Slot 17 - unused */
+        2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+        0, /* Slot 19 - unused */
+        0, /* Slot 20 - unused */
+        0, /* Slot 21 - unused */
+        2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+
+static char ibm8xx_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        15,     /* Line 1 */
+        15,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+/*
+ * a 6015 ibm board
+ * -- Cort
+ */
+static char ibm6015_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 -  */
+        1, /* Slot 12 - SCSI */
+        2, /* Slot 13 -  */
+        2, /* Slot 14 -  */
+        1, /* Slot 15 -  */
+        1, /* Slot 16 -  */
+        0, /* Slot 17 -  */
+        2, /* Slot 18 -  */
+        0, /* Slot 19 -  */
+        0, /* Slot 20 -  */
+        0, /* Slot 21 -  */
+        2, /* Slot 22 -  */
+};
+
+static char ibm6015_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        13,     /* Line 1 */
+        15,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+
+/* IBM Nobis and Thinkpad 850 */
+static char Nobis_pci_IRQ_map[23] __prepdata ={
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 - unused */
+        3, /* Slot 12 - SCSI */
+        0, /* Slot 13 - unused */
+        0, /* Slot 14 - unused */
+        0, /* Slot 15 - unused */
+};
+
+static char Nobis_pci_IRQ_routes[] __prepdata = {
+        0, /* Line 0 - Unused */
+        13, /* Line 1 */
+        13, /* Line 2 */
+        13, /* Line 3 */
+        13      /* Line 4 */
+};
+
+/*
+ * IBM RS/6000 43p/140  -- paulus
+ * XXX we should get all this from the residual data
+ */
+static char ibm43p_pci_IRQ_map[23] __prepdata = {
+        0, /* Slot 0  - unused */
+        0, /* Slot 1  - unused */
+        0, /* Slot 2  - unused */
+        0, /* Slot 3  - unused */
+        0, /* Slot 4  - unused */
+        0, /* Slot 5  - unused */
+        0, /* Slot 6  - unused */
+        0, /* Slot 7  - unused */
+        0, /* Slot 8  - unused */
+        0, /* Slot 9  - unused */
+        0, /* Slot 10 - unused */
+        0, /* Slot 11 - FireCoral ISA bridge */
+        6, /* Slot 12 - Ethernet  */
+        0, /* Slot 13 - openpic */
+        0, /* Slot 14 - unused */
+        0, /* Slot 15 - unused */
+        7, /* Slot 16 - NCR58C825a onboard scsi */
+        0, /* Slot 17 - unused */
+        2, /* Slot 18 - PCI Slot 2 PCIINTx# (See below) */
+        0, /* Slot 19 - unused */
+        0, /* Slot 20 - unused */
+        0, /* Slot 21 - unused */
+        1, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
+};
+
+static char ibm43p_pci_IRQ_routes[] __prepdata = {
+        0,      /* Line 0 - unused */
+        15,     /* Line 1 */
+        15,     /* Line 2 */
+        15,     /* Line 3 */
+        15,     /* Line 4 */
+};
+
+/* Motorola PowerPlus architecture PCI IRQ tables */
+/* Interrupt line values for INTA-D on primary/secondary MPIC inputs */
+
+struct powerplus_irq_list
+{
+	unsigned char primary[4];       /* INT A-D */
+	unsigned char secondary[4];     /* INT A-D */
+};
+
+/*
+ * For standard PowerPlus boards, bus 0 PCI INTs A-D are routed to
+ * OpenPIC inputs 9-12.  PCI INTs A-D from the on board P2P bridge
+ * are routed to OpenPIC inputs 5-8.  These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+struct powerplus_irq_list Powerplus_pci_IRQ_list __prepdata =
+{
+	{25, 26, 27, 28},
+	{21, 22, 23, 24}
+};
+
+/*
+ * For the MCP750 (system slot board), cPCI INTs A-D are routed to
+ * OpenPIC inputs 8-11 and the PMC INTs A-D are routed to OpenPIC
+ * input 3.  On a hot swap MCP750, the companion card PCI INTs A-D
+ * are routed to OpenPIC inputs 12-15. These values are offset by
+ * 16 in the table to reflect the Linux kernel interrupt value.
+ */
+struct powerplus_irq_list Mesquite_pci_IRQ_list __prepdata =
+{
+	{24, 25, 26, 27},
+	{28, 29, 30, 31}
+};
+
+/*
+ * This table represents the standard PCI swizzle defined in the
+ * PCI bus specification.
+ */
+static unsigned char prep_pci_intpins[4][4] __prepdata =
+{
+	{ 1, 2, 3, 4},  /* Buses 0, 4, 8, ... */
+	{ 2, 3, 4, 1},  /* Buses 1, 5, 9, ... */
+	{ 3, 4, 1, 2},  /* Buses 2, 6, 10 ... */
+	{ 4, 1, 2, 3},  /* Buses 3, 7, 11 ... */
+};
+
+/* We have to turn on LEVEL mode for changed IRQ's */
+/* All PCI IRQ's need to be level mode, so this should be something
+ * other than hard-coded as well... IRQ's are individually mappable
+ * to either edge or level.
+ */
+
+/*
+ * 8259 edge/level control definitions
+ */
+#define ISA8259_M_ELCR 0x4d0
+#define ISA8259_S_ELCR 0x4d1
+
+#define ELCRS_INT15_LVL         0x80
+#define ELCRS_INT14_LVL         0x40
+#define ELCRS_INT12_LVL         0x10
+#define ELCRS_INT11_LVL         0x08
+#define ELCRS_INT10_LVL         0x04
+#define ELCRS_INT9_LVL          0x02
+#define ELCRS_INT8_LVL          0x01
+#define ELCRM_INT7_LVL          0x80
+#define ELCRM_INT5_LVL          0x20
+
+#define CFGPTR(dev) (0x80800000 | (1<<(dev>>3)) | ((dev&7)<<8) | offset)
+#define DEVNO(dev)  (dev>>3)                                  
+
+#define cfg_read(val, addr, type, op)	*val = op((type)(addr))
+#define cfg_write(val, addr, type, op)	op((type *)(addr), (val))
+
+#define cfg_read_bad(val, size)		*val = bad_##size;
+#define cfg_write_bad(val, size)
+
+#define bad_byte	0xff
+#define bad_word	0xffff
+#define bad_dword	0xffffffffU
+
+#define PREP_PCI_OP(rw, size, type, op)					\
+static int __prep							\
+prep_##rw##_config_##size(struct pci_dev *dev, int offset, type val)	\
+{									\
+	if ((dev->bus->number != 0) || (DEVNO(dev->devfn) > MAX_DEVNR))	\
+	{                   						\
+		cfg_##rw##_bad(val, size)				\
+		return PCIBIOS_DEVICE_NOT_FOUND;    			\
+	}								\
+	cfg_##rw(val, CFGPTR(dev->devfn), type, op);			\
+	return PCIBIOS_SUCCESSFUL;					\
+}
+
+PREP_PCI_OP(read, byte, u8 *, in_8)
+PREP_PCI_OP(read, word, u16 *, in_le16)
+PREP_PCI_OP(read, dword, u32 *, in_le32)
+PREP_PCI_OP(write, byte, u8, out_8)
+PREP_PCI_OP(write, word, u16, out_le16)
+PREP_PCI_OP(write, dword, u32, out_le32)
+
+static struct pci_ops prep_pci_ops =
+{
+	prep_read_config_byte,
+	prep_read_config_word,
+	prep_read_config_dword,
+	prep_write_config_byte,
+	prep_write_config_word,
+	prep_write_config_dword
+};
+
+#define MOTOROLA_CPUTYPE_REG	0x800
+#define MOTOROLA_BASETYPE_REG	0x803
+#define MPIC_RAVEN_ID		0x48010000
+#define	MPIC_HAWK_ID		0x48030000
+#define	MOT_PROC2_BIT		0x800
+
+static u_char mvme2600_openpic_initsenses[] __initdata = {
+    1,	/* MVME2600_INT_SIO */
+    0,	/* MVME2600_INT_FALCN_ECC_ERR */
+    1,	/* MVME2600_INT_PCI_ETHERNET */
+    1,	/* MVME2600_INT_PCI_SCSI */
+    1,	/* MVME2600_INT_PCI_GRAPHICS */
+    1,	/* MVME2600_INT_PCI_VME0 */
+    1,	/* MVME2600_INT_PCI_VME1 */
+    1,	/* MVME2600_INT_PCI_VME2 */
+    1,	/* MVME2600_INT_PCI_VME3 */
+    1,	/* MVME2600_INT_PCI_INTA */
+    1,	/* MVME2600_INT_PCI_INTB */
+    1,	/* MVME2600_INT_PCI_INTC */
+    1,	/* MVME2600_INT_PCI_INTD */
+    1,	/* MVME2600_INT_LM_SIG0 */
+    1,	/* MVME2600_INT_LM_SIG1 */
+};
+
+#define MOT_RAVEN_PRESENT	0x1
+#define MOT_HAWK_PRESENT	0x2
+
+int mot_entry = -1;
+int prep_keybd_present = 1;
+int MotMPIC;
+int mot_multi;
+
+int __init
+raven_init(void)
+{
+	unsigned int	devid;
+	unsigned int	pci_membase;
+	unsigned char	base_mod;
+
+	/* Check to see if the Raven chip exists. */
+	if ( _prep_type != _PREP_Motorola) {
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+	/* Check to see if this board is a type that might have a Raven. */
+	if ((inb(MOTOROLA_CPUTYPE_REG) & 0xF0) != 0xE0) {
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+	/* Check the first PCI device to see if it is a Raven. */
+	early_read_config_dword(0, 0, 0, PCI_VENDOR_ID, &devid);
+
+	switch (devid & 0xffff0000) {
+	case MPIC_RAVEN_ID:
+		MotMPIC = MOT_RAVEN_PRESENT;
+		break;
+	case MPIC_HAWK_ID:
+		MotMPIC = MOT_HAWK_PRESENT;
+		break;
+	default:
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+
+	/* Read the memory base register. */
+	early_read_config_dword(0, 0, 0, PCI_BASE_ADDRESS_1, &pci_membase);
+
+	if (pci_membase == 0) {
+		OpenPIC_Addr = NULL;
+		return 0;
+	}
+
+	/* Map the Raven MPIC registers to virtual memory. */
+	OpenPIC_Addr = ioremap(pci_membase+0xC0000000, 0x22000);
+
+	OpenPIC_InitSenses = mvme2600_openpic_initsenses;
+	OpenPIC_NumInitSenses = sizeof(mvme2600_openpic_initsenses);
+
+	ppc_md.get_irq = openpic_get_irq;
+	
+	/* If raven is present on Motorola store the system config register
+	 * for later use.
+	 */
+	ProcInfo = (unsigned long *)ioremap(0xfef80400, 4);
+
+	/* Indicate to system if this is a multiprocessor board */
+	if (!(*ProcInfo & MOT_PROC2_BIT)) {
+		mot_multi = 1;
+	}
+
+	/* This is a hack.  If this is a 2300 or 2400 mot board then there is
+	 * no keyboard controller and we have to indicate that.
+	 */
+	base_mod = inb(MOTOROLA_BASETYPE_REG);
+	if ((MotMPIC == MOT_HAWK_PRESENT) || (base_mod == 0xF9) ||
+	    (base_mod == 0xFA) || (base_mod == 0xE1))
+		prep_keybd_present = 0;
+
+	return 1;
+}
+
+struct mot_info {
+	int		cpu_type;	/* 0x100 mask assumes for Raven and Hawk boards that the level/edge are set */
+					/* 0x200 if this board has a Hawk chip. */
+	int		base_type;
+	int		max_cpu;	/* ored with 0x80 if this board should be checked for multi CPU */
+	const char	*name;
+	unsigned char	*map;
+	unsigned char	*routes;
+	void            (*map_non0_bus)(struct pci_dev *);      /* For boards with more than bus 0 devices. */
+	struct powerplus_irq_list *pci_irq_list; /* List of PCI MPIC inputs */
+	unsigned char   secondary_bridge_devfn; /* devfn of secondary bus transparent bridge */
+} mot_info[] __prepdata = {
+	{0x300, 0x00, 0x00, "MVME 2400",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x010, 0x00, 0x00, "Genesis",				Genesis_pci_IRQ_map,	Genesis_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x020, 0x00, 0x00, "Powerstack (Series E)",		Comet_pci_IRQ_map,	Comet_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x040, 0x00, 0x00, "Blackhawk (Powerstack)",		Blackhawk_pci_IRQ_map,	Blackhawk_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x050, 0x00, 0x00, "Omaha (PowerStack II Pro3000)",	Omaha_pci_IRQ_map,	Omaha_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x060, 0x00, 0x00, "Utah (Powerstack II Pro4000)",	Utah_pci_IRQ_map,	Utah_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x0A0, 0x00, 0x00, "Powerstack (Series EX)",		Comet2_pci_IRQ_map,	Comet2_pci_IRQ_routes, NULL, NULL, 0x00},
+	{0x1E0, 0xE0, 0x00, "Mesquite cPCI (MCP750)",		Mesquite_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xE1, 0x00, "Sitka cPCI (MCPN750)",		Sitka_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xE2, 0x00, "Mesquite cPCI (MCP750) w/ HAC",	Mesquite_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Mesquite_pci_IRQ_list, 0xC0},
+	{0x1E0, 0xF6, 0x80, "MTX Plus",				MTXplus_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+	{0x1E0, 0xF6, 0x81, "Dual MTX Plus",			MTXplus_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xA0},
+	{0x1E0, 0xF7, 0x80, "MTX wo/ Parallel Port",		MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF7, 0x81, "Dual MTX wo/ Parallel Port",	MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF8, 0x80, "MTX w/ Parallel Port",		MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF8, 0x81, "Dual MTX w/ Parallel Port",	MTX_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xF9, 0x00, "MVME 2300",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFA, 0x00, "MVME 2300SC/2600",			Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFB, 0x00, "MVME 2600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFC, 0x00, "MVME 2600/2700 with MVME761",	Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFD, 0x80, "MVME 3600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0x00},
+	{0x1E0, 0xFD, 0x81, "MVME 4600 with MVME712M",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFE, 0x80, "MVME 3600 with MVME761",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFE, 0x81, "MVME 4600 with MVME761",		Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x1E0, 0xFF, 0x00, "MVME 1600-001 or 1600-011",	Genesis2_pci_IRQ_map,	Raven_pci_IRQ_routes, Powerplus_Map_Non0, &Powerplus_pci_IRQ_list, 0xFF},
+	{0x000, 0x00, 0x00, "",					NULL,			NULL, NULL, NULL, 0x00}
+};
+
+void __init
+ibm_prep_init(void)
+{
+	u32 addr;
+#ifdef CONFIG_PREP_RESIDUAL
+	PPC_DEVICE *mpic;
+#endif
+
+	if (inb(0x0852) == 0xd5) {
+		/* This is for the 43p-140 */
+		early_read_config_dword(0, 0, PCI_DEVFN(13, 0),
+					PCI_BASE_ADDRESS_0, &addr);
+		if (addr != 0xffffffff
+		    && !(addr & PCI_BASE_ADDRESS_SPACE_IO)
+		    && (addr &= PCI_BASE_ADDRESS_MEM_MASK) != 0) {
+			addr += PREP_ISA_MEM_BASE;
+			OpenPIC_Addr = ioremap(addr, 0x40000);
+			ppc_md.get_irq = openpic_get_irq;
+		}
+	}
+
+#ifdef CONFIG_PREP_RESIDUAL
+	mpic = residual_find_device(-1, NULL, SystemPeripheral,
+				    ProgrammableInterruptController, MPIC, 0);
+	if (mpic != NULL)
+		printk("mpic = %p\n", mpic);
+#endif
+}
+
+static void __init
+ibm43p_pci_map_non0(struct pci_dev *dev)
+{
+	unsigned char intpin;
+	static unsigned char bridge_intrs[4] = { 3, 4, 5, 8 };
+
+	if (dev == NULL)
+		return;
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &intpin);
+	if (intpin < 1 || intpin > 4)
+		return;
+	intpin = (PCI_SLOT(dev->devfn) + intpin - 1) & 3;
+	dev->irq = openpic_to_irq(bridge_intrs[intpin]);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+}
+
+void __init
+prep_route_pci_interrupts(void)
+{
+	unsigned char *ibc_pirq = (unsigned char *)0x80800860;
+	unsigned char *ibc_pcicon = (unsigned char *)0x80800840;
+	int i;
+	
+	if ( _prep_type == _PREP_Motorola)
+	{
+		unsigned short irq_mode;
+		unsigned char  cpu_type;
+		unsigned char  base_mod;
+		int	       entry;
+
+		cpu_type = inb(MOTOROLA_CPUTYPE_REG) & 0xF0;
+		base_mod = inb(MOTOROLA_BASETYPE_REG);
+
+		for (entry = 0; mot_info[entry].cpu_type != 0; entry++) {
+			if (mot_info[entry].cpu_type & 0x200) {		 	/* Check for Hawk chip */
+				if (!(MotMPIC & MOT_HAWK_PRESENT))
+					continue;
+			} else {						/* Check non hawk boards */
+				if ((mot_info[entry].cpu_type & 0xff) != cpu_type)
+					continue;
+
+				if (mot_info[entry].base_type == 0) {
+					mot_entry = entry;
+					break;
+				}
+
+				if (mot_info[entry].base_type != base_mod)
+					continue;
+			}
+
+			if (!(mot_info[entry].max_cpu & 0x80)) {
+				mot_entry = entry;
+				break;
+			}
+
+			/* processor 1 not present and max processor zero indicated */
+			if ((*ProcInfo & MOT_PROC2_BIT) && !(mot_info[entry].max_cpu & 0x7f)) {
+				mot_entry = entry;
+				break;
+			}
+
+			/* processor 1 present and max processor zero indicated */
+			if (!(*ProcInfo & MOT_PROC2_BIT) && (mot_info[entry].max_cpu & 0x7f)) {
+				mot_entry = entry;
+				break;
+			}
+		}
+
+		if (mot_entry == -1) 	/* No particular cpu type found - assume Blackhawk */
+			mot_entry = 3;
+
+		Motherboard_map_name = (unsigned char *)mot_info[mot_entry].name;
+		Motherboard_map = mot_info[mot_entry].map;
+		Motherboard_routes = mot_info[mot_entry].routes;
+		Motherboard_non0 = mot_info[mot_entry].map_non0_bus;
+
+		if (!(mot_info[entry].cpu_type & 0x100)) {
+			/* AJF adjust level/edge control according to routes */
+			irq_mode = 0;
+			for (i = 1;  i <= 4;  i++)
+				irq_mode |= ( 1 << Motherboard_routes[i] );
+			outb( irq_mode & 0xff, 0x4d0 );
+			outb( (irq_mode >> 8) & 0xff, 0x4d1 );
+		}
+	} else if ( _prep_type == _PREP_IBM ) {
+		unsigned char planar_id = inb(0x0852);
+		unsigned char irq_edge_mask_lo, irq_edge_mask_hi;
+
+		printk("IBM ID: %08x\n", planar_id);
+		switch(planar_id) {
+		case 0xff:
+			Motherboard_map_name = "IBM Thinkpad 850/860";
+			Motherboard_map = Nobis_pci_IRQ_map;
+			Motherboard_routes = Nobis_pci_IRQ_routes;
+			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+			irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+			break;
+		case 0xfc:
+			Motherboard_map_name = "IBM 6015/7020 (Sandalfoot/Sandalbow)";
+			Motherboard_map = ibm6015_pci_IRQ_map;
+			Motherboard_routes = ibm6015_pci_IRQ_routes;
+			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+			irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+			break;
+		case 0xd5:
+			Motherboard_map_name = "IBM 43P-140 (Tiger1)";
+			Motherboard_map = ibm43p_pci_IRQ_map;
+			Motherboard_routes = ibm43p_pci_IRQ_routes;
+			Motherboard_non0 = ibm43p_pci_map_non0;
+			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+			irq_edge_mask_hi = 0xA0; /* irq's 13, 15 level-triggered */
+			break;
+		default:
+			printk(KERN_ERR "Unknown IBM motherboard! Defaulting to Carolina.\n");
+		case 0xf0: /* PowerSeries 830/850 */
+		case 0xf1: /* PowerSeries 830/850 */
+		case 0xf2: /* PowerSeries 830/850 */
+		case 0xf4: /* 7248-43P */
+		case 0xf5: /* 7248-43P */
+		case 0xf6: /* 7248-43P */
+		case 0xf7: /* 7248-43P (missing from Carolina Tech Spec) */
+			Motherboard_map_name = "IBM PS830/PS850/7248 (Carolina)";
+			Motherboard_map = ibm8xx_pci_IRQ_map;
+			Motherboard_routes = ibm8xx_pci_IRQ_routes;
+			irq_edge_mask_lo = 0x00; /* irq's 0-7 all edge-triggered */
+			irq_edge_mask_hi = 0xA4; /* irq's 10, 13, 15 level-triggered */
+			break;
+		}
+
+		outb(inb(0x04d0)|irq_edge_mask_lo, 0x04d0); /* primary 8259 */
+		outb(inb(0x04d1)|irq_edge_mask_hi, 0x04d1); /* cascaded 8259 */
+	} else {
+		printk("No known machine pci routing!\n");
+		return;
+	}
+	
+	/* Set up mapping from slots */
+	for (i = 1;  i <= 4;  i++)
+		ibc_pirq[i-1] = Motherboard_routes[i];
+	/* Enable PCI interrupts */
+	*ibc_pcicon |= 0x20;
+}
+
+void __init
+prep_pib_init(void)
+{
+	unsigned char   reg;
+	unsigned short  short_reg;
+
+	struct pci_dev *dev = NULL;
+
+	if (( _prep_type == _PREP_Motorola) && (OpenPIC_Addr)) {
+		/*
+		 * Perform specific configuration for the Via Tech or
+		 * or Winbond PCI-ISA-Bridge part.
+		 */
+		if ((dev = pci_find_device(PCI_VENDOR_ID_VIA, 
+					PCI_DEVICE_ID_VIA_82C586_1, dev))) {
+			/*
+			 * PPCBUG does not set the enable bits
+			 * for the IDE device. Force them on here.
+			 */
+			pci_read_config_byte(dev, 0x40, &reg);
+
+			reg |= 0x03; /* IDE: Chip Enable Bits */
+			pci_write_config_byte(dev, 0x40, reg);
+		}
+		if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
+						PCI_DEVICE_ID_VIA_82C586_2,
+						dev)) && (dev->devfn = 0x5a)) {
+			/* Force correct USB interrupt */
+			dev->irq = 11;
+			pci_write_config_byte(dev,
+					PCI_INTERRUPT_LINE,
+					dev->irq);
+		}
+		if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+					PCI_DEVICE_ID_WINBOND_83C553, dev))) {
+			 /* Clear PCI Interrupt Routing Control Register. */
+			short_reg = 0x0000;
+			pci_write_config_word(dev, 0x44, short_reg);
+			if (OpenPIC_Addr){
+				/* Route IDE interrupts to IRQ 14 */
+				reg = 0xEE;
+				pci_write_config_byte(dev, 0x43, reg);
+			}
+		}
+	}
+
+	if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
+				   PCI_DEVICE_ID_WINBOND_82C105, dev))){
+		if (OpenPIC_Addr){
+			/*
+			 * Disable LEGIRQ mode so PCI INTS are routed
+			 * directly to the 8259 and enable both channels
+			 */
+			pci_write_config_dword(dev, 0x40, 0x10ff0033);
+
+			/* Force correct IDE interrupt */
+			dev->irq = 14;
+			pci_write_config_byte(dev,
+					PCI_INTERRUPT_LINE,
+					dev->irq);
+		} else {
+			/* Enable LEGIRQ for PCI INT -> 8259 IRQ routing */
+			pci_write_config_dword(dev, 0x40, 0x10ff08a1);
+		}
+	}
+}
+
+static void __init
+Powerplus_Map_Non0(struct pci_dev *dev)
+{
+	struct pci_bus  *pbus;          /* Parent bus structure pointer */
+	struct pci_dev  *tdev = dev;    /* Temporary device structure */
+	unsigned int    devnum;         /* Accumulated device number */
+	unsigned char   intline;        /* Linux interrupt value */
+	unsigned char   intpin;         /* PCI interrupt pin */
+
+	/* Check for valid PCI dev pointer */
+	if (dev == NULL) return;
+
+	/* Initialize bridge IDSEL variable */
+	devnum = PCI_SLOT(tdev->devfn);
+
+	/* Read the interrupt pin of the device and adjust for indexing */
+	pcibios_read_config_byte(dev->bus->number, dev->devfn,
+			PCI_INTERRUPT_PIN, &intpin);
+
+	/* If device doesn't request an interrupt, return */
+	if ( (intpin < 1) || (intpin > 4) )
+		return;
+
+	intpin--;
+
+	/*
+	 * Walk up to bus 0, adjusting the interrupt pin for the standard
+	 * PCI bus swizzle.
+	 */
+	do {
+		intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+		pbus = tdev->bus;        /* up one level */
+		tdev = pbus->self;
+		devnum = PCI_SLOT(tdev->devfn);
+	} while(tdev->bus->number);
+
+	/* Use the primary interrupt inputs by default */
+	intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+
+	/*
+	 * If the board has secondary interrupt inputs, walk the bus and
+	 * note the devfn of the bridge from bus 0.  If it is the same as
+	 * the devfn of the bus bridge with secondary inputs, use those.
+	 * Otherwise, assume it's a PMC site and get the interrupt line
+	 * value from the interrupt routing table.
+	 */ 
+	if (mot_info[mot_entry].secondary_bridge_devfn) {
+		pbus = dev->bus;
+
+		while (pbus->primary != 0)
+			pbus = pbus->parent;
+
+		if ((pbus->self)->devfn != 0xA0) {
+			if ((pbus->self)->devfn == mot_info[mot_entry].secondary_bridge_devfn)
+				intline = mot_info[mot_entry].pci_irq_list->secondary[intpin];
+			else {
+				if ((char *)(mot_info[mot_entry].map) == (char *)Mesquite_pci_IRQ_map)
+					intline = mot_info[mot_entry].map[((pbus->self)->devfn)/8] + 16;
+				else {
+					int i;
+					for (i=0;i<3;i++)
+						intpin = (prep_pci_intpins[devnum % 4][intpin]) - 1;
+					intline = mot_info[mot_entry].pci_irq_list->primary[intpin];
+				}
+			}
+		}
+	}
+
+	/* Write calculated interrupt value to header and device list */
+	dev->irq = intline;
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (u8)dev->irq);
+}
+
+void __init
+prep_pcibios_fixup(void)
+{
+        struct pci_dev *dev;
+        extern unsigned char *Motherboard_map;
+        extern unsigned char *Motherboard_routes;
+        unsigned char i;
+
+	prep_route_pci_interrupts();
+
+	printk("Setting PCI interrupts for a \"%s\"\n", Motherboard_map_name);
+	if (OpenPIC_Addr) {
+		/* PCI interrupts are controlled by the OpenPIC */
+		pci_for_each_dev(dev) {
+			if (dev->bus->number == 0) {
+                       		dev->irq = openpic_to_irq(Motherboard_map[PCI_SLOT(dev->devfn)]);
+				pcibios_write_config_byte(dev->bus->number, dev->devfn, PCI_INTERRUPT_LINE, dev->irq);
+			} else {
+				if (Motherboard_non0 != NULL)
+					Motherboard_non0(dev);
+			}
+		}
+
+		/* Setup the Winbond or Via PIB */
+		prep_pib_init();
+
+		return;
+	}
+
+	pci_for_each_dev(dev) {
+		/*
+		 * Use our old hard-coded kludge to figure out what
+		 * irq this device uses.  This is necessary on things
+		 * without residual data. -- Cort
+		 */
+		unsigned char d = PCI_SLOT(dev->devfn);
+		dev->irq = Motherboard_routes[Motherboard_map[d]];
+
+		for ( i = 0 ; i <= 5 ; i++ ) {
+			/*
+			 * Relocate PCI I/O resources if necessary so the
+			 * standard 256MB BAT covers them.
+			 */
+			if ( (pci_resource_flags(dev, i) & IORESOURCE_IO) &&
+				      (dev->resource[i].start > 0x10000000))  {
+				printk("Relocating PCI address %lx -> %lx\n",
+						dev->resource[i].start,
+						(dev->resource[i].start & 
+						 0x00FFFFFF)| 0x01000000);
+				dev->resource[i].start =
+					(dev->resource[i].start & 0x00FFFFFF)
+					| 0x01000000;
+		                pci_write_config_dword(dev,
+						PCI_BASE_ADDRESS_0 + (i*0x4),
+						dev->resource[i].start);
+				dev->resource[i].end = 
+					(dev->resource[i].end & 0x00FFFFFF)
+					| 0x01000000;
+		        }
+		}
+#if 0
+		/*
+		 * If we have residual data and if it knows about this
+		 * device ask it what the irq is.
+		 *  -- Cort
+		 */
+		ppcd = residual_find_device_id( ~0L, dev->device,
+		                                -1,-1,-1, 0);
+#endif
+	}
+}
+
+static void __init
+prep_pcibios_after_init(void)
+{
+	struct pci_dev *dev;
+	
+	/* If there is a WD 90C, reset the IO BAR to 0x0 (it started that 
+	 * way, but the PCI layer relocated it because it thought 0x0 was
+	 * invalid for a BAR).
+	 * If you don't do this, the card's VGA base will be <IO BAR>+0xc0000
+	 * instead of 0xc0000. vgacon.c (for example) is completely unaware of
+	 * this little quirk.
+	 */
+	dev = pci_find_device(PCI_VENDOR_ID_WD, PCI_DEVICE_ID_WD_90C, NULL);
+	if (dev) {
+		dev->resource[1].end -= dev->resource[1].start;
+		dev->resource[1].start = 0;
+		/* tell the hardware */
+		pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0x0);
+	}
+}
+
+static void __init
+prep_init_resource(struct resource *res, unsigned long start,
+		   unsigned long end, int flags)
+{
+	res->flags = flags;
+	res->start = start;
+	res->end = end;
+	res->name = "PCI host bridge";
+	res->parent = NULL;
+	res->sibling = NULL;
+	res->child = NULL;
+}
+
+void __init
+prep_find_bridges(void)
+{
+	struct pci_controller* hose;
+
+	hose = pcibios_alloc_controller();
+	if (!hose)
+		return;
+
+	hose->first_busno = 0;
+	hose->last_busno = 0xff;
+	hose->pci_mem_offset = PREP_ISA_MEM_BASE;
+	hose->io_base_phys = PREP_ISA_IO_BASE;
+	hose->io_base_virt = (void *)0x80000000; /* see prep_map_io() */
+	prep_init_resource(&hose->io_resource, 0, 0x0fffffff, IORESOURCE_IO);
+	prep_init_resource(&hose->mem_resources[0], 0xc0000000, 0xfeffffff,
+			   IORESOURCE_MEM);
+	
+	printk("PReP architecture\n");
+	{
+#ifdef CONFIG_PREP_RESIDUAL	  
+		PPC_DEVICE *hostbridge;
+
+		hostbridge = residual_find_device(PROCESSORDEVICE, NULL,
+			BridgeController, PCIBridge, -1, 0);
+		if (hostbridge &&
+			hostbridge->DeviceId.Interface == PCIBridgeIndirect) {
+			PnP_TAG_PACKET * pkt;
+			pkt = PnP_find_large_vendor_packet(
+				res->DevicePnPHeap+hostbridge->AllocatedOffset,
+				3, 0);
+			if(pkt) {
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+				setup_indirect_pci(hose, 
+					ld_le32((unsigned *) (p.PPCData)),
+					ld_le32((unsigned *) (p.PPCData+8)));
+			} else
+				setup_indirect_pci(hose, 0x80000cf8, 0x80000cfc);
+		} else
+#endif /* CONFIG_PREP_RESIDUAL */
+			hose->ops = &prep_pci_ops;
+	}
+
+	ppc_md.pcibios_fixup = prep_pcibios_fixup;
+	ppc_md.pcibios_after_init = prep_pcibios_after_init;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/prep_setup.c linux/arch/ppc/platforms/prep_setup.c
--- linux.orig/arch/ppc/platforms/prep_setup.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/prep_setup.c	2002-08-12 22:14:25.000000000 +0000
@@ -0,0 +1,904 @@
+/*
+ * BK Id: SCCS/s.prep_setup.c 1.52 04/05/02 10:17:22 trini
+ */
+/*
+ *  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)
+ *
+ * Support for PReP (Motorola MTX/MVME)
+ * by Troy Benjegerdes (hozer@drgw.net)
+ */
+
+/*
+ * bootup setup stuff..
+ */
+
+#include <linux/config.h>
+#include <linux/delay.h>
+#include <linux/module.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/slab.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/ioport.h>
+#include <linux/console.h>
+#include <linux/timex.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+#include <linux/seq_file.h>
+
+#include <asm/sections.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/residual.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/cache.h>
+#include <asm/dma.h>
+#include <asm/machdep.h>
+#include <asm/mk48t59.h>
+#include <asm/prep_nvram.h>
+#include <asm/raven.h>
+#include <asm/keyboard.h>
+#include <asm/vga.h>
+#include <asm/time.h>
+#include <asm/i8259.h>
+#include <asm/open_pic.h>
+
+#if defined(CONFIG_SOUND) || defined(CONFIG_SOUND_MODULE)
+#include <../drivers/sound/sound_config.h>
+#include <../drivers/sound/dev_table.h>
+#endif
+
+unsigned char ucSystemType;
+unsigned char ucBoardRev;
+unsigned char ucBoardRevMaj, ucBoardRevMin;
+
+extern unsigned long mc146818_get_rtc_time(void);
+extern int mc146818_set_rtc_time(unsigned long nowtime);
+extern unsigned long mk48t59_get_rtc_time(void);
+extern int mk48t59_set_rtc_time(unsigned long nowtime);
+
+extern unsigned char prep_nvram_read_val(int addr);
+extern void prep_nvram_write_val(int addr,
+				 unsigned char val);
+extern unsigned char rs_nvram_read_val(int addr);
+extern void rs_nvram_write_val(int addr,
+				 unsigned char val);
+extern void ibm_prep_init(void);
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+		char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[];
+
+extern void prep_find_bridges(void);
+extern char saved_command_line[];
+
+int _prep_type;
+
+#define cached_21	(((char *)(ppc_cached_irq_mask))[3])
+#define cached_A1	(((char *)(ppc_cached_irq_mask))[2])
+
+/* for the mac fs */
+kdev_t boot_dev;
+/* used in nasty hack for sound - see prep_setup_arch() -- Cort */
+long ppc_cs4232_dma, ppc_cs4232_dma2;
+
+extern PTE *Hash, *Hash_end;
+extern unsigned long Hash_size, Hash_mask;
+extern int probingmem;
+extern unsigned long loops_per_jiffy;
+
+#ifdef CONFIG_SOUND_MODULE
+EXPORT_SYMBOL(ppc_cs4232_dma);
+EXPORT_SYMBOL(ppc_cs4232_dma2);
+#endif
+
+static int __prep
+prep_show_cpuinfo(struct seq_file *m)
+{
+	extern char *Motherboard_map_name;
+	int cachew;
+#ifdef CONFIG_PREP_RESIDUAL
+	int i;
+#endif
+
+	seq_printf(m, "machine\t\t: PReP %s\n", Motherboard_map_name);
+
+	switch ( _prep_type ) {
+	case _PREP_IBM:
+		cachew = inw(0x80c);
+		if (cachew & (1<<6))
+			seq_printf(m, "Upgrade CPU\n");
+		seq_printf(m, "L2\t\t: ");
+		if (cachew & (1<<7)) {
+			seq_printf(m, "not present\n");
+			goto no_l2;
+		}
+		seq_printf(m, "%sKb,", (cachew & (1 << 10))? "512" : "256");
+		seq_printf(m, "%ssync\n", (cachew & (1 << 15))? "" : "a");
+		break;
+	case _PREP_Motorola:
+		cachew = *((unsigned char *)CACHECRBA);
+		seq_printf(m, "L2\t\t: ");
+		switch (cachew & L2CACHE_MASK) {
+		case L2CACHE_512KB:
+			seq_printf(m, "512Kb");
+			break;
+		case L2CACHE_256KB:
+			seq_printf(m, "256Kb");
+			break;
+		case L2CACHE_1MB:
+			seq_printf(m, "1MB");
+			break;
+		case L2CACHE_NONE:
+			seq_printf(m, "none\n");
+			goto no_l2;
+			break;
+		default:
+			seq_printf(m, "%x\n", cachew);
+		}
+		
+		seq_printf(m, ", parity %s",
+			   (cachew & L2CACHE_PARITY)? "enabled" : "disabled");
+
+		seq_printf(m, " SRAM:");
+		
+		switch ( ((cachew & 0xf0) >> 4) & ~(0x3) ) {
+		case 1: seq_printf(m, "synchronous,parity,flow-through\n");
+			break;
+		case 2: seq_printf(m, "asynchronous,no parity\n");
+			break;
+		case 3: seq_printf(m, "asynchronous,parity\n");
+			break;
+		default:seq_printf(m, "synchronous,pipelined,no parity\n");
+			break;
+		}
+		break;
+	default:
+		break;
+	}
+
+no_l2:
+#ifdef CONFIG_PREP_RESIDUAL
+	if (res->ResidualLength != 0) {
+		/* print info about SIMMs */
+		seq_printf(m, "simms\t\t: ");
+		for (i = 0; (res->ActualNumMemories) && (i < MAX_MEMS); i++) {
+			if (res->Memories[i].SIMMSize != 0)
+				seq_printf(m, "%d:%ldM ", i,
+					(res->Memories[i].SIMMSize > 1024) ? 
+					res->Memories[i].SIMMSize>>20 : 
+					res->Memories[i].SIMMSize);
+		}
+		seq_printf(m, "\n");
+	}
+#endif
+
+	return 0;
+}
+
+static int __prep
+prep_show_percpuinfo(struct seq_file *m, int i)
+{
+	/* PREP's without residual data will give incorrect values here */
+	seq_printf(m, "clock\t\t: ");
+#ifdef CONFIG_PREP_RESIDUAL	
+	if (res->ResidualLength)
+		seq_printf(m, "%ldMHz\n",
+			   (res->VitalProductData.ProcessorHz > 1024) ?
+			   res->VitalProductData.ProcessorHz / 1000000 :
+			   res->VitalProductData.ProcessorHz);
+	else
+#endif /* CONFIG_PREP_RESIDUAL */
+		seq_printf(m, "???\n");
+
+	return 0;
+}
+
+static void __init
+prep_setup_arch(void)
+{
+	unsigned char reg;
+#if 0 /* unused?? */
+	unsigned char ucMothMemType;
+	unsigned char ucEquipPres1;
+#endif
+
+	/* init to some ~sane value until calibrate_delay() runs */
+	loops_per_jiffy = 50000000;
+	
+	/* Lookup PCI host bridges */
+	prep_find_bridges();
+	
+	/* Set up floppy in PS/2 mode */
+	outb(0x09, SIO_CONFIG_RA);
+	reg = inb(SIO_CONFIG_RD);
+	reg = (reg & 0x3F) | 0x40;
+	outb(reg, SIO_CONFIG_RD);
+	outb(reg, SIO_CONFIG_RD);	/* Have to write twice to change! */
+
+	/* we should determine this according to what we find! -- Cort */
+	switch ( _prep_type )
+	{
+	case _PREP_IBM:
+		/* Enable L2.  Assume we don't need to flush -- Cort*/
+		*(unsigned char *)(0x8000081c) |= 3;
+		ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
+		break;
+	case _PREP_Motorola:
+		/* Enable L2.  Assume we don't need to flush -- Cort*/
+		*(unsigned char *)(0x8000081c) |= 3;
+#ifdef CONFIG_BLK_DEV_INITRD
+		if (initrd_start)
+			ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0); /* /dev/ram */
+		else
+#endif
+#ifdef CONFIG_ROOT_NFS
+			ROOT_DEV = to_kdev_t(0x00ff); /* /dev/nfs */
+#else
+			ROOT_DEV = to_kdev_t(0x0802); /* /dev/sda2 */
+#endif
+		break;
+	}
+
+	/* Read in NVRAM data */ 
+	init_prep_nvram();
+
+	/* if no bootargs, look in NVRAM */
+	if ( cmd_line[0] == '\0' ) {
+		char *bootargs;
+		 bootargs = prep_nvram_get_var("bootargs");
+		 if (bootargs != NULL) {
+			 strcpy(cmd_line, bootargs);
+			 /* again.. */
+			 strcpy(saved_command_line, cmd_line);
+		}
+	}
+
+#ifdef CONFIG_SOUND_CS4232
+	/*
+	 * setup proper values for the cs4232 driver so we don't have
+	 * to recompile for the motorola or ibm workstations sound systems.
+	 * This is a really nasty hack, but unless we change the driver
+	 * it's the only way to support both addrs from one binary.
+	 * -- Cort
+	 */
+	if ( _machine == _MACH_prep )
+	{
+		extern struct card_info snd_installed_cards[];
+		struct card_info *snd_ptr;
+
+		for ( snd_ptr = snd_installed_cards; 
+			snd_ptr < &snd_installed_cards[num_sound_cards];
+			snd_ptr++ )
+		{
+			if ( snd_ptr->card_type == SNDCARD_CS4232 )
+			{
+				if ( _prep_type == _PREP_Motorola )
+				{
+					snd_ptr->config.io_base = 0x830;
+					snd_ptr->config.irq = 10;
+					snd_ptr->config.dma = ppc_cs4232_dma = 6;
+					snd_ptr->config.dma2 = ppc_cs4232_dma2 = 7;
+				}
+				if ( _prep_type == _PREP_IBM )
+				{
+					snd_ptr->config.io_base = 0x530;
+					snd_ptr->config.irq = 5;
+					snd_ptr->config.dma = ppc_cs4232_dma = 1;
+					/* this is wrong - but leave it for now */
+					snd_ptr->config.dma2 = ppc_cs4232_dma2 = 7;
+				}
+			}
+		}
+	}
+#endif /* CONFIG_SOUND_CS4232 */	
+
+	/*print_residual_device_info();*/
+
+	switch (_prep_type) {
+	case _PREP_Motorola:
+		raven_init();
+		break;
+	case _PREP_IBM:
+		ibm_prep_init();
+		break;
+	}
+
+#ifdef CONFIG_VGA_CONSOLE
+	/* remap the VGA memory */
+	vgacon_remap_base = 0xf0000000;
+	/*vgacon_remap_base = ioremap(0xc0000000, 0xba000);*/
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+}
+
+/*
+ * Determine the decrementer frequency from the residual data
+ * This allows for a faster boot as we do not need to calibrate the
+ * decrementer against another clock. This is important for embedded systems.
+ */
+static int __init
+prep_res_calibrate_decr(void)
+{
+#ifdef CONFIG_PREP_RESIDUAL
+	unsigned long freq, divisor = 4;
+
+	if ( res->VitalProductData.ProcessorBusHz ) {
+		freq = res->VitalProductData.ProcessorBusHz;
+		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+				(freq/divisor)/1000000,
+				(freq/divisor)%1000000);
+		tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000);
+		tb_ticks_per_jiffy = freq / HZ / divisor;
+		return 0;
+	} else
+#endif	
+		return 1;
+}
+
+/*
+ * Uses the on-board timer to calibrate the on-chip decrementer register
+ * for prep systems.  On the pmac the OF tells us what the frequency is
+ * but on prep we have to figure it out.
+ * -- Cort
+ */
+/* Done with 3 interrupts: the first one primes the cache and the
+ * 2 following ones measure the interval. The precision of the method
+ * is still doubtful due to the short interval sampled.
+ */
+static volatile int calibrate_steps __initdata = 3;
+static unsigned tbstamp __initdata = 0;
+
+static void __init
+prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs)
+{
+	unsigned long t, freq;
+	int step=--calibrate_steps;
+
+	t = get_tbl();
+	if (step > 0) {
+		tbstamp = t;
+	} else {
+		freq = (t - tbstamp)*HZ;
+		printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+			 freq/1000000, freq%1000000);
+		tb_ticks_per_jiffy = freq / HZ;
+		tb_to_us = mulhwu_scale_factor(freq, 1000000);
+	}
+}
+
+static void __init
+prep_calibrate_decr(void)
+{
+	int res;
+
+	/* Try and get this from the residual data. */
+	res = prep_res_calibrate_decr();
+
+	/* If we didn't get it from the residual data, try this. */
+	if ( res ) {
+		unsigned long flags;
+
+		save_flags(flags);
+
+#define TIMER0_COUNT 0x40
+#define TIMER_CONTROL 0x43
+		/* set timer to periodic mode */
+		outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */
+		/* set the clock to ~100 Hz */
+		outb_p(LATCH & 0xff , TIMER0_COUNT);	/* LSB */
+		outb(LATCH >> 8 , TIMER0_COUNT);	/* MSB */
+
+		if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0)
+			panic("Could not allocate timer IRQ!");
+		__sti();
+		/* wait for calibrate */
+		while ( calibrate_steps )
+			;
+		restore_flags(flags);
+		free_irq( 0, NULL);
+	}
+}
+
+static long __init
+mk48t59_init(void) {
+	unsigned char tmp;
+
+	tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+	if (tmp & MK48T59_RTC_CB_STOP) {
+		printk("Warning: RTC was stopped, date will be wrong.\n");
+		ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, 
+					 tmp & ~MK48T59_RTC_CB_STOP);
+		/* Low frequency crystal oscillators may take a very long
+		 * time to startup and stabilize. For now just ignore the
+		 * the issue, but attempting to calibrate the decrementer
+		 * from the RTC just after this wakeup is likely to be very 
+		 * inaccurate. Firmware should not allow to load
+		 * the OS with the clock stopped anyway...
+		 */
+	}
+	/* Ensure that the clock registers are updated */
+	tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+	tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE);
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp);
+	return 0;
+}
+
+/* We use the NVRAM RTC to time a second to calibrate the decrementer,
+ * the RTC registers have just been set up in the right state by the
+ * preceding routine.
+ */
+static void __init
+mk48t59_calibrate_decr(void)
+{
+	unsigned long freq;
+	unsigned long t1;
+	unsigned char save_control;
+	long i;
+	unsigned char sec;
+ 
+		
+	/* Make sure the time is not stopped. */
+	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB);
+	
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+			(save_control & (~MK48T59_RTC_CB_STOP)));
+
+	/* Now make sure the read bit is off so the value will change. */
+	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+	save_control &= ~MK48T59_RTC_CA_READ;
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+
+	/* Read the seconds value to see when it changes. */
+	sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+	/* Actually this is bad for precision, we should have a loop in
+	 * which we only read the seconds counter. nvram_read_val writes
+	 * the address bytes on every call and this takes a lot of time.
+	 * Perhaps an nvram_wait_change method returning a time
+	 * stamp with a loop count as parameter would be the  solution.
+	 */
+	for (i = 0 ; i < 1000000 ; i++)	{ /* may take up to 1 second... */
+		t1 = get_tbl();
+		if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) {
+			break;
+		}
+	}
+
+	sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+	for (i = 0 ; i < 1000000 ; i++)	{ /* Should take up 1 second... */
+		freq = get_tbl()-t1;
+		if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec)
+			break;
+	}
+
+	printk("time_init: decrementer frequency = %lu.%.6lu MHz\n",
+		 freq/1000000, freq%1000000);
+	tb_ticks_per_jiffy = freq / HZ;
+	tb_to_us = mulhwu_scale_factor(freq, 1000000);
+}
+
+static void __prep
+prep_restart(char *cmd)
+{
+	unsigned long i = 10000;
+
+	__cli();
+
+	/* set exception prefix high - to the prom */
+	_nmask_and_or_msr(0, MSR_IP);
+
+	/* make sure bit 0 (reset) is a 0 */
+	outb( inb(0x92) & ~1L , 0x92 );
+	/* signal a reset to system control port A - soft reset */
+	outb( inb(0x92) | 1 , 0x92 );
+
+	while ( i != 0 ) i++;
+	panic("restart failed\n");
+}
+
+static void __prep
+prep_halt(void)
+{
+	unsigned long flags;
+	__cli();
+	/* set exception prefix high - to the prom */
+	save_flags( flags );
+	restore_flags( flags|MSR_IP );
+
+	/* make sure bit 0 (reset) is a 0 */
+	outb( inb(0x92) & ~1L , 0x92 );
+	/* signal a reset to system control port A - soft reset */
+	outb( inb(0x92) | 1 , 0x92 );
+
+	while ( 1 ) ;
+	/*
+	 * Not reached
+	 */
+}
+
+/*
+ * On IBM PReP's, power management is handled by a Signetics 87c750 behind the
+ * Utah component on the ISA bus. To access the 750 you must write a series of
+ * nibbles to port 0x82a (decoded by the Utah). This is described somewhat in
+ * the IBM Carolina Technical Specification.
+ * -Hollis
+ */
+static void __prep
+utah_sig87c750_setbit(unsigned int bytenum, unsigned int bitnum, int value)
+{
+	/*
+	 * byte1: 0 0 0 1 0  d  a5 a4
+	 * byte2: 0 0 0 1 a3 a2 a1 a0
+	 *
+	 * d = the bit's value, enabled or disabled
+	 * (a5 a4 a3) = the byte number, minus 20
+	 * (a2 a1 a0) = the bit number
+	 *
+	 * example: set the 5th bit of byte 21 (21.5)
+	 *     a5 a4 a3 = 001 (byte 1)
+	 *     a2 a1 a0 = 101 (bit 5)
+	 *
+	 *     byte1 = 0001 0100 (0x14)
+	 *     byte2 = 0001 1101 (0x1d)
+	 */
+	unsigned char byte1=0x10, byte2=0x10;
+	const unsigned int pm_reg_1=0x82a; /* ISA address */
+
+	/* the 750's '20.0' is accessed as '0.0' through Utah (which adds 20) */
+	bytenum -= 20;
+
+	byte1 |= (!!value) << 2;		/* set d */
+	byte1 |= (bytenum >> 1) & 0x3;	/* set a5, a4 */
+
+	byte2 |= (bytenum & 0x1) << 3;	/* set a3 */
+	byte2 |= bitnum & 0x7;			/* set a2, a1, a0 */
+
+	outb(byte1, pm_reg_1);		/* first nibble */
+	mb();
+	udelay(100);				/* important: let controller recover */
+
+	outb(byte2, pm_reg_1);		/* second nibble */
+	mb();
+	udelay(100);				/* important: let controller recover */
+}
+
+static void __prep
+prep_power_off(void)
+{
+	if ( _prep_type == _PREP_IBM) {
+		/* tested on:
+		 * 		Carolina's: 7248-43P, 6070 (PowerSeries 850)
+		 * should work on:
+		 * 		Carolina: 6050 (PowerSeries 830)
+		 * 		7043-140 (Tiger 1)
+		 */
+		unsigned long flags;
+		__cli();
+		/* set exception prefix high - to the prom */
+		save_flags( flags );
+		restore_flags( flags|MSR_IP );
+
+		utah_sig87c750_setbit(21, 5, 1); /* set bit 21.5, "PMEXEC_OFF" */
+
+		while ( 1 ) ;
+		/* not reached */
+	} else {
+		prep_halt();
+	}
+}
+
+static unsigned int __prep
+prep_irq_cannonicalize(u_int irq)
+{
+	if (irq == 2)
+	{
+		return 9;
+	}
+	else
+	{
+		return irq;
+	}
+}
+
+static int __prep
+prep_get_irq(struct pt_regs *regs)
+{
+	return i8259_irq();
+}		
+
+static void __init
+prep_init_IRQ(void)
+{
+	int i;
+
+	if (OpenPIC_Addr != NULL)
+		openpic_init(1, NUM_8259_INTERRUPTS, 0, -1);
+	for ( i = 0 ; i < NUM_8259_INTERRUPTS ; i++ )
+		irq_desc[i].handler = &i8259_pic;
+	i8259_init(0xbffffff0); /* PCI interrupt ack address for MPC105 and 106 */
+}
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+/*
+ * IDE stuff.
+ */
+static int __prep
+prep_ide_default_irq(ide_ioreg_t base)
+{
+	switch (base) {
+		case 0x1f0: return 13;
+		case 0x170: return 13;
+		case 0x1e8: return 11;
+		case 0x168: return 10;
+		case 0xfff0: return 14;		/* MCP(N)750 ide0 */
+		case 0xffe0: return 15;		/* MCP(N)750 ide1 */
+		default: return 0;
+	}
+}
+
+static ide_ioreg_t __prep
+prep_ide_default_io_base(int index)
+{
+	switch (index) {
+		case 0: return 0x1f0;
+		case 1: return 0x170;
+		case 2: return 0x1e8;
+		case 3: return 0x168;
+		default:
+			return 0;
+	}
+}
+
+static int __prep
+prep_ide_check_region(ide_ioreg_t from, unsigned int extent)
+{
+	return check_region(from, extent);
+}
+
+static void __prep
+prep_ide_request_region(ide_ioreg_t from,
+			unsigned int extent,
+			const char *name)
+{
+	request_region(from, extent, name);
+}
+
+static void __prep
+prep_ide_release_region(ide_ioreg_t from,
+			unsigned int extent)
+{
+	release_region(from, extent);
+}
+
+static void __init
+prep_ide_init_hwif_ports (hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+{
+	ide_ioreg_t reg = data_port;
+	int i;
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	if (ctrl_port) {
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
+	} else {
+		hw->io_ports[IDE_CONTROL_OFFSET] = hw->io_ports[IDE_DATA_OFFSET] + 0x206;
+	}
+	if (irq != NULL)
+		*irq = 0;
+}
+#endif
+
+#ifdef CONFIG_SMP
+/* PReP (MTX) support */
+static int __init
+smp_prep_probe(void)
+{
+	extern int mot_multi;
+
+	if (mot_multi) {
+		openpic_request_IPIs();
+		smp_hw_index[1] = 1;
+		return 2;
+	}
+
+	return 1;
+}
+
+static void __init
+smp_prep_kick_cpu(int nr)
+{
+	*(unsigned long *)KERNELBASE = nr;
+	asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory");
+	printk("CPU1 reset, waiting\n");
+}
+
+static void __init
+smp_prep_setup_cpu(int cpu_nr)
+{
+	if (OpenPIC_Addr)
+		do_openpic_setup_cpu();
+}
+
+static struct smp_ops_t prep_smp_ops __prepdata = {
+	smp_openpic_message_pass,
+	smp_prep_probe,
+	smp_prep_kick_cpu,
+	smp_prep_setup_cpu,
+};
+#endif /* CONFIG_SMP */
+
+/*
+ * This finds the amount of physical ram and does necessary
+ * setup for prep.  This is pretty architecture specific so
+ * this will likely stay separate from the pmac.
+ * -- Cort
+ */
+static unsigned long __init
+prep_find_end_of_memory(void)
+{
+	unsigned long total = 0;
+	extern unsigned int boot_mem_size;
+
+#ifdef CONFIG_PREP_RESIDUAL	
+	total = res->TotalMemory;
+#endif	
+
+	if (total == 0 && boot_mem_size != 0)
+		total = boot_mem_size;
+	else if (total == 0) {
+		/*
+		 * I need a way to probe the amount of memory if the residual
+		 * data doesn't contain it. -- Cort
+		 */
+		total = 0x02000000;
+		printk(KERN_INFO "Ramsize from residual data was 0"
+			 " -- defaulting to %ldM\n", total>>20);
+	}
+
+	return (total);
+}
+
+/*
+ * Setup the bat mappings we're going to load that cover
+ * the io areas.  RAM was mapped by mapin_ram().
+ * -- Cort
+ */
+static void __init
+prep_map_io(void)
+{
+	io_block_mapping(0x80000000, PREP_ISA_IO_BASE, 0x10000000, _PAGE_IO);
+	io_block_mapping(0xf0000000, PREP_ISA_MEM_BASE, 0x08000000, _PAGE_IO);
+}
+
+static void __init
+prep_init2(void)
+{
+#ifdef CONFIG_NVRAM
+	request_region(PREP_NVRAM_AS0, 0x8, "nvram");
+#endif
+	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");
+}
+
+void __init
+prep_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+#ifdef CONFIG_PREP_RESIDUAL	
+	/* make a copy of residual data */
+	if ( r3 ) {
+		memcpy((void *)res,(void *)(r3+KERNELBASE),
+			 sizeof(RESIDUAL));
+	}
+#endif
+
+	isa_io_base = PREP_ISA_IO_BASE;
+	isa_mem_base = PREP_ISA_MEM_BASE;
+	pci_dram_offset = PREP_PCI_DRAM_OFFSET;
+	ISA_DMA_THRESHOLD = 0x00ffffff;
+	DMA_MODE_READ = 0x44;
+	DMA_MODE_WRITE = 0x48;
+
+	/* figure out what kind of prep workstation we are */
+#ifdef CONFIG_PREP_RESIDUAL	
+	if ( res->ResidualLength != 0 )
+	{
+		if ( !strncmp(res->VitalProductData.PrintableModel,"IBM",3) )
+			_prep_type = _PREP_IBM;
+		else
+			_prep_type = _PREP_Motorola;
+	}
+	else /* assume motorola if no residual (netboot?) */
+#endif
+	{
+		_prep_type = _PREP_Motorola;
+	}
+
+	ppc_md.setup_arch     = prep_setup_arch;
+	ppc_md.show_percpuinfo = prep_show_percpuinfo;
+	ppc_md.show_cpuinfo   = prep_show_cpuinfo;
+	ppc_md.irq_cannonicalize = prep_irq_cannonicalize;
+	ppc_md.init_IRQ       = prep_init_IRQ;
+	/* this gets changed later on if we have an OpenPIC -- Cort */
+	ppc_md.get_irq        = prep_get_irq;
+	ppc_md.init           = prep_init2;
+
+	ppc_md.restart        = prep_restart;
+	ppc_md.power_off      = prep_power_off;
+	ppc_md.halt           = prep_halt;
+
+	ppc_md.nvram_read_val = prep_nvram_read_val;
+	ppc_md.nvram_write_val = prep_nvram_write_val;
+
+	ppc_md.time_init      = NULL;
+	if (_prep_type == _PREP_IBM) {
+		ppc_md.set_rtc_time   = mc146818_set_rtc_time;
+		ppc_md.get_rtc_time   = mc146818_get_rtc_time;
+		ppc_md.calibrate_decr = prep_calibrate_decr;
+	} else {
+		ppc_md.set_rtc_time   = mk48t59_set_rtc_time;
+		ppc_md.get_rtc_time   = mk48t59_get_rtc_time;
+		ppc_md.calibrate_decr = mk48t59_calibrate_decr;
+		ppc_md.time_init      = mk48t59_init;
+	}
+
+	ppc_md.find_end_of_memory = prep_find_end_of_memory;
+	ppc_md.setup_io_mappings = prep_map_io;
+
+#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
+	ppc_ide_md.default_irq = prep_ide_default_irq;
+	ppc_ide_md.default_io_base = prep_ide_default_io_base;
+	ppc_ide_md.ide_check_region = prep_ide_check_region;
+	ppc_ide_md.ide_request_region = prep_ide_request_region;
+	ppc_ide_md.ide_release_region = prep_ide_release_region;
+	ppc_ide_md.ide_init_hwif = prep_ide_init_hwif_ports;
+#endif
+
+#ifdef CONFIG_VT
+	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.ppc_kbd_sysrq_xlate	 = pckbd_sysrq_xlate;
+	SYSRQ_KEY = 0x54;
+#endif
+#endif
+
+#ifdef CONFIG_SMP
+	ppc_md.smp_ops		 = &prep_smp_ops;
+#endif /* CONFIG_SMP */
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/prep_time.c linux/arch/ppc/platforms/prep_time.c
--- linux.orig/arch/ppc/platforms/prep_time.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/prep_time.c	2002-08-12 22:14:20.000000000 +0000
@@ -0,0 +1,228 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ *  arch/ppc/platforms/prep_time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * Adapted for PowerPC (PReP) by Gary Thomas
+ * Modified by Cort Dougan (cort@cs.nmt.edu).
+ * Copied and modified from arch/i386/kernel/time.c
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+
+#include <asm/sections.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/machdep.h>
+#include <asm/prep_nvram.h>
+#include <asm/mk48t59.h>
+
+#include <asm/time.h>
+
+extern spinlock_t rtc_lock;
+
+/*
+ * The motorola uses the m48t18 rtc (includes DS1643) whose registers
+ * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818
+ * rtc (ds1386) which has regs at addr 0-d).  The intel gets
+ * past this because the bios emulates the mc146818.
+ *
+ * Why in the world did they have to use different clocks?
+ *
+ * Right now things are hacked to check which machine we're on then
+ * use the appropriate macro.  This is very very ugly and I should
+ * probably have a function that checks which machine we're on then
+ * does things correctly transparently or a function pointer which
+ * is setup at boot time to use the correct addresses.
+ * -- Cort
+ */
+
+/*
+ * Set the hardware clock. -- Cort
+ */
+__prep
+int mc146818_set_rtc_time(unsigned long nowtime)
+{
+	unsigned char save_control, save_freq_select;
+	struct rtc_time tm;
+
+	spin_lock(&rtc_lock);
+	to_tm(nowtime, &tm);
+
+	/* tell the clock it's being set */
+	save_control = CMOS_READ(RTC_CONTROL);
+
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	/* stop and reset prescaler */
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
+
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+        tm.tm_year = (tm.tm_year - 1900) % 100;
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BIN_TO_BCD(tm.tm_sec);
+		BIN_TO_BCD(tm.tm_min);
+		BIN_TO_BCD(tm.tm_hour);
+		BIN_TO_BCD(tm.tm_mon);
+		BIN_TO_BCD(tm.tm_mday);
+		BIN_TO_BCD(tm.tm_year);
+	}
+	CMOS_WRITE(tm.tm_sec,  RTC_SECONDS);
+	CMOS_WRITE(tm.tm_min,  RTC_MINUTES);
+	CMOS_WRITE(tm.tm_hour, RTC_HOURS);
+	CMOS_WRITE(tm.tm_mon,  RTC_MONTH);
+	CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH);
+	CMOS_WRITE(tm.tm_year, RTC_YEAR);
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control,     RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+	spin_unlock(&rtc_lock);
+
+	return 0;
+}
+
+__prep
+unsigned long mc146818_get_rtc_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int uip, i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+
+	/* Since the UIP flag is set for about 2.2 ms and the clock
+	 * is typically written with a precision of 1 jiffy, trying
+	 * to obtain a precision better than a few milliseconds is 
+	 * an illusion. Only consistency is interesting, this also
+	 * allows to use the routine for /dev/rtc without a potential
+	 * 1 second kernel busy loop triggered by any reader of /dev/rtc. 
+	 */
+
+	for ( i = 0; i<1000000; i++) {
+		uip = CMOS_READ(RTC_FREQ_SELECT);
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+		uip |= CMOS_READ(RTC_FREQ_SELECT);
+		if ((uip & RTC_UIP)==0) break;
+	}
+
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
+	    || RTC_ALWAYS_BCD)
+	{
+		BCD_TO_BIN(sec);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(hour);
+		BCD_TO_BIN(day);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(year);
+	}
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+__prep
+int mk48t59_set_rtc_time(unsigned long nowtime)
+{
+	unsigned char save_control;
+	struct rtc_time tm;
+
+	spin_lock(&rtc_lock);
+	to_tm(nowtime, &tm);
+
+	/* tell the clock it's being written */
+	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+			     (save_control | MK48T59_RTC_CA_WRITE));
+
+        tm.tm_year = (tm.tm_year - 1900) % 100;
+	BIN_TO_BCD(tm.tm_sec);
+	BIN_TO_BCD(tm.tm_min);
+	BIN_TO_BCD(tm.tm_hour);
+	BIN_TO_BCD(tm.tm_mon);
+	BIN_TO_BCD(tm.tm_mday);
+	BIN_TO_BCD(tm.tm_year);
+
+	ppc_md.nvram_write_val(MK48T59_RTC_SECONDS,      tm.tm_sec);
+	ppc_md.nvram_write_val(MK48T59_RTC_MINUTES,      tm.tm_min);
+	ppc_md.nvram_write_val(MK48T59_RTC_HOURS,        tm.tm_hour);
+	ppc_md.nvram_write_val(MK48T59_RTC_MONTH,        tm.tm_mon);
+	ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday);
+	ppc_md.nvram_write_val(MK48T59_RTC_YEAR,         tm.tm_year);
+
+	/* Turn off the write bit. */
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+	spin_unlock(&rtc_lock);
+
+	return 0;
+}
+
+__prep
+unsigned long mk48t59_get_rtc_time(void)
+{
+	unsigned char save_control;
+	unsigned int year, mon, day, hour, min, sec;
+
+	/* Simple: freeze the clock, read it and allow updates again */
+	save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA);
+	save_control &= ~MK48T59_RTC_CA_READ;
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+	/* Set the register to read the value. */
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA,
+			     (save_control | MK48T59_RTC_CA_READ));
+
+	sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS);
+	min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES);
+	hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS);
+	day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH);
+	mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH);
+	year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR);
+
+	/* Let the time values change again. */
+	ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	year = year + 1900;
+	if (year < 1970) {
+		year += 100;
+	}
+
+	return mktime(year, mon, day, hour, min, sec);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/proc_rtas.c linux/arch/ppc/platforms/proc_rtas.c
--- linux.orig/arch/ppc/platforms/proc_rtas.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/proc_rtas.c	2002-08-12 22:14:27.000000000 +0000
@@ -0,0 +1,787 @@
+/*
+ * BK Id: SCCS/s.proc_rtas.c 1.5 05/17/01 18:14:22 cort
+ */
+/*
+ *   arch/ppc/kernel/proc_rtas.c
+ *   Copyright (C) 2000 Tilmann Bitterberg
+ *   (tilmann@bitterberg.de)
+ *
+ *   RTAS (Runtime Abstraction Services) stuff
+ *   Intention is to provide a clean user interface
+ *   to use the RTAS.
+ *
+ *   TODO:
+ *   Split off a header file and maybe move it to a different
+ *   location. Write Documentation on what the /proc/rtas/ entries
+ *   actually do.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/ctype.h>
+#include <linux/time.h>
+#include <linux/string.h>
+
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/prom.h>
+#include <asm/machdep.h> /* for ppc_md */
+#include <asm/time.h>
+
+/* Token for Sensors */
+#define KEY_SWITCH		0x0001
+#define ENCLOSURE_SWITCH	0x0002
+#define THERMAL_SENSOR		0x0003
+#define LID_STATUS		0x0004
+#define POWER_SOURCE		0x0005
+#define BATTERY_VOLTAGE		0x0006
+#define BATTERY_REMAINING	0x0007
+#define BATTERY_PERCENTAGE	0x0008
+#define EPOW_SENSOR		0x0009
+#define BATTERY_CYCLESTATE	0x000a
+#define BATTERY_CHARGING	0x000b
+
+/* IBM specific sensors */
+#define IBM_SURVEILLANCE	0x2328 /* 9000 */
+#define IBM_FANRPM		0x2329 /* 9001 */
+#define IBM_VOLTAGE		0x232a /* 9002 */
+#define IBM_DRCONNECTOR		0x232b /* 9003 */
+#define IBM_POWERSUPPLY		0x232c /* 9004 */
+#define IBM_INTQUEUE		0x232d /* 9005 */
+
+/* Status return values */
+#define SENSOR_CRITICAL_HIGH	13
+#define SENSOR_WARNING_HIGH	12
+#define SENSOR_NORMAL		11
+#define SENSOR_WARNING_LOW	10
+#define SENSOR_CRITICAL_LOW	 9
+#define SENSOR_SUCCESS		 0
+#define SENSOR_HW_ERROR		-1
+#define SENSOR_BUSY		-2
+#define SENSOR_NOT_EXIST	-3
+#define SENSOR_DR_ENTITY	-9000
+
+/* Location Codes */
+#define LOC_SCSI_DEV_ADDR	'A'
+#define LOC_SCSI_DEV_LOC	'B'
+#define LOC_CPU			'C'
+#define LOC_DISKETTE		'D'
+#define LOC_ETHERNET		'E'
+#define LOC_FAN			'F'
+#define LOC_GRAPHICS		'G'
+/* reserved / not used		'H' */
+#define LOC_IO_ADAPTER		'I'
+/* reserved / not used		'J' */
+#define LOC_KEYBOARD		'K'
+#define LOC_LCD			'L'
+#define LOC_MEMORY		'M'
+#define LOC_NV_MEMORY		'N'
+#define LOC_MOUSE		'O'
+#define LOC_PLANAR		'P'
+#define LOC_OTHER_IO		'Q'
+#define LOC_PARALLEL		'R'
+#define LOC_SERIAL		'S'
+#define LOC_DEAD_RING		'T'
+#define LOC_RACKMOUNTED		'U' /* for _u_nit is rack mounted */
+#define LOC_VOLTAGE		'V'
+#define LOC_SWITCH_ADAPTER	'W'
+#define LOC_OTHER		'X'
+#define LOC_FIRMWARE		'Y'
+#define LOC_SCSI		'Z'
+
+/* Tokens for indicators */
+#define TONE_FREQUENCY		0x0001 /* 0 - 1000 (HZ)*/
+#define TONE_VOLUME		0x0002 /* 0 - 100 (%) */
+#define SYSTEM_POWER_STATE	0x0003 
+#define WARNING_LIGHT		0x0004
+#define DISK_ACTIVITY_LIGHT	0x0005
+#define HEX_DISPLAY_UNIT	0x0006
+#define BATTERY_WARNING_TIME	0x0007
+#define CONDITION_CYCLE_REQUEST	0x0008
+#define SURVEILLANCE_INDICATOR	0x2328 /* 9000 */
+#define DR_ACTION		0x2329 /* 9001 */
+#define DR_INDICATOR		0x232a /* 9002 */
+/* 9003 - 9004: Vendor specific */
+#define GLOBAL_INTERRUPT_QUEUE	0x232d /* 9005 */
+/* 9006 - 9999: Vendor specific */
+
+/* other */
+#define MAX_SENSORS		 17  /* I only know of 17 sensors */    
+#define MAX_LINELENGTH          256
+#define SENSOR_PREFIX		"ibm,sensor-"
+#define cel_to_fahr(x)		((x*9/5)+32)
+
+
+/* Globals */
+static struct proc_dir_entry *proc_rtas;
+static struct rtas_sensors sensors;
+static struct device_node *rtas;
+static unsigned long power_on_time = 0; /* Save the time the user set */
+static char progress_led[MAX_LINELENGTH];
+
+static unsigned long rtas_tone_frequency = 1000;
+static unsigned long rtas_tone_volume = 0;
+
+/* ****************STRUCTS******************************************* */
+struct individual_sensor {
+	unsigned int token;
+	unsigned int quant;
+};
+
+struct rtas_sensors {
+        struct individual_sensor sensor[MAX_SENSORS];
+	unsigned int quant;
+};
+
+/* ****************************************************************** */
+/* Declarations */
+static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
+		int count, int *eof, void *data);
+static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, 
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, 
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+
+static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos);
+static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos);
+
+struct file_operations ppc_rtas_poweron_operations = {
+	read:		ppc_rtas_poweron_read,
+	write:		ppc_rtas_poweron_write
+};
+struct file_operations ppc_rtas_progress_operations = {
+	read:		ppc_rtas_progress_read,
+	write:		ppc_rtas_progress_write
+};
+
+struct file_operations ppc_rtas_clock_operations = {
+	read:		ppc_rtas_clock_read,
+	write:		ppc_rtas_clock_write
+};
+
+struct file_operations ppc_rtas_tone_freq_operations = {
+	read:		ppc_rtas_tone_freq_read,
+	write:		ppc_rtas_tone_freq_write
+};
+struct file_operations ppc_rtas_tone_volume_operations = {
+	read:		ppc_rtas_tone_volume_read,
+	write:		ppc_rtas_tone_volume_write
+};
+
+int ppc_rtas_find_all_sensors (void);
+int ppc_rtas_process_sensor(struct individual_sensor s, int state, 
+		int error, char * buf);
+char * ppc_rtas_process_error(int error);
+int get_location_code(struct individual_sensor s, char * buf);
+int check_location_string (char *c, char * buf);
+int check_location (char *c, int idx, char * buf);
+
+/* ****************************************************************** */
+/* MAIN                                                               */
+/* ****************************************************************** */
+void proc_rtas_init(void)
+{
+	struct proc_dir_entry *entry;
+
+	rtas = find_devices("rtas");
+	if ((rtas == 0) || (_machine != _MACH_chrp)) {
+		return;
+	}
+	
+	proc_rtas = proc_mkdir("rtas", 0);
+	if (proc_rtas == 0)
+		return;
+
+	/* /proc/rtas entries */
+
+	entry = create_proc_entry("progress", S_IRUGO|S_IWUSR, proc_rtas);
+	if (entry) entry->proc_fops = &ppc_rtas_progress_operations;
+
+	entry = create_proc_entry("clock", S_IRUGO|S_IWUSR, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_clock_operations;
+
+	entry = create_proc_entry("poweron", S_IWUSR|S_IRUGO, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_poweron_operations;
+
+	create_proc_read_entry("sensors", S_IRUGO, proc_rtas, 
+			ppc_rtas_sensor_read, NULL);
+	
+	entry = create_proc_entry("frequency", S_IWUSR|S_IRUGO, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_tone_freq_operations;
+
+	entry = create_proc_entry("volume", S_IWUSR|S_IRUGO, proc_rtas); 
+	if (entry) entry->proc_fops = &ppc_rtas_tone_volume_operations;
+}
+
+/* ****************************************************************** */
+/* POWER-ON-TIME                                                      */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_poweron_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	struct rtc_time tm;
+	unsigned long nowtime;
+	char *dest;
+	int error;
+
+	nowtime = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_poweron_write: Invalid time\n");
+		return count;
+	}
+	power_on_time = nowtime; /* save the time */
+
+	to_tm(nowtime, &tm);
+
+	error = call_rtas("set-time-for-power-on", 7, 1, NULL, 
+			tm.tm_year, tm.tm_mon, tm.tm_mday, 
+			tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting poweron time returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_poweron_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n;
+	if (power_on_time == 0)
+		n = sprintf(buf, "Power on time not set\n");
+	else
+		n = sprintf(buf, "%lu\n", power_on_time);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* ****************************************************************** */
+/* PROGRESS                                                           */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_progress_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long hex;
+
+	strcpy(progress_led, buf); /* save the string */
+	/* Lets see if the user passed hexdigits */
+	hex = simple_strtoul(buf, NULL, 10);
+	
+	ppc_md.progress ((char *)buf, hex);
+	return count;
+
+	/* clear the line */ /* ppc_md.progress("                   ", 0xffff);*/
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_progress_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n = 0;
+	if (progress_led != NULL)
+		n = sprintf (buf, "%s\n", progress_led);
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* ****************************************************************** */
+/* CLOCK                                                              */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_clock_write(struct file * file, const char * buf, 
+		size_t count, loff_t *ppos)
+{
+	struct rtc_time tm;
+	unsigned long nowtime;
+	char *dest;
+	int error;
+
+	nowtime = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_clock_write: Invalid time\n");
+		return count;
+	}
+
+	to_tm(nowtime, &tm);
+	error = call_rtas("set-time-of-day", 7, 1, NULL, 
+			tm.tm_year, tm.tm_mon, tm.tm_mday, 
+			tm.tm_hour, tm.tm_min, tm.tm_sec, 0);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting the clock returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_clock_read(struct file * file, char * buf, 
+		size_t count, loff_t *ppos)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	unsigned long *ret = kmalloc(4*8, GFP_KERNEL);
+	int n, error;
+
+	error = call_rtas("get-time-of-day", 0, 8, ret);
+	
+	year = ret[0]; mon  = ret[1]; day  = ret[2];
+	hour = ret[3]; min  = ret[4]; sec  = ret[5];
+
+	if (error != 0){
+		printk(KERN_WARNING "error: reading the clock returned: %s\n", 
+				ppc_rtas_process_error(error));
+		n = sprintf (buf, "0");
+	} else { 
+		n = sprintf (buf, "%lu\n", mktime(year, mon, day, hour, min, sec));
+	}
+	kfree(ret);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+
+/* ****************************************************************** */
+/* SENSOR STUFF                                                       */
+/* ****************************************************************** */
+static int ppc_rtas_sensor_read(char * buf, char ** start, off_t off,
+		int count, int *eof, void *data)
+{
+	int i,j,n;
+	unsigned long ret;
+	int state, error;
+	char buffer[MAX_LINELENGTH*MAX_SENSORS]; /* May not be enough */
+
+	if (count < 0)
+		return -EINVAL;
+
+	n  = sprintf ( buffer  , "RTAS (RunTime Abstraction Services) Sensor Information\n");
+	n += sprintf ( buffer+n, "Sensor\t\tValue\t\tCondition\tLocation\n");
+	n += sprintf ( buffer+n, "********************************************************\n");
+
+	if (ppc_rtas_find_all_sensors() != 0) {
+		n += sprintf ( buffer+n, "\nNo sensors are available\n");
+		goto return_string;
+	}
+
+	for (i=0; i<sensors.quant; i++) {
+		j = sensors.sensor[i].quant;
+		/* A sensor may have multiple instances */
+		while (j >= 0) {
+			error =	call_rtas("get-sensor-state", 2, 2, &ret, 
+				  sensors.sensor[i].token, sensors.sensor[i].quant-j);
+			state = (int) ret;
+			n += ppc_rtas_process_sensor(sensors.sensor[i], state, error, buffer+n );
+			n += sprintf (buffer+n, "\n");
+			j--;
+		} /* while */
+	} /* for */
+
+return_string:
+	if (off >= strlen(buffer)) {
+		*eof = 1;
+		return 0;
+	}
+	if (n > strlen(buffer) - off)
+		n = strlen(buffer) - off;
+	if (n > count)
+		n = count;
+	else
+		*eof = 1;
+	memcpy(buf, buffer + off, n);
+	*start = buf;
+	return n;
+}
+
+/* ****************************************************************** */
+
+int ppc_rtas_find_all_sensors (void)
+{
+	unsigned long *utmp;
+	int len, i, j;
+
+	utmp = (unsigned long *) get_property(rtas, "rtas-sensors", &len);
+	if (utmp == NULL) {
+		printk (KERN_ERR "error: could not get rtas-sensors\n");
+		return 1;
+	}
+
+	sensors.quant = len / 8;      /* int + int */
+
+	for (i=0, j=0; j<sensors.quant; i+=2, j++) {
+		sensors.sensor[j].token = utmp[i];
+		sensors.sensor[j].quant = utmp[i+1];
+	}
+	return 0;
+}
+
+/* ****************************************************************** */
+/*
+ * Builds a string of what rtas returned
+ */
+char * ppc_rtas_process_error(int error)
+{
+	switch (error) {
+		case SENSOR_CRITICAL_HIGH:
+			return "(critical high)";
+		case SENSOR_WARNING_HIGH:
+			return "(warning high)";
+		case SENSOR_NORMAL:
+			return "(normal)";
+		case SENSOR_WARNING_LOW:
+			return "(warning low)";
+		case SENSOR_CRITICAL_LOW:
+			return "(critical low)";
+		case SENSOR_SUCCESS:
+			return "(read ok)";
+		case SENSOR_HW_ERROR:
+			return "(hardware error)";
+		case SENSOR_BUSY:
+			return "(busy)";
+		case SENSOR_NOT_EXIST:
+			return "(non existant)";
+		case SENSOR_DR_ENTITY:
+			return "(dr entity removed)";
+		default:
+			return "(UNKNOWN)";
+	}
+}
+
+/* ****************************************************************** */
+/*
+ * Builds a string out of what the sensor said
+ */
+
+int ppc_rtas_process_sensor(struct individual_sensor s, int state, 
+		int error, char * buf) 
+{
+	/* Defined return vales */
+	const char * key_switch[]        = { "Off\t", "Normal\t", "Secure\t", "Mainenance" };
+	const char * enclosure_switch[]  = { "Closed", "Open" };
+	const char * lid_status[]        = { " ", "Open", "Closed" };
+	const char * power_source[]      = { "AC\t", "Battery", "AC & Battery" };
+	const char * battery_remaining[] = { "Very Low", "Low", "Mid", "High" };
+	const char * epow_sensor[]       = { 
+		"EPOW Reset", "Cooling warning", "Power warning",
+		"System shutdown", "System halt", "EPOW main enclosure",
+		"EPOW power off" };
+	const char * battery_cyclestate[]  = { "None", "In progress", "Requested" };
+	const char * battery_charging[]    = { "Charging", "Discharching", "No current flow" };
+	const char * ibm_drconnector[]     = { "Empty", "Present" };
+	const char * ibm_intqueue[]        = { "Disabled", "Enabled" };
+
+	int have_strings = 0;
+	int temperature = 0;
+	int unknown = 0;
+	int n = 0;
+
+	/* What kind of sensor do we have here? */
+	switch (s.token) {
+		case KEY_SWITCH:
+			n += sprintf(buf+n, "Key switch:\t");
+			n += sprintf(buf+n, "%s\t", key_switch[state]);
+			have_strings = 1;
+			break;
+		case ENCLOSURE_SWITCH:
+			n += sprintf(buf+n, "Enclosure switch:\t");
+			n += sprintf(buf+n, "%s\t", enclosure_switch[state]);
+			have_strings = 1;
+			break;
+		case THERMAL_SENSOR:
+			n += sprintf(buf+n, "Temp. (°C/°F):\t");
+			temperature = 1;
+			break;
+		case LID_STATUS:
+			n += sprintf(buf+n, "Lid status:\t");
+			n += sprintf(buf+n, "%s\t", lid_status[state]);
+			have_strings = 1;
+			break;
+		case POWER_SOURCE:
+			n += sprintf(buf+n, "Power source:\t");
+			n += sprintf(buf+n, "%s\t", power_source[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_VOLTAGE:
+			n += sprintf(buf+n, "Battery voltage:\t");
+			break;
+		case BATTERY_REMAINING:
+			n += sprintf(buf+n, "Battery remaining:\t");
+			n += sprintf(buf+n, "%s\t", battery_remaining[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_PERCENTAGE:
+			n += sprintf(buf+n, "Battery percentage:\t");
+			break;
+		case EPOW_SENSOR:
+			n += sprintf(buf+n, "EPOW Sensor:\t");
+			n += sprintf(buf+n, "%s\t", epow_sensor[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_CYCLESTATE:
+			n += sprintf(buf+n, "Battery cyclestate:\t");
+			n += sprintf(buf+n, "%s\t", battery_cyclestate[state]);
+			have_strings = 1;
+			break;
+		case BATTERY_CHARGING:
+			n += sprintf(buf+n, "Battery Charging:\t");
+			n += sprintf(buf+n, "%s\t", battery_charging[state]);
+			have_strings = 1;
+			break;
+		case IBM_SURVEILLANCE:
+			n += sprintf(buf+n, "Surveillance:\t");
+			break;
+		case IBM_FANRPM:
+			n += sprintf(buf+n, "Fan (rpm):\t");
+			break;
+		case IBM_VOLTAGE:
+			n += sprintf(buf+n, "Voltage (mv):\t");
+			break;
+		case IBM_DRCONNECTOR:
+			n += sprintf(buf+n, "DR connector:\t");
+			n += sprintf(buf+n, "%s\t", ibm_drconnector[state]);
+			have_strings = 1;
+			break;
+		case IBM_POWERSUPPLY:
+			n += sprintf(buf+n, "Powersupply:\t");
+			break;
+		case IBM_INTQUEUE:
+			n += sprintf(buf+n, "Interrupt queue:\t");
+			n += sprintf(buf+n, "%s\t", ibm_intqueue[state]);
+			have_strings = 1;
+			break;
+		default:
+			n += sprintf(buf+n,  "Unkown sensor (type %d), ignoring it\n",
+					s.token);
+			unknown = 1;
+			have_strings = 1;
+			break;
+	}
+	if (have_strings == 0) {
+		if (temperature) {
+			n += sprintf(buf+n, "%4d /%4d\t", state, cel_to_fahr(state));
+		} else
+			n += sprintf(buf+n, "%10d\t", state);
+	}
+	if (unknown == 0) {
+		n += sprintf ( buf+n, "%s\t", ppc_rtas_process_error(error));
+		n += get_location_code(s, buf+n);
+	}
+	return n;
+}
+
+/* ****************************************************************** */
+
+int check_location (char *c, int idx, char * buf)
+{
+	int n = 0;
+
+	switch (*(c+idx)) {
+		case LOC_PLANAR:
+			n += sprintf ( buf, "Planar #%c", *(c+idx+1));
+			break;
+		case LOC_CPU:
+			n += sprintf ( buf, "CPU #%c", *(c+idx+1));
+			break;
+		case LOC_FAN:
+			n += sprintf ( buf, "Fan #%c", *(c+idx+1));
+			break;
+		case LOC_RACKMOUNTED:
+			n += sprintf ( buf, "Rack #%c", *(c+idx+1));
+			break;
+		case LOC_VOLTAGE:
+			n += sprintf ( buf, "Voltage #%c", *(c+idx+1));
+			break;
+		case LOC_LCD:
+			n += sprintf ( buf, "LCD #%c", *(c+idx+1));
+			break;
+		case '.':
+			n += sprintf ( buf, "- %c", *(c+idx+1));
+		default:
+			n += sprintf ( buf, "Unknown location");
+			break;
+	}
+	return n;
+}
+
+
+/* ****************************************************************** */
+/* 
+ * Format: 
+ * ${LETTER}${NUMBER}[[-/]${LETTER}${NUMBER} [ ... ] ]
+ * the '.' may be an abbrevation
+ */
+int check_location_string (char *c, char *buf)
+{
+	int n=0,i=0;
+
+	while (c[i]) {
+		if (isalpha(c[i]) || c[i] == '.') {
+			 n += check_location(c, i, buf+n);
+		}
+		else if (c[i] == '/' || c[i] == '-')
+			n += sprintf(buf+n, " at ");
+		i++;
+	}
+	return n;
+}
+
+
+/* ****************************************************************** */
+
+int get_location_code(struct individual_sensor s, char * buffer)
+{
+	char rstr[512], tmp[10], tmp2[10];
+	int n=0, i=0, llen, len;
+	/* char *buf = kmalloc(MAX_LINELENGTH, GFP_KERNEL); */
+	char *ret;
+
+	static int pos = 0; /* remember position where buffer was */
+
+	/* construct the sensor number like 0003 */
+	/* fill with zeros */
+	n = sprintf(tmp, "%d", s.token);
+	len = strlen(tmp);
+	while (strlen(tmp) < 4)
+		n += sprintf (tmp+n, "0");
+	
+	/* invert the string */
+	while (tmp[i]) {
+		if (i<len)
+			tmp2[4-len+i] = tmp[i];
+		else
+			tmp2[3-i] = tmp[i];
+		i++;
+	}
+	tmp2[4] = '\0';
+
+	sprintf (rstr, SENSOR_PREFIX"%s", tmp2);
+
+	ret = (char *) get_property(rtas, rstr, &llen);
+
+	n=0;
+	if (ret[0] == '\0')
+		n += sprintf ( buffer+n, "--- ");/* does not have a location */
+	else {
+		char t[50];
+		ret += pos;
+
+		n += check_location_string(ret, buffer + n);
+		n += sprintf ( buffer+n, " ");
+		/* see how many characters we have printed */
+		sprintf ( t, "%s ", ret);
+
+		pos += strlen(t);
+		if (pos >= llen) pos=0;
+	}
+	return n;
+}
+/* ****************************************************************** */
+/* INDICATORS - Tone Frequency                                        */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_freq_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long freq;
+	char *dest;
+	int error;
+	freq = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_tone_freq_write: Invalid tone freqency\n");
+		return count;
+	}
+	if (freq < 0) freq = 0;
+	rtas_tone_frequency = freq; /* save it for later */
+	error = call_rtas("set-indicator", 3, 1, NULL,
+			TONE_FREQUENCY, 0, freq);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting tone frequency returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_freq_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n;
+	n = sprintf(buf, "%lu\n", rtas_tone_frequency);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
+/* ****************************************************************** */
+/* INDICATORS - Tone Volume                                           */
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_volume_write(struct file * file, const char * buf,
+		size_t count, loff_t *ppos)
+{
+	unsigned long volume;
+	char *dest;
+	int error;
+	volume = simple_strtoul(buf, &dest, 10);
+	if (*dest != '\0' && *dest != '\n') {
+		printk("ppc_rtas_tone_volume_write: Invalid tone volume\n");
+		return count;
+	}
+	if (volume < 0) volume = 0;
+	if (volume > 100) volume = 100;
+	
+        rtas_tone_volume = volume; /* save it for later */
+	error = call_rtas("set-indicator", 3, 1, NULL,
+			TONE_VOLUME, 0, volume);
+	if (error != 0)
+		printk(KERN_WARNING "error: setting tone volume returned: %s\n", 
+				ppc_rtas_process_error(error));
+	return count;
+}
+/* ****************************************************************** */
+static ssize_t ppc_rtas_tone_volume_read(struct file * file, char * buf,
+		size_t count, loff_t *ppos)
+{
+	int n;
+	n = sprintf(buf, "%lu\n", rtas_tone_volume);
+
+	if (*ppos >= strlen(buf))
+		return 0;
+	if (n > strlen(buf) - *ppos)
+		n = strlen(buf) - *ppos;
+	if (n > count)
+		n = count;
+	*ppos += n;
+	return n;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/residual.c linux/arch/ppc/platforms/residual.c
--- linux.orig/arch/ppc/platforms/residual.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/residual.c	2002-08-12 22:14:07.000000000 +0000
@@ -0,0 +1,913 @@
+/*
+ * BK Id: SCCS/s.residual.c 1.15 02/05/02 18:08:35 trini
+ */
+/*
+ * Code to deal with the PReP residual data.
+ *
+ * Written by: Cort Dougan (cort@cs.nmt.edu)
+ * Improved _greatly_ and rewritten by Gabriel Paubert (paubert@iram.es)
+ *
+ *  This file is based on the following documentation:
+ *
+ *	IBM Power Personal Systems Architecture
+ *	Residual Data
+ * 	Document Number: PPS-AR-FW0001
+ *
+ *  This file is subject to the terms and conditions of the GNU General Public
+ *  License.  See the file COPYING in the main directory of this archive
+ *  for more details.
+ *
+ */
+
+#include <linux/string.h>
+#include <asm/residual.h>
+#include <asm/pnp.h>
+#include <asm/byteorder.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/slab.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/ioport.h>
+#include <linux/pci.h>
+#include <linux/ide.h>
+
+#include <asm/sections.h>
+#include <asm/mmu.h>
+#include <asm/processor.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/ide.h>
+
+
+unsigned char __res[sizeof(RESIDUAL)] __prepdata = {0,};
+RESIDUAL *res = (RESIDUAL *)&__res;
+
+char * PnP_BASE_TYPES[] __initdata = {
+  "Reserved",
+  "MassStorageDevice",
+  "NetworkInterfaceController",
+  "DisplayController",
+  "MultimediaController",
+  "MemoryController",
+  "BridgeController",
+  "CommunicationsDevice",
+  "SystemPeripheral",
+  "InputDevice",
+  "ServiceProcessor"
+  };
+
+/* Device Sub Type Codes */
+
+unsigned char * PnP_SUB_TYPES[] __initdata = {
+  "\001\000SCSIController",
+  "\001\001IDEController",
+  "\001\002FloppyController",
+  "\001\003IPIController",
+  "\001\200OtherMassStorageController",
+  "\002\000EthernetController",
+  "\002\001TokenRingController",
+  "\002\002FDDIController",
+  "\002\0x80OtherNetworkController",
+  "\003\000VGAController",
+  "\003\001SVGAController",
+  "\003\002XGAController",
+  "\003\200OtherDisplayController",
+  "\004\000VideoController",
+  "\004\001AudioController",
+  "\004\200OtherMultimediaController",
+  "\005\000RAM",
+  "\005\001FLASH",
+  "\005\200OtherMemoryDevice",
+  "\006\000HostProcessorBridge",
+  "\006\001ISABridge",
+  "\006\002EISABridge",
+  "\006\003MicroChannelBridge",
+  "\006\004PCIBridge",
+  "\006\005PCMCIABridge",
+  "\006\006VMEBridge",
+  "\006\200OtherBridgeDevice",
+  "\007\000RS232Device",
+  "\007\001ATCompatibleParallelPort",
+  "\007\200OtherCommunicationsDevice",
+  "\010\000ProgrammableInterruptController",
+  "\010\001DMAController",
+  "\010\002SystemTimer",
+  "\010\003RealTimeClock",
+  "\010\004L2Cache",
+  "\010\005NVRAM",
+  "\010\006PowerManagement",
+  "\010\007CMOS",
+  "\010\010OperatorPanel",
+  "\010\011ServiceProcessorClass1",
+  "\010\012ServiceProcessorClass2",
+  "\010\013ServiceProcessorClass3",
+  "\010\014GraphicAssist",
+  "\010\017SystemPlanar",
+  "\010\200OtherSystemPeripheral",
+  "\011\000KeyboardController",
+  "\011\001Digitizer",
+  "\011\002MouseController",
+  "\011\003TabletController",
+  "\011\0x80OtherInputController",
+  "\012\000GeneralMemoryController",
+  NULL
+};
+
+/* Device Interface Type Codes */
+
+unsigned char * PnP_INTERFACES[] __initdata = {
+  "\000\000\000General",
+  "\001\000\000GeneralSCSI",
+  "\001\001\000GeneralIDE",
+  "\001\001\001ATACompatible",
+
+  "\001\002\000GeneralFloppy",
+  "\001\002\001Compatible765",
+  "\001\002\002NS398_Floppy",         /* NS Super I/O wired to use index
+                                         register at port 398 and data
+                                         register at port 399               */
+  "\001\002\003NS26E_Floppy",         /* Ports 26E and 26F                  */
+  "\001\002\004NS15C_Floppy",         /* Ports 15C and 15D                  */
+  "\001\002\005NS2E_Floppy",          /* Ports 2E and 2F                    */
+  "\001\002\006CHRP_Floppy",          /* CHRP Floppy in PR*P system         */
+
+  "\001\003\000GeneralIPI",
+  
+  "\002\000\000GeneralEther",
+  "\002\001\000GeneralToken",
+  "\002\002\000GeneralFDDI",
+  
+  "\003\000\000GeneralVGA",
+  "\003\001\000GeneralSVGA",
+  "\003\002\000GeneralXGA",
+  
+  "\004\000\000GeneralVideo",
+  "\004\001\000GeneralAudio",
+  "\004\001\001CS4232Audio",            /* CS 4232 Plug 'n Play Configured    */
+
+  "\005\000\000GeneralRAM",
+  /* This one is obviously wrong ! */
+  "\005\000\000PCIMemoryController",    /* PCI Config Method                  */
+  "\005\000\001RS6KMemoryController",   /* RS6K Config Method                 */
+  "\005\001\000GeneralFLASH",
+  
+  "\006\000\000GeneralHostBridge",
+  "\006\001\000GeneralISABridge",
+  "\006\002\000GeneralEISABridge",
+  "\006\003\000GeneralMCABridge",
+  /* GeneralPCIBridge = 0, */
+  "\006\004\000PCIBridgeDirect",
+  "\006\004\001PCIBridgeIndirect",
+  "\006\004\002PCIBridgeRS6K",
+  "\006\005\000GeneralPCMCIABridge",
+  "\006\006\000GeneralVMEBridge",
+  
+  "\007\000\000GeneralRS232",
+  "\007\000\001COMx",
+  "\007\000\002Compatible16450",
+  "\007\000\003Compatible16550",
+  "\007\000\004NS398SerPort",         /* NS Super I/O wired to use index
+                                         register at port 398 and data
+                                         register at port 399               */
+  "\007\000\005NS26ESerPort",         /* Ports 26E and 26F                  */
+  "\007\000\006NS15CSerPort",         /* Ports 15C and 15D                  */
+  "\007\000\007NS2ESerPort",          /* Ports 2E and 2F                    */
+
+  "\007\001\000GeneralParPort",
+  "\007\001\001LPTx",
+  "\007\001\002NS398ParPort",         /* NS Super I/O wired to use index
+                                         register at port 398 and data
+                                         register at port 399               */
+  "\007\001\003NS26EParPort",         /* Ports 26E and 26F                  */
+  "\007\001\004NS15CParPort",         /* Ports 15C and 15D                  */
+  "\007\001\005NS2EParPort",          /* Ports 2E and 2F                    */
+  
+  "\010\000\000GeneralPIC",
+  "\010\000\001ISA_PIC",
+  "\010\000\002EISA_PIC",
+  "\010\000\003MPIC",
+  "\010\000\004RS6K_PIC",
+
+  "\010\001\000GeneralDMA",
+  "\010\001\001ISA_DMA",
+  "\010\001\002EISA_DMA",
+
+  "\010\002\000GeneralTimer",
+  "\010\002\001ISA_Timer",
+  "\010\002\002EISA_Timer",
+  "\010\003\000GeneralRTC",
+  "\010\003\001ISA_RTC",
+  
+  "\010\004\001StoreThruOnly",
+  "\010\004\002StoreInEnabled",
+  "\010\004\003RS6KL2Cache",
+
+  "\010\005\000IndirectNVRAM",        /* Indirectly addressed               */
+  "\010\005\001DirectNVRAM",          /* Memory Mapped                      */
+  "\010\005\002IndirectNVRAM24",      /* Indirectly addressed - 24 bit      */
+
+  "\010\006\000GeneralPowerManagement",
+  "\010\006\001EPOWPowerManagement",
+  "\010\006\002PowerControl",         // d1378
+  
+  "\010\007\000GeneralCMOS",
+
+  "\010\010\000GeneralOPPanel",
+  "\010\010\001HarddiskLight",
+  "\010\010\002CDROMLight",
+  "\010\010\003PowerLight",
+  "\010\010\004KeyLock",
+  "\010\010\005ANDisplay",            /* AlphaNumeric Display               */
+  "\010\010\006SystemStatusLED",      /* 3 digit 7 segment LED              */
+  "\010\010\007CHRP_SystemStatusLED", /* CHRP LEDs in PR*P system           */
+
+  "\010\011\000GeneralServiceProcessor",
+  "\010\012\000GeneralServiceProcessor",
+  "\010\013\000GeneralServiceProcessor",
+  
+  "\010\014\001TransferData",
+  "\010\014\002IGMC32",
+  "\010\014\003IGMC64",
+  
+  "\010\017\000GeneralSystemPlanar",   /* 10/5/95                            */
+  NULL
+  };
+
+static const unsigned char __init *PnP_SUB_TYPE_STR(unsigned char BaseType, 
+					     unsigned char SubType) {
+	unsigned char ** s=PnP_SUB_TYPES;
+	while (*s && !((*s)[0]==BaseType 
+		       && (*s)[1]==SubType)) s++;
+	if (*s) return *s+2;
+	else return("Unknown !");
+};
+
+static const unsigned char __init *PnP_INTERFACE_STR(unsigned char BaseType, 
+					      unsigned char SubType,
+					      unsigned char Interface) {
+	unsigned char ** s=PnP_INTERFACES;
+	while (*s && !((*s)[0]==BaseType 
+		       && (*s)[1]==SubType 
+		       && (*s)[2]==Interface)) s++;
+	if (*s) return *s+3;
+	else return NULL;
+};
+
+static void __init printsmallvendor(PnP_TAG_PACKET *pkt, int size) {
+	int i, c;
+	char decomp[4];
+#define p pkt->S14_Pack.S14_Data.S14_PPCPack
+	switch(p.Type) {
+	case 1:
+	  /* Decompress first 3 chars */
+	  c = *(unsigned short *)p.PPCData;
+	  decomp[0]='A'-1+((c>>10)&0x1F);
+	  decomp[1]='A'-1+((c>>5)&0x1F);
+	  decomp[2]='A'-1+(c&0x1F);
+	  decomp[3]=0;
+	  printk("    Chip identification: %s%4.4X\n",
+		 decomp, ld_le16((unsigned short *)(p.PPCData+2)));
+	  break;
+	default:
+	  printk("    Small vendor item type 0x%2.2x, data (hex): ",
+		 p.Type);
+	  for(i=0; i<size-2; i++) printk("%2.2x ", p.PPCData[i]);
+	  printk("\n");
+	  break;
+	}
+#undef p
+}
+
+static void __init printsmallpacket(PnP_TAG_PACKET * pkt, int size) {
+	static const unsigned char * intlevel[] = {"high", "low"};
+	static const unsigned char * intsense[] = {"edge", "level"};
+
+	switch (tag_small_item_name(pkt->S1_Pack.Tag)) {
+	case PnPVersion:
+	  printk("    PnPversion 0x%x.%x\n", 
+		 pkt->S1_Pack.Version[0], /* How to interpret version ? */
+		 pkt->S1_Pack.Version[1]);
+	  break;
+//	case Logicaldevice:
+	  break;
+//	case CompatibleDevice:
+	  break;
+	case IRQFormat:
+#define p pkt->S4_Pack
+	  printk("    IRQ Mask 0x%4.4x, %s %s sensitive\n", 
+		 ld_le16((unsigned short *)p.IRQMask),
+		 intlevel[(size>3) ? !(p.IRQInfo&0x05) : 0],
+		 intsense[(size>3) ? !(p.IRQInfo&0x03) : 0]);
+#undef p
+	  break;
+	case DMAFormat:
+#define p pkt->S5_Pack
+	  printk("    DMA channel mask 0x%2.2x, info 0x%2.2x\n",
+		 p.DMAMask, p.DMAInfo);
+#undef p
+	  break;
+	case StartDepFunc:
+	  printk("Start dependent function:\n");
+	  break;
+	case EndDepFunc:
+	  printk("End dependent function\n");
+	  break;
+	case IOPort:
+#define p pkt->S8_Pack
+	  printk("    Variable (%d decoded bits) I/O port\n"
+		 "      from 0x%4.4x to 0x%4.4x, alignment %d, %d ports\n",
+		 p.IOInfo&ISAAddr16bit?16:10,
+		 ld_le16((unsigned short *)p.RangeMin),
+ 		 ld_le16((unsigned short *)p.RangeMax),
+		 p.IOAlign, p.IONum); 
+#undef p
+	  break;
+	case FixedIOPort:
+#define p pkt->S9_Pack
+	  printk("    Fixed (10 decoded bits) I/O port from %3.3x to %3.3x\n",
+		 (p.Range[1]<<8)|p.Range[0],
+		 ((p.Range[1]<<8)|p.Range[0])+p.IONum-1);
+#undef p		 
+	  break;
+	case Res1:
+	case Res2:
+	case Res3:
+	  printk("    Undefined packet type %d!\n", 
+		 tag_small_item_name(pkt->S1_Pack.Tag));
+	  break;
+	case SmallVendorItem:
+	  printsmallvendor(pkt,size);
+	  break;
+	default:
+	  printk("    Type 0x2.2x%d, size=%d\n", 
+		 pkt->S1_Pack.Tag, size);    
+	  break;
+	}
+}
+
+static void __init printlargevendor(PnP_TAG_PACKET * pkt, int size) {
+	static const unsigned char * addrtype[] = {"I/O", "Memory", "System"};
+	static const unsigned char * inttype[] = {"8259", "MPIC", "RS6k BUID %d"};
+	static const unsigned char * convtype[] = {"Bus Memory", "Bus I/O", "DMA"};
+	static const unsigned char * transtype[] = {"direct", "mapped", "direct-store segment"};
+	static const unsigned char * L2type[] = {"WriteThru", "CopyBack"};
+	static const unsigned char * L2assoc[] = {"DirectMapped", "2-way set"};
+
+	int i;
+	char tmpstr[30], *t;
+#define p pkt->L4_Pack.L4_Data.L4_PPCPack
+	switch(p.Type) {
+	case 2:
+	  printk("    %d K %s %s L2 cache, %d/%d bytes line/sector size\n",
+		 ld_le32((unsigned int *)p.PPCData),
+		 L2type[p.PPCData[10]-1],
+		 L2assoc[p.PPCData[4]-1],
+		 ld_le16((unsigned short *)p.PPCData+3),
+		 ld_le16((unsigned short *)p.PPCData+4));
+	  break;
+	case 3:
+	  printk("    PCI Bridge parameters\n"
+		 "      ConfigBaseAddress %0x\n"
+		 "      ConfigBaseData %0x\n"
+		 "      Bus number %d\n",
+		 ld_le32((unsigned int *)p.PPCData),
+		 ld_le32((unsigned int *)(p.PPCData+8)),
+		 p.PPCData[16]);
+	  for(i=20; i<size-4; i+=12) {
+	  	int j, first;
+	  	if(p.PPCData[i]) printk("      PCI Slot %d", p.PPCData[i]);
+		else printk ("      Integrated PCI device");
+		for(j=0, first=1, t=tmpstr; j<4; j++) {
+			int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
+			if(line!=0xffff){
+			        if(first) first=0; else *t++='/';
+				*t++='A'+j;
+			}
+		}
+		*t='\0';
+		printk(" DevFunc 0x%x interrupt line(s) %s routed to",
+		       p.PPCData[i+1],tmpstr);
+		sprintf(tmpstr,
+			inttype[p.PPCData[i+2]-1],
+			p.PPCData[i+3]);
+		printk(" %s line(s) ",
+		       tmpstr);
+		for(j=0, first=1, t=tmpstr; j<4; j++) {
+			int line=ld_le16((unsigned short *)(p.PPCData+i+4)+j);
+			if(line!=0xffff){
+				if(first) first=0; else *t++='/';
+				t+=sprintf(t,"%d(%c)",
+					   line&0x7fff,
+					   line&0x8000?'E':'L');
+			}
+		}
+		printk("%s\n",tmpstr);
+	  }
+	  break;
+	case 5:
+	  printk("    Bridge address translation, %s decoding:\n"
+		 "      Processor  Bus        Size       Conversion Translation\n"
+		 "      0x%8.8x 0x%8.8x 0x%8.8x %s %s\n",
+		 p.PPCData[0]&1 ? "positive" : "subtractive",
+		 ld_le32((unsigned int *)p.PPCData+1),
+		 ld_le32((unsigned int *)p.PPCData+3),
+		 ld_le32((unsigned int *)p.PPCData+5),
+		 convtype[p.PPCData[2]-1],
+		 transtype[p.PPCData[1]-1]);
+	  break;
+	case 6:
+	  printk("    Bus speed %d Hz, %d slot(s)\n",
+		 ld_le32((unsigned int *)p.PPCData),
+		 p.PPCData[4]);
+	  break;
+	case 7:
+	  printk("    SCSI buses: %d, id(s):", p.PPCData[0]);
+	  for(i=1; i<=p.PPCData[0]; i++) 
+	    printk(" %d%c", p.PPCData[i], i==p.PPCData[0] ? '\n' : ',');
+	  break;
+	case 9:
+	  printk("    %s address (%d bits), at 0x%x size 0x%x bytes\n",
+		 addrtype[p.PPCData[0]-1],
+		 p.PPCData[1],
+		 ld_le32((unsigned int *)(p.PPCData+4)),
+		 ld_le32((unsigned int *)(p.PPCData+12)));
+	  break;
+	case 10:
+	  sprintf(tmpstr,
+		  inttype[p.PPCData[0]-1],
+		  p.PPCData[1]);
+
+	  printk("    ISA interrupts routed to %s\n"
+		 "      lines", 
+		 tmpstr);
+	  for(i=0; i<16; i++) {
+	  	int line=ld_le16((unsigned short *)p.PPCData+i+1);
+		if (line!=0xffff) printk(" %d(IRQ%d)", line, i); 
+	  }
+	  printk("\n");
+	  break;
+	default:
+	  printk("    Large vendor item type 0x%2.2x\n      Data (hex):",
+		 p.Type);
+	  for(i=0; i<size-4; i++) printk(" %2.2x", p.PPCData[i]);
+	  printk("\n");
+#undef p
+	}
+}
+
+static void __init printlargepacket(PnP_TAG_PACKET * pkt, int size) {
+	switch (tag_large_item_name(pkt->S1_Pack.Tag)) {
+	case LargeVendorItem:
+	  printlargevendor(pkt, size);
+	  break;
+	default:
+	  printk("    Type 0x2.2x%d, size=%d\n", 
+		 pkt->S1_Pack.Tag, size);    
+	  break;
+	}
+}
+static void __init printpackets(PnP_TAG_PACKET * pkt, const char * cat) {
+	if (pkt->S1_Pack.Tag== END_TAG) {
+		printk("  No packets describing %s resources.\n", cat);
+		return;
+	}
+	printk(  "  Packets describing %s resources:\n",cat);
+	do {
+		int size;
+		if (tag_type(pkt->S1_Pack.Tag)) {
+		  	size= 3 +
+			  pkt->L1_Pack.Count0 + 
+			  pkt->L1_Pack.Count1*256;
+			printlargepacket(pkt, size);
+		} else {
+			size=tag_small_count(pkt->S1_Pack.Tag)+1;
+			printsmallpacket(pkt, size);
+		}
+		(unsigned char *) pkt+=size;
+	} while (pkt->S1_Pack.Tag != END_TAG);
+}
+
+void __init print_residual_device_info(void)
+{
+	int i;
+	PPC_DEVICE *dev;
+#define did dev->DeviceId
+	
+	/* make sure we have residual data first */
+	if ( res->ResidualLength == 0 )
+		return;
+	
+	printk("Residual: %ld devices\n", res->ActualNumDevices);
+	for ( i = 0;
+	      i < res->ActualNumDevices ;
+	      i++)
+	{
+	  	char decomp[4], sn[20];
+		const char * s;
+		dev = &res->Devices[i];
+		s = PnP_INTERFACE_STR(did.BaseType, did.SubType, 
+				      did.Interface);
+		if(!s) {
+			sprintf(sn, "interface %d", did.Interface);
+			s=sn;
+		}
+		if ( did.BusId & PCIDEVICE ) 
+		  printk("PCI Device, Bus %d, DevFunc 0x%x:",
+			 dev->BusAccess.PCIAccess.BusNumber,
+			 dev->BusAccess.PCIAccess.DevFuncNumber);
+	       	if ( did.BusId & PNPISADEVICE ) printk("PNPISA Device:");
+		if ( did.BusId & ISADEVICE ) 
+		  printk("ISA Device, Slot %d, LogicalDev %d:",
+			 dev->BusAccess.ISAAccess.SlotNumber,
+			 dev->BusAccess.ISAAccess.LogicalDevNumber);
+		if ( did.BusId & EISADEVICE ) printk("EISA Device:");
+		if ( did.BusId & PROCESSORDEVICE ) 
+		  printk("ProcBus Device, Bus %d, BUID %d: ",
+			 dev->BusAccess.ProcBusAccess.BusNumber,
+			 dev->BusAccess.ProcBusAccess.BUID);
+		if ( did.BusId & PCMCIADEVICE ) printk("PCMCIA ");
+		if ( did.BusId & VMEDEVICE ) printk("VME ");
+		if ( did.BusId & MCADEVICE ) printk("MCA ");
+		if ( did.BusId & MXDEVICE ) printk("MX ");
+		/* Decompress first 3 chars */
+		decomp[0]='A'-1+((did.DevId>>26)&0x1F);
+		decomp[1]='A'-1+((did.DevId>>21)&0x1F);
+		decomp[2]='A'-1+((did.DevId>>16)&0x1F);
+		decomp[3]=0;
+		printk(" %s%4.4lX, %s, %s, %s\n", 
+		       decomp, did.DevId&0xffff,
+		       PnP_BASE_TYPES[did.BaseType],
+		       PnP_SUB_TYPE_STR(did.BaseType,did.SubType),
+		       s);
+		if ( dev->AllocatedOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->AllocatedOffset],
+				      "allocated");
+		if ( dev->PossibleOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->PossibleOffset],
+				      "possible");
+		if ( dev->CompatibleOffset )
+			printpackets( (union _PnP_TAG_PACKET *)
+				      &res->DevicePnPHeap[dev->CompatibleOffset],
+				      "compatible");
+	}
+}
+
+
+#if 0
+static void __init printVPD(void) {
+#define vpd res->VitalProductData
+	int ps=vpd.PageSize, i, j;
+	static const char* Usage[]={
+	  "FirmwareStack",  "FirmwareHeap",  "FirmwareCode", "BootImage",
+	  "Free", "Unpopulated", "ISAAddr", "PCIConfig",
+	  "IOMemory", "SystemIO", "SystemRegs", "PCIAddr", 
+	  "UnPopSystemRom", "SystemROM", "ResumeBlock", "Other" 
+	};
+	static const unsigned char *FWMan[]={
+	  "IBM", "Motorola", "FirmWorks", "Bull"
+	};
+	static const unsigned char *FWFlags[]={
+	  "Conventional", "OpenFirmware", "Diagnostics", "LowDebug",
+	  "MultiBoot", "LowClient", "Hex41", "FAT", 
+	  "ISO9660", "SCSI_ID_Override", "Tape_Boot", "FW_Boot_Path"
+	};
+	static const unsigned char *ESM[]={
+	  "Port92", "PCIConfigA8", "FF001030", "????????"
+	};
+	static const unsigned char *SIOM[]={
+	  "Port850", "????????", "PCIConfigA8", "????????"
+	};
+
+	printk("Model: %s\n",vpd.PrintableModel);
+	printk("Serial: %s\n", vpd.Serial);
+	printk("FirmwareSupplier: %s\n", FWMan[vpd.FirmwareSupplier]);
+	printk("FirmwareFlags:");
+	for(j=0; j<12; j++) {
+	  	if (vpd.FirmwareSupports & (1<<j)) {
+			printk(" %s%c", FWFlags[j], 
+			       vpd.FirmwareSupports&(-2<<j) ? ',' : '\n');
+		}
+	}
+	printk("NVRamSize: %ld\n", vpd.NvramSize);
+	printk("SIMMslots: %ld\n", vpd.NumSIMMSlots);
+	printk("EndianSwitchMethod: %s\n", 
+	       ESM[vpd.EndianSwitchMethod>2 ? 2 : vpd.EndianSwitchMethod]);
+	printk("SpreadIOMethod: %s\n", 
+	       SIOM[vpd.SpreadIOMethod>3 ? 3 : vpd.SpreadIOMethod]);
+	printk("Processor/Bus frequencies (Hz): %ld/%ld\n",
+	       vpd.ProcessorHz, vpd.ProcessorBusHz);
+	printk("Time Base Divisor: %ld\n", vpd.TimeBaseDivisor);
+	printk("WordWidth, PageSize: %ld, %d\n", vpd.WordWidth, ps);
+	printk("Cache sector size, Lock granularity: %ld, %ld\n",
+	       vpd.CoherenceBlockSize, vpd.GranuleSize);
+	for (i=0; i<res->ActualNumMemSegs; i++) {
+		int mask=res->Segs[i].Usage, first, j;
+		printk("%8.8lx-%8.8lx ", 
+		       res->Segs[i].BasePage*ps,
+		       (res->Segs[i].PageCount+res->Segs[i].BasePage)*ps-1);
+		for(j=15, first=1; j>=0; j--) {
+			if (mask&(1<<j)) {
+				if (first) first=0;
+				else printk(", ");
+				printk("%s", Usage[j]);
+			}
+		}
+		printk("\n");
+	}
+}
+
+/*
+ * Spit out some info about residual data
+ */
+void print_residual_device_info(void)
+{
+	int i;
+	union _PnP_TAG_PACKET *pkt;
+	PPC_DEVICE *dev;
+#define did dev->DeviceId
+	
+	/* make sure we have residual data first */
+	if ( res->ResidualLength == 0 )
+		return;
+	printk("Residual: %ld devices\n", res->ActualNumDevices);
+	for ( i = 0;
+	      i < res->ActualNumDevices ;
+	      i++)
+	{
+		dev = &res->Devices[i];
+		/*
+		 * pci devices
+		 */
+		if ( did.BusId & PCIDEVICE )
+		{
+			printk("PCI Device:");
+			/* unknown vendor */
+			if ( !strncmp( "Unknown", pci_strvendor(did.DevId>>16), 7) )
+				printk(" id %08lx types %d/%d", did.DevId,
+				       did.BaseType, did.SubType);
+			/* known vendor */
+			else
+				printk(" %s %s",
+				       pci_strvendor(did.DevId>>16),
+				       pci_strdev(did.DevId>>16,
+						  did.DevId&0xffff)
+					);
+			
+			if ( did.BusId & PNPISADEVICE )
+			{
+				printk(" pnp:");
+				/* get pnp info on the device */
+				pkt = (union _PnP_TAG_PACKET *)
+					&res->DevicePnPHeap[dev->AllocatedOffset];
+				for (; pkt->S1_Pack.Tag != DF_END_TAG;
+				     pkt++ )
+				{
+					if ( (pkt->S1_Pack.Tag == S4_Packet) ||
+					     (pkt->S1_Pack.Tag == S4_Packet_flags) )
+						printk(" irq %02x%02x",
+						       pkt->S4_Pack.IRQMask[0],
+						       pkt->S4_Pack.IRQMask[1]);
+				}
+			}
+			printk("\n");
+			continue;
+		}
+		/*
+		 * isa devices
+		 */
+		if ( did.BusId & ISADEVICE )
+		{
+			printk("ISA Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}		
+		/*
+		 * eisa devices
+		 */
+		if ( did.BusId & EISADEVICE )
+		{
+			printk("EISA Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}		
+		/*
+		 * proc bus devices
+		 */
+		if ( did.BusId & PROCESSORDEVICE )
+		{
+			printk("ProcBus Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}
+		/*
+		 * pcmcia devices
+		 */
+		if ( did.BusId & PCMCIADEVICE )
+		{
+			printk("PCMCIA Device: basetype: %d subtype: %d",
+			       did.BaseType, did.SubType);
+			printk("\n");
+			continue;
+		}		
+		printk("Unknown bus access device: busid %lx\n",
+		       did.BusId);
+	}
+}
+#endif	
+
+/* Returns the device index in the residual data, 
+   any of the search items may be set as -1 for wildcard,
+   DevID number field (second halfword) is big endian ! 
+
+   Examples:
+   - search for the Interrupt controller (8259 type), 2 methods:
+     1) i8259 = residual_find_device(~0, 
+                                     NULL, 
+				     SystemPeripheral, 
+				     ProgrammableInterruptController, 
+				     ISA_PIC, 
+				     0);
+     2) i8259 = residual_find_device(~0, "PNP0000", -1, -1, -1, 0) 
+
+   - search for the first two serial devices, whatever their type)
+     iserial1 = residual_find_device(~0,NULL,
+                                     CommunicationsDevice,
+				     RS232Device,
+				     -1, 0)
+     iserial2 = residual_find_device(~0,NULL,
+                                     CommunicationsDevice,
+				     RS232Device,
+				     -1, 1)
+   - but search for typical COM1 and COM2 is not easy due to the
+     fact that the interface may be anything and the name "PNP0500" or 
+     "PNP0501". Quite bad. 
+
+*/
+
+/* devid are easier to uncompress than to compress, so to minimize bloat
+in this rarely used area we unencode and compare */
+
+/* in residual data number is big endian in the device table and
+little endian in the heap, so we use two parameters to avoid writing
+two very similar functions */
+
+static int __init same_DevID(unsigned short vendor,
+	       unsigned short Number,
+	       char * str) 
+{
+	static unsigned const char hexdigit[]="0123456789ABCDEF";
+	if (strlen(str)!=7) return 0;
+	if ( ( ((vendor>>10)&0x1f)+'A'-1 == str[0])  &&
+	     ( ((vendor>>5)&0x1f)+'A'-1 == str[1])   &&
+	     ( (vendor&0x1f)+'A'-1 == str[2])        &&
+	     (hexdigit[(Number>>12)&0x0f] == str[3]) &&
+	     (hexdigit[(Number>>8)&0x0f] == str[4])  &&
+	     (hexdigit[(Number>>4)&0x0f] == str[5])  &&
+	     (hexdigit[Number&0x0f] == str[6]) ) return 1;
+	return 0;
+}
+
+PPC_DEVICE __init *residual_find_device(unsigned long BusMask,
+			 unsigned char * DevID,
+			 int BaseType,
+			 int SubType,
+			 int Interface,
+			 int n)
+{
+	int i;
+	if ( !res->ResidualLength ) return NULL;
+	for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+		if ( (Dev.BusId&BusMask)                                  &&
+		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
+		     (SubType==-1 || Dev.SubType==SubType)                &&
+		     (Interface==-1 || Dev.Interface==Interface)          &&
+		     (DevID==NULL || same_DevID((Dev.DevId>>16)&0xffff,
+						Dev.DevId&0xffff, DevID)) &&
+		     !(n--) ) return res->Devices+i;
+#undef Dev
+	}
+	return 0;
+}
+
+PPC_DEVICE __init *residual_find_device_id(unsigned long BusMask,
+			 unsigned short DevID,
+			 int BaseType,
+			 int SubType,
+			 int Interface,
+			 int n)
+{
+	int i;
+	if ( !res->ResidualLength ) return NULL;
+	for (i=0; i<res->ActualNumDevices; i++) {
+#define Dev res->Devices[i].DeviceId
+		if ( (Dev.BusId&BusMask)                                  &&
+		     (BaseType==-1 || Dev.BaseType==BaseType)             &&
+		     (SubType==-1 || Dev.SubType==SubType)                &&
+		     (Interface==-1 || Dev.Interface==Interface)          &&
+		     (DevID==0xffff || (Dev.DevId&0xffff) == DevID)	  &&
+		     !(n--) ) return res->Devices+i;
+#undef Dev
+	}
+	return 0;
+}
+
+PnP_TAG_PACKET *PnP_find_packet(unsigned char *p,
+				unsigned packet_tag,
+				int n)
+{
+	unsigned mask, masked_tag, size;
+	if(!p) return 0;
+	if (tag_type(packet_tag)) mask=0xff; else mask=0xF8;
+	masked_tag = packet_tag&mask;
+	for(; *p != END_TAG; p+=size) {
+		if ((*p & mask) == masked_tag && !(n--)) 
+			return (PnP_TAG_PACKET *) p;
+		if (tag_type(*p))
+			size=ld_le16((unsigned short *)(p+1))+3;
+		else 
+			size=tag_small_count(*p)+1;
+	}
+	return 0; /* not found */
+}
+
+PnP_TAG_PACKET __init *PnP_find_small_vendor_packet(unsigned char *p,
+					     unsigned packet_type,
+					     int n)
+{
+	int next=0;
+	while (p) {
+		p = (unsigned char *) PnP_find_packet(p, 0x70, next);
+		if (p && p[1]==packet_type && !(n--)) 
+			return (PnP_TAG_PACKET *) p;
+		next = 1;
+	};
+	return 0; /* not found */
+}
+
+PnP_TAG_PACKET __init *PnP_find_large_vendor_packet(unsigned char *p,
+					   unsigned packet_type,
+					   int n)
+{
+	int next=0;
+	while (p) {
+		p = (unsigned char *) PnP_find_packet(p, 0x84, next);
+		if (p && p[3]==packet_type && !(n--)) 
+			return (PnP_TAG_PACKET *) p;
+		next = 1;
+	};
+	return 0; /* not found */
+}
+
+#ifdef CONFIG_PROC_PREPRESIDUAL
+static int proc_prep_residual_read(char * buf, char ** start, off_t off,
+		int count, int *eof, void *data)
+{
+	int n;
+
+	n = res->ResidualLength - off;
+	if (n < 0) {
+		*eof = 1;
+		n = 0;
+	}
+	else {
+		if (n > count)
+			n = count;
+		else
+			*eof = 1;
+
+		memcpy(buf, (char *)res + off, n);
+		*start = buf;
+	}
+
+	return n;
+}
+
+void __init
+proc_prep_residual_init(void)
+{
+	if (res->ResidualLength)
+		create_proc_read_entry("residual", S_IRUGO, NULL,
+					proc_prep_residual_read, NULL);
+}
+
+__initcall(proc_prep_residual_init);
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/rpxclassic.h linux/arch/ppc/platforms/rpxclassic.h
--- linux.orig/arch/ppc/platforms/rpxclassic.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/rpxclassic.h	2002-08-12 22:14:06.000000000 +0000
@@ -0,0 +1,104 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the RPCG RPX-Classic board.  Copied from the RPX-Lite stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPX_DEFS
+#define __MACH_RPX_DEFS
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define PCI_ISA_IO_ADDR		((unsigned)0x80000000)
+#define PCI_ISA_IO_SIZE		((uint)(512 * 1024 * 1024))
+#define PCI_ISA_MEM_ADDR	((unsigned)0xc0000000)
+#define PCI_ISA_MEM_SIZE	((uint)(512 * 1024 * 1024))
+#define RPX_CSR_ADDR		((uint)0xfa400000)
+#define RPX_CSR_SIZE		((uint)(4 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCI_CSR_ADDR		((uint)0x80000000)
+#define PCI_CSR_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0xe0000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#define PCMCIA_IO_ADDR		((uint)0xe4000000)
+#define PCMCIA_IO_SIZE		((uint)(4 * 1024))
+#define PCMCIA_ATTRB_ADDR	((uint)0xe8000000)
+#define PCMCIA_ATTRB_SIZE	((uint)(4 * 1024))
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ETHEN		((uint)0x80000000)
+#define BCSR0_ETHLPBK		((uint)0x40000000)
+#define BCSR0_COLTESTDIS	((uint)0x20000000)
+#define BCSR0_FULLDPLXDIS	((uint)0x10000000)
+#define BCSR0_ENFLSHSEL		((uint)0x04000000)
+#define BCSR0_FLASH_SEL		((uint)0x02000000)
+#define BCSR0_ENMONXCVR		((uint)0x01000000)
+
+#define BCSR0_PCMCIAVOLT	((uint)0x000f0000)	/* CLLF */
+#define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)	/* CLLF */
+#define BCSR0_PCMCIA5VOLT	((uint)0x00060000)	/* CLLF */
+
+#define BCSR1_IPB5SEL           ((uint)0x00100000)
+#define BCSR1_PCVCTL4           ((uint)0x00080000)
+#define BCSR1_PCVCTL5           ((uint)0x00040000)
+#define BCSR1_PCVCTL6           ((uint)0x00020000)
+#define BCSR1_PCVCTL7           ((uint)0x00010000)
+
+#define BCSR2_EN232XCVR		((uint)0x00008000)
+#define BCSR2_QSPACESEL		((uint)0x00004000)
+#define BCSR2_FETHLEDMODE	((uint)0x00000800)	/* CLLF */
+
+#if defined(CONFIG_HTDMSOUND)
+#include <platforms/rpxhiox.h>
+#endif
+
+/* define IO_BASE for pcmcia, CLLF only */
+#if !defined(CONFIG_PCI)
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+/* for pcmcia sandisk */
+#ifdef CONFIG_IDE
+#define MAX_HWIFS 1
+#define ide_request_irq(irq,hand,flg,dev,id)    request_8xxirq((irq),(hand),(flg),(dev),(id))
+#endif
+#endif
+
+/* Interrupt level assignments.
+*/
+#define FEC_INTERRUPT	SIU_LEVEL1	/* FEC interrupt */
+
+#endif /* !__ASSEMBLY__ */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/rpxhiox.h linux/arch/ppc/platforms/rpxhiox.h
--- linux.orig/arch/ppc/platforms/rpxhiox.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/rpxhiox.h	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,45 @@
+/*
+ * BK Id: SCCS/s.rpxhiox.h 1.3 05/17/01 18:14:25 cort
+ */
+
+/*
+ * The Embedded Planet HIOX expansion card definitions.
+ * There were a few different versions of these cards, but only
+ * the one that escaped real production is defined here.
+ *
+ * Copyright (c) 2000 Dan Malek (dmalek@jlc.net)
+ */
+#ifndef __MACH_RPX_HIOX_DEFS
+#define __MACH_RPX_HIOX_DEFS
+
+#define HIOX_CSR_ADDR		((uint)0xfac00000)
+#define HIOX_CSR_SIZE		((uint)(4 * 1024))
+#define HIOX_CSR0_ADDR		HIOX_CSR_ADDR
+#define HIOX_CSR4_ADDR		((uint)0xfac00004)
+
+#define HIOX_CSR0_DEFAULT	((uint)0x380f3c00)
+#define HIOX_CSR0_ENSCC2	((uint)0x80000000)
+#define HIOX_CSR0_ENSMC2	((uint)0x04000000)
+#define HIOX_CSR0_ENVDOCLK	((uint)0x02000000)
+#define HIOX_CSR0_VDORST_HL	((uint)0x01000000)
+#define HIOX_CSR0_RS232SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SCC3SEL	((uint)0x0000c000)
+#define HIOX_CSR0_SMC1SEL	((uint)0x00008000)
+#define HIOX_CSR0_SCC1SEL	((uint)0x00004000)
+#define HIOX_CSR0_ENTOUCH	((uint)0x00000080)
+#define HIOX_CSR0_PDOWN100	((uint)0x00000060)
+#define HIOX_CSR0_PDOWN10	((uint)0x00000040)
+#define HIOX_CSR0_PDOWN1	((uint)0x00000020)
+#define HIOX_CSR0_TSELSPI	((uint)0x00000010)
+#define HIOX_CSR0_TIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_DEFAULT	((uint)0x00000000)
+#define HIOX_CSR4_ENTIRQ2	((uint)0x20000000)
+#define HIOX_CSR4_ENTIRQ3	((uint)0x10000000)
+#define HIOX_CSR4_ENAUDIO	((uint)0x00000080)
+#define HIOX_CSR4_RSTAUDIO	((uint)0x00000040)	/* 0 == reset */
+#define HIOX_CSR4_AUDCLKHI	((uint)0x00000020)
+#define HIOX_CSR4_AUDSPISEL	((uint)0x00000010)
+#define HIOX_CSR4_AUDIRQSTAT	((uint)0x00000008)
+#define HIOX_CSR4_AUDCLKSEL	((uint)0x00000007)
+
+#endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/rpxlite.h linux/arch/ppc/platforms/rpxlite.h
--- linux.orig/arch/ppc/platforms/rpxlite.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/rpxlite.h	2002-08-12 22:14:03.000000000 +0000
@@ -0,0 +1,84 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+
+/*
+ * A collection of structures, addresses, and values associated with
+ * the RPCG RPX-Lite board.  Copied from the MBX stuff.
+ *
+ * Copyright (c) 1998 Dan Malek (dmalek@jlc.net)
+ */
+#ifdef __KERNEL__
+#ifndef __MACH_RPX_DEFS
+#define __MACH_RPX_DEFS
+
+#include <linux/config.h>
+
+#ifndef __ASSEMBLY__
+/* A Board Information structure that is given to a program when
+ * prom starts it up.
+ */
+typedef struct bd_info {
+	unsigned int	bi_memstart;	/* Memory start address */
+	unsigned int	bi_memsize;	/* Memory (end) size in bytes */
+	unsigned int	bi_intfreq;	/* Internal Freq, in Hz */
+	unsigned int	bi_busfreq;	/* Bus Freq, in Hz */
+	unsigned char	bi_enetaddr[6];
+	unsigned int	bi_baudrate;
+} bd_t;
+
+extern bd_t m8xx_board_info;
+
+/* Memory map is configured by the PROM startup.
+ * We just map a few things we need.  The CSR is actually 4 byte-wide
+ * registers that can be accessed as 8-, 16-, or 32-bit values.
+ */
+#define RPX_CSR_ADDR		((uint)0xfa400000)
+#define RPX_CSR_SIZE		((uint)(4 * 1024))
+#define IMAP_ADDR		((uint)0xfa200000)
+#define IMAP_SIZE		((uint)(64 * 1024))
+#define PCMCIA_MEM_ADDR		((uint)0x04000000)
+#define PCMCIA_MEM_SIZE		((uint)(64 * 1024))
+#define PCMCIA_IO_ADDR		((uint)0x04400000)
+#define PCMCIA_IO_SIZE		((uint)(4 * 1024))
+
+/* Things of interest in the CSR.
+*/
+#define BCSR0_ETHEN		((uint)0x80000000)
+#define BCSR0_ETHLPBK		((uint)0x40000000)
+#define BCSR0_COLTESTDIS	((uint)0x20000000)
+#define BCSR0_FULLDPLXDIS	((uint)0x10000000)
+#define BCSR0_LEDOFF		((uint)0x08000000)
+#define BCSR0_USBDISABLE	((uint)0x04000000)
+#define BCSR0_USBHISPEED	((uint)0x02000000)
+#define BCSR0_USBPWREN		((uint)0x01000000)
+#define BCSR0_PCMCIAVOLT	((uint)0x000f0000)
+#define BCSR0_PCMCIA3VOLT	((uint)0x000a0000)
+#define BCSR0_PCMCIA5VOLT	((uint)0x00060000)
+
+#define BCSR1_IPB5SEL          ((uint)0x00100000)
+#define BCSR1_PCVCTL4          ((uint)0x00080000)
+#define BCSR1_PCVCTL5          ((uint)0x00040000)
+#define BCSR1_PCVCTL6          ((uint)0x00020000)
+#define BCSR1_PCVCTL7          ((uint)0x00010000)
+
+#if defined(CONFIG_HTDMSOUND)
+#include <platforms/rpxhiox.h>
+#endif
+#endif /* !__ASSEMBLY__ */
+
+/* define IO_BASE for pcmcia */
+#define _IO_BASE 0x80000000
+#define _IO_BASE_SIZE 0x1000
+
+#ifdef CONFIG_IDE
+#define MAX_HWIFS 1
+#define ide_request_irq(irq,hand,flg,dev,id)    request_8xxirq((irq),(hand),(flg),(dev),(id))
+#endif
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/sleep.S linux/arch/ppc/platforms/sleep.S
--- linux.orig/arch/ppc/platforms/sleep.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/sleep.S	2002-08-12 22:14:04.000000000 +0000
@@ -0,0 +1,452 @@
+/*
+ * BK Id: %F% %I% %G% %U% %#%
+ */
+/*
+ * This file contains sleep low-level functions for PowerBook G3.
+ *    Copyright (C) 1999 Benjamin Herrenschmidt (benh@kernel.crashing.org)
+ *    and Paul Mackerras (paulus@samba.org).
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+#include <asm/cputable.h>
+#include <asm/ppc_asm.h>
+
+#define MAGIC	0x4c617273	/* 'Lars' */
+
+/*
+ * Structure for storing CPU registers on the stack.
+ */
+#define SL_SP		0
+#define SL_PC		4
+#define SL_MSR		8
+#define SL_SDR1		0xc
+#define SL_SPRG0	0x10	/* 4 sprg's */
+#define SL_DBAT0	0x20
+#define SL_IBAT0	0x28
+#define SL_DBAT1	0x30
+#define SL_IBAT1	0x38
+#define SL_DBAT2	0x40
+#define SL_IBAT2	0x48
+#define SL_DBAT3	0x50
+#define SL_IBAT3	0x58
+#define SL_TB		0x60
+#define SL_HID0		0x68
+#define SL_HID1		0x6c
+#define SL_MSSCR0	0x70
+#define SL_MSSSR0	0x74
+#define SL_ICTRL	0x78
+#define SL_LDSTCR	0x7c
+#define SL_LDSTDB	0x80
+#define SL_R2		0x84
+#define SL_CR		0x88
+#define SL_R12		0x8c	/* r12 to r31 */
+#define SL_SIZE		(SL_R12 + 80)
+
+	.text
+	.align	5
+
+/* This gets called by via-pmu.c late during the sleep process.
+ * The PMU was already send the sleep command and will shut us down
+ * soon. We need to save all that is needed and setup the wakeup
+ * vector that will be called by the ROM on wakeup
+ */
+_GLOBAL(low_sleep_handler)
+	mflr	r0
+	stw	r0,4(r1)
+	stwu	r1,-SL_SIZE(r1)
+	mfcr	r0
+	stw	r0,SL_CR(r1)
+	stw	r2,SL_R2(r1)
+	stmw	r12,SL_R12(r1)
+
+	/* Save MSR & SDR1 */
+	mfmsr	r4
+	stw	r4,SL_MSR(r1)
+	mfsdr1	r4
+	stw	r4,SL_SDR1(r1)
+
+	/* Get a stable timebase and save it */
+1:	mftbu	r4
+	stw	r4,SL_TB(r1)
+	mftb	r5
+	stw	r5,SL_TB+4(r1)
+	mftbu	r3
+	cmpw	r3,r4
+	bne	1b
+	
+	/* Save SPRGs */
+	mfsprg	r4,0
+	stw	r4,SL_SPRG0(r1)
+	mfsprg	r4,1
+	stw	r4,SL_SPRG0+4(r1)
+	mfsprg	r4,2
+	stw	r4,SL_SPRG0+8(r1)
+	mfsprg	r4,3
+	stw	r4,SL_SPRG0+12(r1)
+
+	/* Save BATs */
+	mfdbatu	r4,0
+	stw	r4,SL_DBAT0(r1)
+	mfdbatl	r4,0
+	stw	r4,SL_DBAT0+4(r1)
+	mfdbatu	r4,1
+	stw	r4,SL_DBAT1(r1)
+	mfdbatl	r4,1
+	stw	r4,SL_DBAT1+4(r1)
+	mfdbatu	r4,2
+	stw	r4,SL_DBAT2(r1)
+	mfdbatl	r4,2
+	stw	r4,SL_DBAT2+4(r1)
+	mfdbatu	r4,3
+	stw	r4,SL_DBAT3(r1)
+	mfdbatl	r4,3
+	stw	r4,SL_DBAT3+4(r1)
+	mfibatu	r4,0
+	stw	r4,SL_IBAT0(r1)
+	mfibatl	r4,0
+	stw	r4,SL_IBAT0+4(r1)
+	mfibatu	r4,1
+	stw	r4,SL_IBAT1(r1)
+	mfibatl	r4,1
+	stw	r4,SL_IBAT1+4(r1)
+	mfibatu	r4,2
+	stw	r4,SL_IBAT2(r1)
+	mfibatl	r4,2
+	stw	r4,SL_IBAT2+4(r1)
+	mfibatu	r4,3
+	stw	r4,SL_IBAT3(r1)
+	mfibatl	r4,3
+	stw	r4,SL_IBAT3+4(r1)
+
+	/* Save HID0 */
+	mfspr	r4,HID0
+	stw	r4,SL_HID0(r1)
+
+	/* Save 7400/7410/7450 specific registers */
+	mfspr	r3,PVR
+	srwi	r3,r3,16
+	cmpli	cr0,r3,0x8000
+	cmpli	cr1,r3,0x000c
+	cmpli	cr2,r3,0x800c
+	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
+	bne	1f
+	mfspr	r4,SPRN_MSSCR0
+	stw	r4,SL_MSSCR0(r1)
+	mfspr	r4,SPRN_MSSSR0
+	stw	r4,SL_MSSSR0(r1)
+	/* Save 7450 specific registers */
+	beq	cr1,1f
+	mfspr	r4,HID1
+	stw	r4,SL_HID1(r1)
+	mfspr	r4,SPRN_ICTRL
+	stw	r4,SL_ICTRL(r1)
+	mfspr	r4,SPRN_LDSTCR
+	stw	r4,SL_LDSTCR(r1)
+	mfspr	r4,SPRN_LDSTDB
+	stw	r4,SL_LDSTDB(r1)
+1:
+	/* The ROM can wake us up via 2 different vectors:
+	 *  - On wallstreet & lombard, we must write a magic
+	 *    value 'Lars' at address 4 and a pointer to a
+	 *    memory location containing the PC to resume from
+	 *    at address 0.
+	 *  - On Core99, we must store the wakeup vector at
+	 *    address 0x80 and eventually it's parameters
+	 *    at address 0x84. I've have some trouble with those
+	 *    parameters however and I no longer use them.
+	 */
+	lis	r5,grackle_wake_up@ha
+	addi	r5,r5,grackle_wake_up@l
+	tophys(r5,r5)
+	stw	r5,SL_PC(r1)
+	lis	r4,KERNELBASE@h
+	tophys(r5,r1)
+	addi	r5,r5,SL_PC
+	lis	r6,MAGIC@ha
+	addi	r6,r6,MAGIC@l
+	stw	r5,0(r4)
+	stw	r6,4(r4)
+	/* Setup stuffs at 0x80-0x84 for Core99 */
+	lis	r3,core99_wake_up@ha
+	addi	r3,r3,core99_wake_up@l
+	tophys(r3,r3)
+	stw	r3,0x80(r4)
+	stw	r5,0x84(r4)
+	/* Store a pointer to our backup storage into
+	 * a kernel global
+	 */
+	lis r3,sleep_storage@ha
+	addi r3,r3,sleep_storage@l
+	stw r5,0(r3)
+
+	BEGIN_FTR_SECTION
+	DSSALL
+	sync
+	END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
+
+/*
+ * Flush the L1 data cache by reading the first 128kB of RAM
+ * and then flushing the same area with the dcbf instruction.
+ * The L2 cache has already been disabled.
+ */
+	li	r4,0x1000	/* 128kB / 32B */
+	mtctr	r4
+	lis	r4,KERNELBASE@h
+1:
+	lwz	r0,0(r4)
+	addi	r4,r4,0x0020	/* Go to start of next cache line */
+	bdnz	1b
+	sync
+	
+	li	r4,0x1000	/* 128kB / 32B */
+	mtctr	r4
+	lis	r4,KERNELBASE@h
+1:
+	dcbf	r0,r4
+	addi	r4,r4,0x0020	/* Go to start of next cache line */
+	bdnz	1b
+	sync
+
+/*
+ * Set the HID0 and MSR for sleep.
+ */
+	mfspr	r2,HID0
+	rlwinm	r2,r2,0,10,7	/* clear doze, nap */
+	oris	r2,r2,HID0_SLEEP@h
+	sync
+	mtspr	HID0,r2
+	sync
+
+/* This loop puts us back to sleep in case we have a spurrious
+ * wakeup so that the host bridge properly stays asleep. The
+ * CPU will be turned off, either after a known time (about 1
+ * second) on wallstreet & lombard, or as soon as the CPU enters
+ * SLEEP mode on core99
+ */
+	mfmsr	r2
+	oris	r2,r2,MSR_POW@h
+1:	sync
+	mtmsr	r2
+	isync
+	b	1b
+
+/* 
+ * Here is the resume code.
+ */
+
+
+/*
+ * Core99 machines resume here
+ * r4 has the physical address of SL_PC(sp) (unused)
+ */
+_GLOBAL(core99_wake_up)
+	/* Make sure HID0 no longer contains any sleep bit */
+	mfspr	r3,HID0
+	rlwinm	r3,r3,0,11,7		/* clear SLEEP, NAP, DOZE bits */
+	mtspr	HID0,r3
+	sync
+	isync
+
+	/* Won't that cause problems on CPU that doesn't support it ? */
+	lis	r3, 0
+	mtspr	SPRN_MMCR0, r3
+	
+	/* sanitize MSR */
+	mfmsr	r3
+	ori	r3,r3,MSR_EE|MSR_IP
+	xori	r3,r3,MSR_EE|MSR_IP
+	sync
+	isync
+	mtmsr	r3
+	sync
+	isync
+
+	/* Recover sleep storage */
+	lis	r3,sleep_storage@ha
+	addi	r3,r3,sleep_storage@l
+	tophys(r3,r3)
+	lwz	r1,0(r3)
+
+	/* Pass thru to older resume code ... */
+/* 
+ * Here is the resume code for older machines.
+ * r1 has the physical address of SL_PC(sp).
+ */
+	
+grackle_wake_up:
+	/* Enable and then Flash inval the instruction & data cache */
+	mfspr	r3,HID0
+	ori	r3,r3, HID0_ICE|HID0_ICFI|HID0_DCE|HID0_DCI
+	sync
+	isync
+	mtspr	HID0,r3
+	xori	r3,r3, HID0_ICFI|HID0_DCI
+	mtspr	HID0,r3
+	sync
+	
+	/* Restore the kernel's segment registers before
+	 * we do any r1 memory access as we are not sure they
+	 * are in a sane state above the first 256Mb region
+	 */
+	li	r0,16		/* load up segment register values */
+	mtctr	r0		/* for context 0 */
+	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
+	li	r4,0
+3:	mtsrin	r3,r4
+	addi	r3,r3,0x111	/* increment VSID */
+	addis	r4,r4,0x1000	/* address of next segment */
+	bdnz	3b
+	
+	/* Restore the remaining bits of the HID0 register. */
+	subi	r1,r1,SL_PC
+	lwz	r3,SL_HID0(r1)
+	sync
+	isync
+	mtspr	HID0,r3
+	sync
+	isync
+
+	/* Restore 7400/7410/7450 specific registers */
+	mfspr	r3,PVR
+	srwi	r3,r3,16
+	cmpli	cr0,r3,0x8000
+	cmpli	cr1,r3,0x000c
+	cmpli	cr2,r3,0x800c
+	cror	4*cr1+eq,4*cr1+eq,4*cr2+eq
+	cror	4*cr0+eq,4*cr0+eq,4*cr1+eq
+	bne	1f
+	lwz	r4,SL_MSSCR0(r1)
+	sync
+	mtspr	SPRN_MSSCR0,r4
+	sync
+	isync
+	lwz	r4,SL_MSSSR0(r1)
+	sync
+	mtspr	SPRN_MSSSR0,r4
+	sync
+	isync
+	bne	cr2,1f
+	li	r4,0
+	mtspr	SPRN_L2CR2,r4
+	/* Restore 7450 specific registers */
+	beq	cr1,1f
+	lwz	r4,SL_HID1(r1)
+	sync
+	mtspr	HID1,r4
+	isync
+	sync
+	lwz	r4,SPRN_ICTRL(r1)
+	sync
+	mtspr	SPRN_ICTRL,r4
+	isync
+	sync
+	lwz	r4,SPRN_LDSTCR(r1)
+	sync
+	mtspr	SPRN_LDSTCR,r4
+	isync
+	sync
+	lwz	r4,SL_LDSTDB(r1)
+	sync
+	mtspr	SPRN_LDSTDB,r4
+	isync
+	sync
+1:
+	/* Restore the BATs, and SDR1.  Then we can turn on the MMU. */
+	lwz	r4,SL_SDR1(r1)
+	mtsdr1	r4
+	lwz	r4,SL_SPRG0(r1)
+	mtsprg	0,r4
+	lwz	r4,SL_SPRG0+4(r1)
+	mtsprg	1,r4
+	lwz	r4,SL_SPRG0+8(r1)
+	mtsprg	2,r4
+	lwz	r4,SL_SPRG0+12(r1)
+	mtsprg	3,r4
+
+	lwz	r4,SL_DBAT0(r1)
+	mtdbatu	0,r4
+	lwz	r4,SL_DBAT0+4(r1)
+	mtdbatl	0,r4
+	lwz	r4,SL_DBAT1(r1)
+	mtdbatu	1,r4
+	lwz	r4,SL_DBAT1+4(r1)
+	mtdbatl	1,r4
+	lwz	r4,SL_DBAT2(r1)
+	mtdbatu	2,r4
+	lwz	r4,SL_DBAT2+4(r1)
+	mtdbatl	2,r4
+	lwz	r4,SL_DBAT3(r1)
+	mtdbatu	3,r4
+	lwz	r4,SL_DBAT3+4(r1)
+	mtdbatl	3,r4
+	lwz	r4,SL_IBAT0(r1)
+	mtibatu	0,r4
+	lwz	r4,SL_IBAT0+4(r1)
+	mtibatl	0,r4
+	lwz	r4,SL_IBAT1(r1)
+	mtibatu	1,r4
+	lwz	r4,SL_IBAT1+4(r1)
+	mtibatl	1,r4
+	lwz	r4,SL_IBAT2(r1)
+	mtibatu	2,r4
+	lwz	r4,SL_IBAT2+4(r1)
+	mtibatl	2,r4
+	lwz	r4,SL_IBAT3(r1)
+	mtibatu	3,r4
+	lwz	r4,SL_IBAT3+4(r1)
+	mtibatl	3,r4
+
+	/* Flush all TLBs */
+	lis	r4,0x1000
+1:	addic.	r4,r4,-0x1000
+	tlbie	r4
+	blt	1b
+	sync
+
+	/* restore the MSR and turn on the MMU */
+	lwz	r3,SL_MSR(r1)
+	bl	turn_on_mmu	
+
+	/* get back the stack pointer */
+	tovirt(r1,r1)
+
+	/* Restore TB */
+	li	r3,0
+	mttbl	r3
+	lwz	r3,SL_TB(r1)
+	lwz	r4,SL_TB+4(r1)
+	mttbu	r3
+	mttbl	r4
+
+	/* Restore the callee-saved registers and return */
+	lwz	r0,SL_CR(r1)
+	mtcr	r0
+	lwz	r2,SL_R2(r1)
+	lmw	r12,SL_R12(r1)
+	addi	r1,r1,SL_SIZE
+	lwz	r0,4(r1)
+	mtlr	r0
+	blr
+
+turn_on_mmu:
+	mflr	r4
+	tovirt(r4,r4)
+	mtsrr0	r4
+	mtsrr1	r3
+	sync
+	isync
+	rfi
+
+	.data
+	.globl sleep_storage
+sleep_storage:
+	.long 0
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/spd8xx.h linux/arch/ppc/platforms/spd8xx.h
--- linux.orig/arch/ppc/platforms/spd8xx.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/spd8xx.h	2002-08-12 22:14:03.000000000 +0000
@@ -0,0 +1,69 @@
+/*
+ * BK Id: SCCS/s.spd8xx.h 1.8 10/27/01 13:39:41 trini
+ */
+/*
+ * Speech Design SPD8xxTS board specific definitions
+ * 
+ * Copyright (c) 2000,2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifdef __KERNEL__
+#ifndef __ASM_SPD8XX_H__
+#define __ASM_SPD8XX_H__
+
+#include <linux/config.h>
+ 
+#include <asm/ppcboot.h>
+
+#define SPD_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
+#define SPD_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
+
+#define IMAP_ADDR	SPD_IMMR_BASE	/* physical base address of IMMR area */
+#define IMAP_SIZE	SPD_IMAP_SIZE	/* mapped size of IMMR area */
+
+#define PCMCIA_MEM_ADDR	((uint)0xFE100000)
+#define PCMCIA_MEM_SIZE	((uint)(64 * 1024))
+
+#define IDE0_INTERRUPT	10		/* = IRQ5 */
+#define IDE1_INTERRUPT	12		/* = IRQ6 */
+#define CPM_INTERRUPT	13		/* = SIU_LEVEL6 (was: SIU_LEVEL2) */
+
+/* override the default number of IDE hardware interfaces */
+#define MAX_HWIFS	2
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0x0000	/* Offset in PCMCIA memory */
+#define IDE0_DATA_REG_OFFSET		0x0000
+#define IDE0_ERROR_REG_OFFSET		0x0081
+#define IDE0_NSECTOR_REG_OFFSET		0x0082
+#define IDE0_SECTOR_REG_OFFSET		0x0083
+#define IDE0_LCYL_REG_OFFSET		0x0084
+#define IDE0_HCYL_REG_OFFSET		0x0085
+#define IDE0_SELECT_REG_OFFSET		0x0086
+#define IDE0_STATUS_REG_OFFSET		0x0087
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/*
+ * Definitions for IDE1 Interface
+ */
+#define IDE1_BASE_OFFSET		0x0C00	/* Offset in PCMCIA memory */
+#define IDE1_DATA_REG_OFFSET		0x0000
+#define IDE1_ERROR_REG_OFFSET		0x0081
+#define IDE1_NSECTOR_REG_OFFSET		0x0082
+#define IDE1_SECTOR_REG_OFFSET		0x0083
+#define IDE1_LCYL_REG_OFFSET		0x0084
+#define IDE1_HCYL_REG_OFFSET		0x0085
+#define IDE1_SELECT_REG_OFFSET		0x0086
+#define IDE1_STATUS_REG_OFFSET		0x0087
+#define IDE1_CONTROL_REG_OFFSET		0x0106
+#define IDE1_IRQ_REG_OFFSET		0x000A	/* not used */
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif /* __ASM_SPD8XX_H__ */
+#endif /* __KERNEL__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/tqm8xx.h linux/arch/ppc/platforms/tqm8xx.h
--- linux.orig/arch/ppc/platforms/tqm8xx.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/tqm8xx.h	2002-08-12 22:14:14.000000000 +0000
@@ -0,0 +1,54 @@
+/*
+ * BK Id: SCCS/s.tqm8xx.h 1.8 08/30/01 09:01:04 trini
+ */
+/*
+ * TQM8xx(L) board specific definitions
+ * 
+ * Copyright (c) 1999,2000,2001 Wolfgang Denk (wd@denx.de)
+ */
+
+#ifndef __MACH_TQM8xx_H
+#define __MACH_TQM8xx_H
+
+#include <linux/config.h>
+ 
+#include <asm/ppcboot.h>
+
+#define	TQM_IMMR_BASE	0xFFF00000	/* phys. addr of IMMR */
+#define	TQM_IMAP_SIZE	(64 * 1024)	/* size of mapped area */
+
+#define	IMAP_ADDR	TQM_IMMR_BASE	/* physical base address of IMMR area */
+#define IMAP_SIZE	TQM_IMAP_SIZE	/* mapped size of IMMR area */
+
+/*-----------------------------------------------------------------------
+ * PCMCIA stuff
+ *-----------------------------------------------------------------------
+ *
+ */
+#define PCMCIA_MEM_SIZE		( 64 << 20 )
+
+#define	MAX_HWIFS	1	/* overwrite default in include/asm-ppc/ide.h */
+
+/*
+ * Definitions for IDE0 Interface
+ */
+#define IDE0_BASE_OFFSET		0
+#define IDE0_DATA_REG_OFFSET		(PCMCIA_MEM_SIZE + 0x320)
+#define IDE0_ERROR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 1)
+#define IDE0_NSECTOR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 2)
+#define IDE0_SECTOR_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 3)
+#define IDE0_LCYL_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 4)
+#define IDE0_HCYL_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 5)
+#define IDE0_SELECT_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 6)
+#define IDE0_STATUS_REG_OFFSET		(2 * PCMCIA_MEM_SIZE + 0x320 + 7)
+#define IDE0_CONTROL_REG_OFFSET		0x0106
+#define IDE0_IRQ_REG_OFFSET		0x000A	/* not used */
+
+#define	IDE0_INTERRUPT			13
+
+
+/* We don't use the 8259.
+*/
+#define NR_8259_INTS	0
+
+#endif	/* __MACH_TQM8xx_H */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/walnut.c linux/arch/ppc/platforms/walnut.c
--- linux.orig/arch/ppc/platforms/walnut.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/walnut.c	2002-08-12 22:14:17.000000000 +0000
@@ -0,0 +1,291 @@
+/*
+ * BK Id: SCCS/s.walnut_setup.c 1.10 11/13/01 21:26:07 paulus
+ */
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: walnut_setup.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 403GP "Walnut" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@fsmlabs.com>, and Dan Malek
+ *      <dan@net4x.com>.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/interrupt.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/blk.h>
+#include <linux/seq_file.h>
+
+#include <asm/processor.h>
+#include <asm/board.h>
+#include <asm/machdep.h>
+#include <asm/page.h>
+
+#include "ppc4xx_pic.h"
+#include <asm/time.h>
+#include "walnut_setup.h"
+
+
+/* Function Prototypes */
+
+extern void abort(void);
+
+/* Global Variables */
+
+unsigned char __res[sizeof(bd_t)];
+
+
+/*
+ * void __init walnut_init()
+ *
+ * Description:
+ *   This routine...
+ *
+ * Input(s):
+ *   r3 - Optional pointer to a board information structure.
+ *   r4 - Optional pointer to the physical starting address of the init RAM
+ *        disk.
+ *   r5 - Optional pointer to the physical ending address of the init RAM
+ *        disk.
+ *   r6 - Optional pointer to the physical starting address of any kernel
+ *        command-line parameters.
+ *   r7 - Optional pointer to the physical ending address of any kernel
+ *        command-line parameters.
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+walnut_init(unsigned long r3, unsigned long r4, unsigned long r5, 
+	    unsigned long r6, unsigned long r7)
+{
+	/*
+	 * If we were passed in a board information, copy it into the
+	 * residual data area.
+	 */
+	if (r3) {
+		memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t));
+	}
+
+#if defined(CONFIG_BLK_DEV_INITRD)
+	/*
+	 * If the init RAM disk has been configured in, and there's a valid
+	 * starting address for it, set it up.
+	 */
+	if (r4) {
+		initrd_start = r4 + KERNELBASE;
+		initrd_end = r5 + KERNELBASE;
+	}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
+	/* Copy the kernel command line arguments to a safe place. */
+
+	if (r6) {
+ 		*(char *)(r7 + KERNELBASE) = 0;
+		strcpy(cmd_line, (char *)(r6 + KERNELBASE));
+	}
+
+	/* Initialize machine-dependency vectors */
+
+	ppc_md.setup_arch	 	= walnut_setup_arch;
+	ppc_md.show_percpuinfo	 	= walnut_show_percpuinfo;
+	ppc_md.irq_cannonicalize 	= NULL;
+	ppc_md.init_IRQ		 	= walnut_init_IRQ;
+	ppc_md.get_irq		 	= walnut_get_irq;
+	ppc_md.init		 	= NULL;
+
+	ppc_md.restart		 	= walnut_restart;
+	ppc_md.power_off	 	= walnut_power_off;
+	ppc_md.halt		 	= walnut_halt;
+
+	ppc_md.time_init	 	= walnut_time_init;
+	ppc_md.set_rtc_time	 	= walnut_set_rtc_time;
+	ppc_md.get_rtc_time	 	= walnut_get_rtc_time;
+	ppc_md.calibrate_decr	 	= walnut_calibrate_decr;
+
+	ppc_md.kbd_setkeycode    	= NULL;
+	ppc_md.kbd_getkeycode    	= NULL;
+	ppc_md.kbd_translate     	= NULL;
+	ppc_md.kbd_unexpected_up 	= NULL;
+	ppc_md.kbd_leds          	= NULL;
+	ppc_md.kbd_init_hw       	= NULL;
+	ppc_md.ppc_kbd_sysrq_xlate	= NULL;
+}
+
+/*
+ * Document me.
+ */
+void __init
+walnut_setup_arch(void)
+{
+	/* XXX - Implement me */
+}
+
+/*
+ * int walnut_show_percpuinfo()
+ *
+ * Description:
+ *   This routine pretty-prints the platform's internal CPU and bus clock
+ *   frequencies into the buffer for usage in /proc/cpuinfo.
+ *
+ * Input(s):
+ *  *buffer - Buffer into which CPU and bus clock frequencies are to be
+ *            printed.
+ *
+ * Output(s):
+ *  *buffer - Buffer with the CPU and bus clock frequencies.
+ *
+ * Returns:
+ *   The number of bytes copied into 'buffer' if OK, otherwise zero or less
+ *   on error.
+ */
+int
+walnut_show_percpuinfo(struct seq_file *m)
+{
+	bd_t *bp = (bd_t *)__res;
+
+	seq_printf(m, "clock\t\t: %dMHz\n"
+		   "bus clock\t\t: %dMHz\n",
+		   bp->bi_intfreq / 1000000,
+		   bp->bi_busfreq / 1000000);
+
+	return 0;
+}
+
+/*
+ * Document me.
+ */
+void __init
+walnut_init_IRQ(void)
+{
+	int i;
+
+	ppc4xx_pic_init();
+
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].handler = ppc4xx_pic;
+	}
+
+	return;
+}
+
+/*
+ * Document me.
+ */
+int
+walnut_get_irq(struct pt_regs *regs)
+{
+	return (ppc4xx_pic_get_irq(regs));
+}
+
+/*
+ * Document me.
+ */
+void
+walnut_restart(char *cmd)
+{
+	abort();
+}
+
+/*
+ * Document me.
+ */
+void
+walnut_power_off(void)
+{
+	walnut_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+void
+walnut_halt(void)
+{
+	walnut_restart(NULL);
+}
+
+/*
+ * Document me.
+ */
+long __init
+walnut_time_init(void)
+{
+	/* XXX - Implement me */
+	return 0;
+}
+
+/*
+ * Document me.
+ */
+int __init
+walnut_set_rtc_time(unsigned long time)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * Document me.
+ */
+unsigned long __init
+walnut_get_rtc_time(void)
+{
+	/* XXX - Implement me */
+
+	return (0);
+}
+
+/*
+ * void __init walnut_calibrate_decr()
+ *
+ * Description:
+ *   This routine retrieves the internal processor frequency from the board
+ *   information structure, sets up the kernel timer decrementer based on
+ *   that value, enables the 403 programmable interval timer (PIT) and sets
+ *   it up for auto-reload.
+ *
+ * Input(s):
+ *   N/A
+ *
+ * Output(s):
+ *   N/A
+ *
+ * Returns:
+ *   N/A
+ *
+ */
+void __init
+walnut_calibrate_decr(void)
+{
+	unsigned int freq;
+	bd_t *bip = (bd_t *)__res;
+
+	freq = bip->bi_intfreq;
+
+	decrementer_count = freq / HZ;
+	count_period_num = 1;
+	count_period_den = freq;
+
+	/* Enable the PIT and set auto-reload of its value */
+
+	mtspr(SPRN_TCR, TCR_PIE | TCR_ARE);
+
+	/* Clear any pending timer interrupts */
+
+	mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS);
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc/platforms/walnut.h linux/arch/ppc/platforms/walnut.h
--- linux.orig/arch/ppc/platforms/walnut.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/ppc/platforms/walnut.h	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,53 @@
+/*
+ * BK Id: SCCS/s.walnut_setup.h 1.5 05/17/01 18:14:22 cort
+ */
+/*
+ *
+ *    Copyright (c) 1999-2000 Grant Erickson <grant@lcse.umn.edu>
+ *
+ *    Module name: walnut_setup.c
+ *
+ *    Description:
+ *      Architecture- / platform-specific boot-time initialization code for
+ *      the IBM PowerPC 405GP "Walnut" evaluation board. Adapted from original
+ *      code by Gary Thomas, Cort Dougan <cort@cs.nmt.edu>, and Dan Malek
+ *      <dan@netx4.com>.
+ *
+ */
+
+#ifndef	__WALNUT_SETUP_H__
+#define	__WALNUT_SETUP_H__
+
+#include <asm/ptrace.h>
+#include <asm/board.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned char	 __res[sizeof(bd_t)];
+
+extern void		 walnut_init(unsigned long r3,
+				  unsigned long ird_start,
+				  unsigned long ird_end,
+				  unsigned long cline_start,
+				  unsigned long cline_end);
+extern void		 walnut_setup_arch(void);
+extern int		 walnut_setup_residual(char *buffer);
+extern void		 walnut_init_IRQ(void);
+extern int		 walnut_get_irq(struct pt_regs *regs);
+extern void		 walnut_restart(char *cmd);
+extern void		 walnut_power_off(void);
+extern void		 walnut_halt(void);
+extern void		 walnut_time_init(void);
+extern int		 walnut_set_rtc_time(unsigned long now);
+extern unsigned long	 walnut_get_rtc_time(void);
+extern void		 walnut_calibrate_decr(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __WALNUT_SETUP_H__ */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc64/config.in linux/arch/ppc64/config.in
--- linux.orig/arch/ppc64/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc64/config.in	2002-08-12 22:14:09.000000000 +0000
@@ -70,9 +70,9 @@
    define_bool CONFIG_KCORE_ELF y
 fi
 
-bool 'Kernel Support for 64 bit ELF binaries' CONFIG_BINFMT_ELF
+bool 'Kernel support for 64-bit ELF binaries' CONFIG_BINFMT_ELF
 
-tristate 'Kernel support for 32 bit binaries' CONFIG_BINFMT_ELF32
+tristate 'Kernel support for 32-bit ELF binaries' CONFIG_BINFMT_ELF32
 
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc64/kernel/htab.c linux/arch/ppc64/kernel/htab.c
--- linux.orig/arch/ppc64/kernel/htab.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc64/kernel/htab.c	2002-08-12 22:14:23.000000000 +0000
@@ -38,7 +38,6 @@
 #include <linux/cache.h>
 #include <asm/uaccess.h>
 #include <asm/naca.h>
-#include <asm/system.h>
 #include <asm/pmc.h>
 #include <asm/machdep.h>
 #include <asm/lmb.h>
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/ppc64/kernel/pSeries_pci.c linux/arch/ppc64/kernel/pSeries_pci.c
--- linux.orig/arch/ppc64/kernel/pSeries_pci.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/ppc64/kernel/pSeries_pci.c	2002-08-12 22:14:09.000000000 +0000
@@ -491,7 +491,7 @@
 					 0x100000); 
 
 		/* 
-		 * Firmware doesnt always clear this bit which is critical
+		 * Firmware doesn't always clear this bit which is critical
 		 * for good performance - Anton
 		 */
 		{
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/config.in linux/arch/s390/config.in
--- linux.orig/arch/s390/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/config.in	2002-08-12 22:14:09.000000000 +0000
@@ -75,3 +75,4 @@
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
 
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/defconfig linux/arch/s390/defconfig
--- linux.orig/arch/s390/defconfig	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/defconfig	2002-08-12 22:14:13.000000000 +0000
@@ -32,6 +32,8 @@
 # General setup
 #
 CONFIG_FAST_IRQ=y
+CONFIG_MACHCHK_WARNING=y
+CONFIG_CHSC=y
 CONFIG_IPL=y
 # CONFIG_IPL_TAPE is not set
 CONFIG_IPL_VM=y
@@ -146,9 +148,10 @@
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
+CONFIG_SHARED_IPV6_CARDS=y
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
+CONFIG_VLAN_8021Q=m
 
 #
 #  
@@ -163,7 +166,7 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-CONFIG_NET_FASTROUTE=y
+# CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/debug.c linux/arch/s390/kernel/debug.c
--- linux.orig/arch/s390/kernel/debug.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/debug.c	2002-08-12 22:14:05.000000000 +0000
@@ -443,6 +443,7 @@
 {
 	size_t count = 0;
 	size_t entry_offset, size = 0;
+	int rc;
 	file_private_info_t *p_info;
 
 	p_info = ((file_private_info_t *) file->private_data);
@@ -458,9 +459,9 @@
 		size = MIN((len - count), (size - entry_offset));
 
 		if(size){
-			if (copy_to_user(user_buf + count, 
-					p_info->temp_buf + entry_offset, size))
-				return count ? count: -EFAULT;
+			if ((rc = copy_to_user(user_buf + count, 
+					p_info->temp_buf + entry_offset, size)))
+			return rc;
 		}
 		count += size;
 		entry_offset = 0;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
--- linux.orig/arch/s390/kernel/entry.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/entry.S	2002-08-12 22:14:07.000000000 +0000
@@ -221,11 +221,11 @@
 # call trace before and after sys_call
 #
 sysc_tracesys:
-	la	%r12,BASED(sysc_return)
+	la	%r11,BASED(sysc_return)
 
 #
 # call syscall_trace before and after system call
-# special linkage: %r12 contains the return address for trace_svc
+# special linkage: %r11 contains the return address for trace_svc
 #
 trace_svc:
         l       %r1,BASED(.Ltrace)
@@ -244,7 +244,7 @@
         basr    %r14,%r8          # call sys_xxx
         st      %r2,SP_R2(%r15)   # store return value
         l       %r1,BASED(.Ltrace)
-	lr	%r14,%r12	  # return point is in %r12
+	lr	%r14,%r11	  # return point is in %r11
         br      %r1
 
 #
@@ -678,7 +678,7 @@
 # call trace before and after sys_call
 #
 pgm_tracesys:
-	la	%r12,BASED(pgm_svcret)
+	la	%r11,BASED(pgm_svcret)
 	b	BASED(trace_svc)
 
 /*
@@ -758,25 +758,25 @@
 	SAVE_ALL_BASE
         SAVE_ALL __LC_EXT_OLD_PSW,0
         GET_CURRENT                    # load pointer to task_struct to R9
-        la      %r2,SP_PTREGS(%r15)    # address of register-save area
-        lh      %r3,__LC_EXT_INT_CODE  # error code
-        lr      %r1,%r3                # calculate index = code & 0xff
-        n       %r1,BASED(.Lc0xff)
-        sll     %r1,2
-        l       %r4,BASED(.Lext_hash)
-        l       %r4,0(%r1,%r4)         # get first list entry for hash value
-        ltr     %r4,%r4                # == NULL ?
-        bz      BASED(io_return)       # yes, nothing to do, exit
+	lh	%r6,__LC_EXT_INT_CODE  # get interruption code
+	lr	%r1,%r6		       # calculate index = code & 0xff
+	n	%r1,BASED(.Lc0xff)
+	sll	%r1,2
+	l	%r7,BASED(.Lext_hash)
+	l	%r7,0(%r1,%r7)	       # get first list entry for hash value
+	ltr	%r7,%r7		       # == NULL ?
+	bz	BASED(io_return)       # yes, nothing to do, exit
 ext_int_loop:
-        ch      %r3,8(%r4)             # compare external interrupt code
-        be      BASED(ext_int_found)
-        icm     %r4,15,0(%r4)          # next list entry
-        bnz     BASED(ext_int_loop)
-        b       BASED(io_return)
-ext_int_found:
-        l       %r4,4(%r4)             # get handler address
-        la      %r14,BASED(io_return)
-        br      %r4                    # branch to ext call handler
+	ch	%r6,8(%r7)	       # compare external interrupt code
+	bne	BASED(ext_int_next)
+	l	%r1,4(%r7)	       # get handler address
+	la	%r2,SP_PTREGS(%r15)    # address of register-save area
+	lr	%r3,%r6		       # interruption code
+	basr	%r14,%r1	       # call handler
+ext_int_next:
+	icm	%r7,15,0(%r7)	       # next list entry
+	bnz	BASED(ext_int_loop)
+	b	BASED(io_return)
 
 /*
  * Machine check handler routines
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/ieee.h linux/arch/s390/kernel/ieee.h
--- linux.orig/arch/s390/kernel/ieee.h	2000-05-12 18:41:44.000000000 +0000
+++ linux/arch/s390/kernel/ieee.h	1970-01-01 00:00:00.000000000 +0000
@@ -1,90 +0,0 @@
-/*
- *  arch/s390/kernel/ieee.h
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
- */
-
-#include <linux/sched.h>
-
-static    inline void _adddf(int R1,int R2)
-{
-  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd +
-                             current->tss.fprs[R2].fd;
-}
-
-static    inline void _subdf(int R1,int R2)
-{
-  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd -
-                             current->tss.fprs[R2].fd;
-}
-
-static    inline void _muldf(int R1,int R2)
-{
-  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd *
-                             current->tss.fprs[R2].fd;
-}
-
-static    inline void _divdf(int R1,int R2)
-{
-  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd /
-                             current->tss.fprs[R2].fd;
-}
-
-static    inline void _negdf(int R1,int R2)
-{
-  current->tss.fprs[R1].fd = -current->tss.fprs[R1].fd;
-}
-
-static    inline void _fixdfsi(int R1,int R2)
-{
-  current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].fd;
-}
-
-static    inline void _extendsidf(int R1,int R2)
-{
-  current->tss.fprs[R1].fd = (double) current->tss.regs->gprs[R2];
-}
-
-
-static    inline  void _addsf(int R1,int R2)
-{
-  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff +
-                             current->tss.fprs[R2].ff;
-}
-
-static    inline  void _subsf(int R1,int R2)
-{
-  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff -
-                             current->tss.fprs[R2].ff;
-}
-
-static    inline void _mulsf(int R1,int R2)
-{
-  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff *
-                             current->tss.fprs[R2].ff;
-}
-
-static    inline void _divsf(int R1,int R2)
-{
-  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff /
-                             current->tss.fprs[R2].ff;
-}
-
-static    inline void _negsf(int R1,int R2)
-{
-  current->tss.fprs[R1].ff = -current->tss.fprs[R1].ff;
-}
-
-static    inline void _fixsfsi(int R1,int R2)
-{
-  current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].ff;
-}
-
-static    inline void _extendsisf(int R1,int R2)
-{
-  current->tss.fprs[R1].ff = (double) current->tss.regs->gprs[R2];
-}
-
-
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/ptrace.c linux/arch/s390/kernel/ptrace.c
--- linux.orig/arch/s390/kernel/ptrace.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/ptrace.c	2002-08-12 22:14:14.000000000 +0000
@@ -121,10 +121,11 @@
 		else
 		{
 			if(realuseraddr==(addr_t)NULL)
-				retval=(clear_user((void *)copyaddr,len)==-EFAULT ? -EIO:0);
+				retval=clear_user((void *)copyaddr,len);
 			else
-				retval=(copy_to_user((void *)copyaddr,(void *)realuseraddr,len)==-EFAULT ? -EIO:0);
+				retval=copy_to_user((void *)copyaddr,(void *)realuseraddr,len);
 		}      
+		retval = retval ? -EFAULT : 0;
 	}
 	else
 	{
@@ -235,16 +236,18 @@
 	ret = -ESRCH;
 	read_lock(&tasklist_lock);
 	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
-		goto out;
+		goto out_tsk;
 	if (request == PTRACE_ATTACH) 
 	{
 		ret = ptrace_attach(child);
-		goto out;
+		goto out_tsk;
 	}
 	ret = -ESRCH;
 	// printk("child=%lX child->flags=%lX",child,child->flags);
@@ -253,14 +256,14 @@
 	if(child!=current)
 	{
 		if (!(child->ptrace & PT_PTRACED))
-			goto out;
+			goto out_tsk;
 		if (child->state != TASK_STOPPED) 
 		{
 			if (request != PTRACE_KILL)
-				goto out;
+				goto out_tsk;
 		}
 		if (child->p_pptr != current)
-			goto out;
+			goto out_tsk;
 	}
 	switch (request) 
 	{
@@ -270,9 +273,9 @@
 		copied = access_process_vm(child,ADDR_BITS_REMOVE(addr), &tmp, sizeof(tmp), 0);
 		ret = -EIO;
 		if (copied != sizeof(tmp))
-			goto out;
+			break;
 		ret = put_user(tmp,(unsigned long *) data);
-		goto out;
+		break;
 
 		/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR:
@@ -284,9 +287,8 @@
 	case PTRACE_POKEDATA:
 		ret = 0;
 		if (access_process_vm(child,ADDR_BITS_REMOVE(addr), &data, sizeof(data), 1) == sizeof(data))
-			goto out;
+			break;
 		ret = -EIO;
-		goto out;
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
@@ -343,14 +345,15 @@
 	case PTRACE_POKEUSR_AREA:
 		if(copy_from_user(&parea,(void *)addr,sizeof(parea))==0)  
 			ret=copy_user(child,parea.kernel_addr,parea.process_addr,
-				 parea.len,1,(request==PTRACE_POKEUSR_AREA));
-		else
-			ret = -EFAULT;
+				      parea.len,1,(request==PTRACE_POKEUSR_AREA));
+		else ret = -EFAULT;
 		break;
 	default:
 		ret = -EIO;
 		break;
 	}
+ out_tsk:
+	free_task_struct(child);
  out:
 	unlock_kernel();
 	return ret;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/s390_ext.c linux/arch/s390/kernel/s390_ext.c
--- linux.orig/arch/s390/kernel/s390_ext.c	2001-07-25 21:12:01.000000000 +0000
+++ linux/arch/s390/kernel/s390_ext.c	2002-08-12 22:14:19.000000000 +0000
@@ -21,34 +21,31 @@
  * iucv and 0x2603 pfault) this is always the first element. 
  */
 ext_int_info_t *ext_int_hash[256] = { 0, };
-ext_int_info_t ext_int_info_timer;
-ext_int_info_t ext_int_info_hwc;
-ext_int_info_t ext_int_pfault;
 
 int register_external_interrupt(__u16 code, ext_int_handler_t handler) {
         ext_int_info_t *p;
         int index;
 
-        index = code & 0xff;
-        p = ext_int_hash[index];
-        while (p != NULL) {
-                if (p->code == code)
-                        return -EBUSY;
-                p = p->next;
-        }
-        if (code == 0x1004) /* time_init is done before kmalloc works :-/ */
-                p = &ext_int_info_timer;
-        else if (code == 0x2401) /* hwc_init is done too early too */
-                p = &ext_int_info_hwc;
-        else if (code == 0x2603) /* pfault_init is done too early too */
-		p = &ext_int_pfault;
-	else
-                p = (ext_int_info_t *)
-                          kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+	p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
         if (p == NULL)
                 return -ENOMEM;
         p->code = code;
         p->handler = handler;
+        index = code & 0xff;
+        p->next = ext_int_hash[index];
+        ext_int_hash[index] = p;
+        return 0;
+}
+
+int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
+				      ext_int_info_t *p) {
+        int index;
+
+        if (p == NULL)
+                return -EINVAL;
+        p->code = code;
+        p->handler = handler;
+        index = code & 0xff;
         p->next = ext_int_hash[index];
         ext_int_hash[index] = p;
         return 0;
@@ -73,11 +70,33 @@
                 q->next = p->next;
         else
                 ext_int_hash[index] = p->next;
-        if (code != 0x1004 && code != 0x2401 && code != 0x2603)
-                kfree(p);
+	kfree(p);
         return 0;
 }
 
+int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
+					ext_int_info_t *p) {
+	ext_int_info_t *q;
+	int index;
+
+	if (p == NULL || p->code != code || p->handler != handler)
+		return -EINVAL;
+	index = code & 0xff;
+	q = ext_int_hash[index];
+	if (p != q) {
+		while (q != NULL) {
+			if (q->next == p)
+				break;
+			q = q->next;
+		}
+		if (q == NULL)
+			return -ENOENT;
+		q->next = p->next;
+	} else
+		ext_int_hash[index] = p->next;
+	return 0;
+}
+
 EXPORT_SYMBOL(register_external_interrupt);
 EXPORT_SYMBOL(unregister_external_interrupt);
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/s390_ksyms.c linux/arch/s390/kernel/s390_ksyms.c
--- linux.orig/arch/s390/kernel/s390_ksyms.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/s390_ksyms.c	2002-08-12 22:14:02.000000000 +0000
@@ -9,6 +9,7 @@
 #include <asm/checksum.h>
 #include <asm/delay.h>
 #include <asm/setup.h>
+#include <asm/softirq.h>
 #if CONFIG_IP_MULTICAST
 #include <net/arp.h>
 #endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c
--- linux.orig/arch/s390/kernel/setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/setup.c	2002-08-12 22:14:04.000000000 +0000
@@ -165,15 +165,15 @@
 static int __init conmode_setup(char *str)
 {
 #if defined(CONFIG_HWC_CONSOLE)
-	if (strncmp(str, "hwc", 4) == 0 && !MACHINE_IS_P390)
+	if (strncmp(str, "hwc", 4) == 0)
                 SET_CONSOLE_HWC;
 #endif
 #if defined(CONFIG_TN3215_CONSOLE)
-	if (strncmp(str, "3215", 5) == 0 && (MACHINE_IS_VM || MACHINE_IS_P390))
+	if (strncmp(str, "3215", 5) == 0)
 		SET_CONSOLE_3215;
 #endif
 #if defined(CONFIG_TN3270_CONSOLE)
-	if (strncmp(str, "3270", 5) == 0 && (MACHINE_IS_VM || MACHINE_IS_P390))
+	if (strncmp(str, "3270", 5) == 0)
 		SET_CONSOLE_3270;
 #endif
         return 1;
@@ -233,32 +233,63 @@
 	}
 }
 
+#ifdef CONFIG_SMP
+extern void machine_restart_smp(char *);
+extern void machine_halt_smp(void);
+extern void machine_power_off_smp(void);
+
+void (*_machine_restart)(char *command) = machine_restart_smp;
+void (*_machine_halt)(void) = machine_halt_smp;
+void (*_machine_power_off)(void) = machine_power_off_smp;
+#else
 /*
  * Reboot, halt and power_off routines for non SMP.
  */
-
-#ifndef CONFIG_SMP
-void machine_restart(char * __unused)
+static void do_machine_restart_nonsmp(char * __unused)
 {
 	reipl(S390_lowcore.ipl_device);
 }
 
-void machine_halt(void)
+static void do_machine_halt_nonsmp(void)
 {
         if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
                 cpcmd(vmhalt_cmd, NULL, 0);
         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
-void machine_power_off(void)
+static void do_machine_power_off_nonsmp(void)
 {
         if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
                 cpcmd(vmpoff_cmd, NULL, 0);
         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
+
+void (*_machine_restart)(char *command) = do_machine_restart_nonsmp;
+void (*_machine_halt)(void) = do_machine_halt_nonsmp;
+void (*_machine_power_off)(void) = do_machine_power_off_nonsmp;
 #endif
 
 /*
+ * Reboot, halt and power_off stubs. They just call _machine_restart,
+ * _machine_halt or _machine_power_off. 
+ */
+
+void machine_restart(char *command)
+{
+	_machine_restart(command);
+}
+
+void machine_halt(void)
+{
+	_machine_halt();
+}
+
+void machine_power_off(void)
+{
+	_machine_power_off();
+}
+
+/*
  * Setup function called from init/main.c just after the banner
  * was printed.
  */
@@ -497,7 +528,7 @@
 	}
 	if (cpu_online_map & (1 << n)) {
 		cpuinfo = &safe_get_cpu_lowcore(n)->cpu_data;
-		seq_printf(m, "processor %i: "
+		seq_printf(m, "processor %li: "
 			       "version = %02X,  "
 			       "identification = %06X,  "
 			       "machine = %04X\n",
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/signal.c linux/arch/s390/kernel/signal.c
--- linux.orig/arch/s390/kernel/signal.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/signal.c	2002-08-12 22:14:09.000000000 +0000
@@ -335,6 +335,10 @@
 			goto give_sigsegv;
 	}
 
+	/* Set up backchain. */
+	if (__put_user(regs->gprs[15], (addr_t *) frame))
+		goto give_sigsegv;
+
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (addr_t)frame;
 	regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
@@ -388,6 +392,10 @@
 	                          (u16 *)(frame->retcode));
 	}
 
+	/* Set up backchain. */
+	if (__put_user(regs->gprs[15], (addr_t *) frame))
+		goto give_sigsegv;
+
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (addr_t)frame;
 	regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/smp.c linux/arch/s390/kernel/smp.c
--- linux.orig/arch/s390/kernel/smp.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/smp.c	2002-08-12 22:14:00.000000000 +0000
@@ -176,61 +176,132 @@
 	return 0;
 }
 
+static inline void do_send_stop(void)
+{
+        u32 dummy;
+        int i;
+
+        /* stop all processors */
+        for (i =  0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        int ccode;
+                        do {
+                                ccode = signal_processor_ps(
+                                   &dummy,
+                                   0,
+                                   i,
+                                   sigp_stop);
+                        } while(ccode == sigp_busy);
+                }
+        }
+}
+
+static inline void do_store_status(void)
+{
+        unsigned long low_core_addr;
+        u32 dummy;
+        int i;
+
+        /* store status of all processors in their lowcores (real 0) */
+        for (i =  0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        int ccode;
+                        low_core_addr = (unsigned long)get_cpu_lowcore(i);
+                        do {
+                                ccode = signal_processor_ps(
+                                   &dummy,
+                                   low_core_addr,
+                                   i,
+                                   sigp_store_status_at_address);
+                        } while(ccode == sigp_busy);
+                }
+        }
+}
 
 /*
- * Various special callbacks
+ * this function sends a 'stop' sigp to all other CPUs in the system.
+ * it goes straight through.
  */
-
-void do_machine_restart(void)
+void smp_send_stop(void)
 {
-        smp_send_stop();
-	reipl(S390_lowcore.ipl_device);
+        /* write magic number to zero page (absolute 0) */
+        get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
+
+	/* stop other processors. */
+	do_send_stop();
+
+	/* store status of other processors. */
+	do_store_status();
+}
+
+/*
+ * Reboot, halt and power_off routines for SMP.
+ */
+static volatile unsigned long cpu_restart_map;
+
+static void do_machine_restart(void * __unused)
+{
+	clear_bit(smp_processor_id(), &cpu_restart_map);
+	if (smp_processor_id() == 0) {
+		/* Wait for all other cpus to enter do_machine_restart. */
+		while (cpu_restart_map != 0);
+		/* Store status of other cpus. */
+		do_store_status();
+		/*
+		 * Finally call reipl. Because we waited for all other
+		 * cpus to enter this function we know that they do
+		 * not hold any s390irq-locks (the cpus have been
+		 * interrupted by an external interrupt and s390irq
+		 * locks are always held disabled).
+		 */
+		reipl(S390_lowcore.ipl_device);
+	}
+	signal_processor(smp_processor_id(), sigp_stop);
 }
 
-void machine_restart(char * __unused) 
+void machine_restart_smp(char * __unused) 
 {
-        if (smp_processor_id() != 0) {
-                smp_ext_bitcall(0, ec_restart);
-		for (;;)
-			enabled_wait();
-        } else
-                do_machine_restart();
+	cpu_restart_map = cpu_online_map;
+        smp_call_function(do_machine_restart, NULL, 0, 0);
+	do_machine_restart(NULL);
 }
 
-void do_machine_halt(void)
+static void do_machine_halt(void * __unused)
 {
-        smp_send_stop();
-        if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
-                cpcmd(vmhalt_cmd, NULL, 0);
-        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+	if (smp_processor_id() == 0) {
+		smp_send_stop();
+		if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+			cpcmd(vmhalt_cmd, NULL, 0);
+		signal_processor(smp_processor_id(),
+				 sigp_stop_and_store_status);
+	}
+	for (;;)
+		enabled_wait();
 }
 
-void machine_halt(void)
+void machine_halt_smp(void)
 {
-        if (smp_processor_id() != 0) {
-                smp_ext_bitcall(0, ec_halt);
-		for (;;)
-			enabled_wait();
-        } else
-                do_machine_halt();
+        smp_call_function(do_machine_halt, NULL, 0, 0);
+	do_machine_halt(NULL);
 }
 
-void do_machine_power_off(void)
+static void do_machine_power_off(void * __unused)
 {
-        smp_send_stop();
-        if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
-                cpcmd(vmpoff_cmd, NULL, 0);
-        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+	if (smp_processor_id() == 0) {
+		smp_send_stop();
+		if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+			cpcmd(vmpoff_cmd, NULL, 0);
+		signal_processor(smp_processor_id(),
+				 sigp_stop_and_store_status);
+	}
+	for (;;)
+		enabled_wait();
 }
 
-void machine_power_off(void)
+void machine_power_off_smp(void)
 {
-        if (smp_processor_id() != 0) {
-                smp_ext_bitcall(0, ec_power_off);
-		for (;;)
-			enabled_wait();
-        } else
-                do_machine_power_off();
+        smp_call_function(do_machine_power_off, NULL, 0, 0);
+	do_machine_power_off(NULL);
 }
 
 /*
@@ -247,19 +318,11 @@
          *
          * For the ec_schedule signal we have to do nothing. All the work
          * is done automatically when we return from the interrupt.
-	 * For the ec_restart, ec_halt and ec_power_off we call the
-         * appropriate routine.
          */
         do {
                 bits = atomic_read(&S390_lowcore.ext_call_fast);
         } while (atomic_compare_and_swap(bits,0,&S390_lowcore.ext_call_fast));
 
-        if (test_bit(ec_restart, &bits))
-		do_machine_restart();
-        if (test_bit(ec_halt, &bits))
-		do_machine_halt();
-        if (test_bit(ec_power_off, &bits))
-		do_machine_power_off();
 	if (test_bit(ec_call_function, &bits)) 
 		do_call_function();
 }
@@ -288,7 +351,6 @@
 static void smp_ext_bitcall_others(ec_bit_sig sig)
 {
         struct _lowcore *lowcore;
-        sigp_ccode ccode;
         int i;
 
         for (i = 0; i < smp_num_cpus; i++) {
@@ -305,53 +367,6 @@
 }
 
 /*
- * this function sends a 'stop' sigp to all other CPUs in the system.
- * it goes straight through.
- */
-
-void smp_send_stop(void)
-{
-        int i;
-        u32 dummy;
-        unsigned long low_core_addr;
-
-        /* write magic number to zero page (absolute 0) */
-
-        get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
-
-        /* stop all processors */
-
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() != i) {
-                        int ccode;
-                        do {
-                                ccode = signal_processor_ps(
-                                   &dummy,
-                                   0,
-                                   i,
-                                   sigp_stop);
-                        } while(ccode == sigp_busy);
-                }
-        }
-
-        /* store status of all processors in their lowcores (real 0) */
-
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() != i) {
-                        int ccode;
-                        low_core_addr = (unsigned long)get_cpu_lowcore(i);
-                        do {
-                                ccode = signal_processor_ps(
-                                   &dummy,
-                                   low_core_addr,
-                                   i,
-                                   sigp_store_status_at_address);
-                        } while(ccode == sigp_busy);
-                }
-        }
-}
-
-/*
  * this function sends a 'purge tlb' signal to another CPU.
  */
 void smp_ptlb_callback(void *info)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/time.c linux/arch/s390/kernel/time.c
--- linux.orig/arch/s390/kernel/time.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/time.c	2002-08-12 22:14:00.000000000 +0000
@@ -39,6 +39,7 @@
 
 #define TICK_SIZE tick
 
+static ext_int_info_t ext_int_info_timer;
 static uint64_t init_timer_cc;
 
 extern rwlock_t xtime_lock;
@@ -224,7 +225,8 @@
         tod_to_timeval(set_time_cc, &xtime);
 
         /* request the 0x1004 external interrupt */
-        if (register_external_interrupt(0x1004, do_comparator_interrupt) != 0)
+        if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
+					      &ext_int_info_timer) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
         /* init CPU timer */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390/kernel/traps.c linux/arch/s390/kernel/traps.c
--- linux.orig/arch/s390/kernel/traps.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390/kernel/traps.c	2002-08-12 22:14:14.000000000 +0000
@@ -58,6 +58,7 @@
 extern int pfault_init(void);
 extern void pfault_fini(void);
 extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
+static ext_int_info_t ext_int_pfault;
 #endif
 
 int kstack_depth_to_print = 12;
@@ -646,7 +647,8 @@
 #ifdef CONFIG_PFAULT
 	if (MACHINE_IS_VM) {
 		/* request the 0x2603 external interrupt */
-		if (register_external_interrupt(0x2603, pfault_interrupt) != 0)
+		if (register_early_external_interrupt(0x2603, pfault_interrupt,
+						      &ext_int_pfault) != 0)
 			panic("Couldn't request external interrupt 0x2603");
 		/*
 		 * First try to get pfault pseudo page faults going.
@@ -654,8 +656,9 @@
 		 */
 		if (pfault_init() != 0) {
 			/* Tough luck, no pfault. */
-			unregister_external_interrupt(0x2603,
-						      pfault_interrupt);
+			unregister_early_external_interrupt(0x2603,
+							    pfault_interrupt,
+							    &ext_int_pfault);
 			cpcmd("SET PAGEX ON", NULL, 0);
 		}
 	}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/config.in linux/arch/s390x/config.in
--- linux.orig/arch/s390x/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/config.in	2002-08-12 22:14:04.000000000 +0000
@@ -40,6 +40,8 @@
 mainmenu_option next_comment
 comment 'General setup'
 bool 'Fast IRQ handling' CONFIG_FAST_IRQ
+bool 'Process warning machine checks' CONFIG_MACHCHK_WARNING
+bool 'Use chscs for Common I/O' CONFIG_CHSC
 bool 'Builtin IPL record support' CONFIG_IPL
 if [ "$CONFIG_IPL" = "y" ]; then
   choice 'IPL method generated into head.S' \
@@ -77,3 +79,4 @@
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
 
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/defconfig linux/arch/s390x/defconfig
--- linux.orig/arch/s390x/defconfig	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/defconfig	2002-08-12 22:13:59.000000000 +0000
@@ -33,6 +33,8 @@
 # General setup
 #
 CONFIG_FAST_IRQ=y
+CONFIG_MACHCHK_WARNING=y
+CONFIG_CHSC=y
 CONFIG_IPL=y
 # CONFIG_IPL_TAPE is not set
 CONFIG_IPL_VM=y
@@ -146,9 +148,10 @@
 # CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
 CONFIG_IPV6=m
+CONFIG_SHARED_IPV6_CARDS=y
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
-# CONFIG_VLAN_8021Q is not set
+CONFIG_VLAN_8021Q=m
 
 #
 #  
@@ -163,7 +166,7 @@
 # CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
-CONFIG_NET_FASTROUTE=y
+# CONFIG_NET_FASTROUTE is not set
 # CONFIG_NET_HW_FLOWCONTROL is not set
 
 #
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/Makefile linux/arch/s390x/kernel/Makefile
--- linux.orig/arch/s390x/kernel/Makefile	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/Makefile	2002-08-12 22:14:16.000000000 +0000
@@ -34,6 +34,7 @@
 
 .PHONY: asm-offsets.h
 
+entry.S: asm-offsets.h
 #
 # This is just to get the dependencies...
 #
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/debug.c linux/arch/s390x/kernel/debug.c
--- linux.orig/arch/s390x/kernel/debug.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/debug.c	2002-08-12 22:14:05.000000000 +0000
@@ -443,6 +443,7 @@
 {
 	size_t count = 0;
 	size_t entry_offset, size = 0;
+	int rc;
 	file_private_info_t *p_info;
 
 	p_info = ((file_private_info_t *) file->private_data);
@@ -458,9 +459,9 @@
 		size = MIN((len - count), (size - entry_offset));
 
 		if(size){
-			if (copy_to_user(user_buf + count, 
-					p_info->temp_buf + entry_offset, size))
-				return count ? count : -EFAULT;
+			if ((rc = copy_to_user(user_buf + count, 
+					p_info->temp_buf + entry_offset, size)))
+			return rc;
 		}
 		count += size;
 		entry_offset = 0;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
--- linux.orig/arch/s390x/kernel/entry.S	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/entry.S	2002-08-12 22:14:09.000000000 +0000
@@ -207,15 +207,15 @@
 # call trace before and after sys_call
 #
 sysc_tracesys:
-	larl	%r12,sysc_return
+	larl	%r11,sysc_return
 
 #
 # call syscall_trace before and after system call
-# special linkage: %r12 contains the return address for trace_svc
+# special linkage: %r11 contains the return address for trace_svc
 #
 trace_svc:
-	lghi    %r7,-ENOSYS
-	stg     %r7,SP_R2(%r15)     # give sysc_trace an -ENOSYS retval
+	lghi    %r0,-ENOSYS
+	stg     %r0,SP_R2(%r15)     # give sysc_trace an -ENOSYS retval
         brasl   %r14,syscall_trace
 	lg      %r2,SP_R2(%r15)
 	cghi    %r2,-ENOSYS
@@ -232,7 +232,7 @@
 	lg      %r2,SP_ORIG_R2(%r15)
         basr    %r14,%r8            # call sys_xxx
         stg     %r2,SP_R2(%r15)     # store return value
-	lgr	%r14,%r12	    # return point is in %r12
+	lgr	%r14,%r11	    # return point is in %r11
         jg      syscall_trace       # return point is sysc_return
 
 #
@@ -712,7 +712,7 @@
 # call trace before and after sys_call
 #
 pgm_tracesys:
-	larl	%r12,pgm_svcret
+	larl	%r11,pgm_svcret
 	j	trace_svc
 
 /*
@@ -786,26 +786,26 @@
 ext_int_handler:
         SAVE_ALL __LC_EXT_OLD_PSW,0
         GET_CURRENT                    # load pointer to task_struct to R9
-        la      %r2,SP_PTREGS(%r15)    # address of register-save area
-        llgh    %r3,__LC_EXT_INT_CODE  # error code
-        lgr     %r1,%r3                # calculate index = code & 0xff
-	nill    %r1,0xff
-        sll     %r1,3
-        larl    %r4,ext_int_hash
-        lg      %r4,0(%r1,%r4)         # get first list entry for hash value
-        ltgr    %r4,%r4                # == NULL ?
-        jz      io_return              # yes, nothing to do, exit
+	llgh	%r6,__LC_EXT_INT_CODE  # get interruption code
+	lgr	%r1,%r6		       # calculate index = code & 0xff
+	nill	%r1,0xff
+	sll	%r1,3
+	larl	%r7,ext_int_hash
+	lg	%r7,0(%r1,%r7)	       # get first list entry for hash value
+	ltgr	%r7,%r7		       # == NULL ?
+	jz	io_return	       # yes, nothing to do, exit
 ext_int_loop:
-        ch      %r3,16(%r4)            # compare external interrupt code
-        je      ext_int_found
-        lg      %r4,0(%r4)             # next list entry
-	ltgr    %r4,%r4
-        jnz     ext_int_loop
-        j       io_return
-ext_int_found:
-        lg      %r4,8(%r4)             # get handler address
-        larl    %r14,io_return
-        br      %r4                    # branch to ext call handler
+	ch	%r6,16(%r7)	       # compare external interrupt code
+	jne	ext_int_next
+	lg	%r1,8(%r7)	       # get handler address
+	la	%r2,SP_PTREGS(%r15)    # address of register-save area
+	lgr	%r3,%r6		       # interruption code
+	basr	%r14,%r1	       # call handler
+ext_int_next:
+	lg	%r7,0(%r7)	       # next list entry
+	ltgr	%r7,%r7
+	jnz	ext_int_loop
+	j	io_return
 
 /*
  * Machine check handler routines
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/head.S linux/arch/s390x/kernel/head.S
--- linux.orig/arch/s390x/kernel/head.S	2001-11-09 21:58:02.000000000 +0000
+++ linux/arch/s390x/kernel/head.S	2002-08-12 22:14:05.000000000 +0000
@@ -326,7 +326,7 @@
         bnz   .Lrdcont
         st    %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it
 .Lrdcont:
-	l     %r2,INITRD_START-PARMAREA(%r12)
+	l     %r2,INITRD_START+4-PARMAREA(%r12)
 	clc   0(3,%r2),.L_hdr		       # skip HDRx and EOFx 
 	bz    .Lagain2
 	clc   0(3,%r2),.L_eof
@@ -555,6 +555,17 @@
 	oi     7(%r12),16               # set MVPG flag
 0:
 
+#
+# find out if the diag 0x44 works in 64 bit mode
+#
+	la     %r1,0f-.LPG1(%r13)	# set program check address
+	stg    %r1,__LC_PGM_NEW_PSW+8
+	mvc    __LC_DIAG44_OPCODE(8),.Lnop-.LPG1(%r13)
+	diag   0,0,0x44			# test diag 0x44
+	oi     7(%r12),32		# set diag44 flag
+	mvc    __LC_DIAG44_OPCODE(8),.Ldiag44-.LPG1(%r13)
+0:	
+
         lpswe .Lentry-.LPG1(13)         # jump to _stext in primary-space,
                                         # virtual and never return ...
         .align 16
@@ -578,6 +589,8 @@
 .Lpcmsk:.quad  0x0000000180000000
 .L4malign:.quad 0xffffffffffc00000
 .Lscan2g:.quad 0x80000000 + 0x20000 - 8 # 2GB + 128K - 8
+.Lnop:	.long  0x07000700
+.Ldiag44:.long 0x83000044
 
 	.org PARMAREA-64
 .Lduct:	.long 0,0,0,0,0,0,0,0
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/process.c linux/arch/s390x/kernel/process.c
--- linux.orig/arch/s390x/kernel/process.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/process.c	2002-08-12 22:14:07.000000000 +0000
@@ -183,6 +183,43 @@
         return 0;
 }
 
+/* 
+ * Allocation and freeing of basic task resources. 
+ * The task struct and the stack go together.
+ *
+ * NOTE: An order-2 allocation can easily fail.  If this
+ *       happens we fall back to using vmalloc ...
+ */
+
+struct task_struct *alloc_task_struct(void)
+{
+	struct task_struct *tsk = __get_free_pages(GFP_KERNEL, 2);
+	if (!tsk)
+		tsk = vmalloc(16384);
+	if (!tsk)
+		return NULL;
+
+        atomic_set((atomic_t *)(tsk + 1), 1);
+        return tsk;
+}
+
+void free_task_struct(struct task_struct *tsk)
+{
+	if (atomic_dec_and_test((atomic_t *)(tsk + 1)))
+	{
+		if ((unsigned long)tsk < VMALLOC_START)
+			free_pages((unsigned long)tsk, 2);
+		else
+			vfree(tsk);
+	}
+}
+
+void get_task_struct(struct task_struct *tsk)
+{
+	atomic_inc((atomic_t *)(tsk + 1));
+}
+
+
 asmlinkage int sys_fork(struct pt_regs regs)
 {
         return do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/ptrace.c linux/arch/s390x/kernel/ptrace.c
--- linux.orig/arch/s390x/kernel/ptrace.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/ptrace.c	2002-08-12 22:14:04.000000000 +0000
@@ -38,6 +38,12 @@
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#ifdef CONFIG_S390_SUPPORT
+#include "linux32.h"
+#else
+#define parent_31bit 0
+#endif
+
 
 void FixPerRegisters(struct task_struct *task)
 {
@@ -122,8 +128,8 @@
 				retval = clear_user(copyptr, len);
 			else
 				retval = copy_to_user(copyptr,realuserptr,len);
-                        retval = (retval == -EFAULT) ? -EIO : 0;
 		}      
+		retval = retval ? -EFAULT : 0;
 	} else {
 		if (writeuser)
 			memcpy(realuserptr, copyptr, len);
@@ -135,48 +141,180 @@
 	return retval;
 }
 
+#ifdef CONFIG_S390_SUPPORT
+
+typedef struct
+{
+	__u32 cr[3];
+} per_cr_words32  __attribute__((packed));
+
+typedef struct
+{
+	__u16          perc_atmid;          /* 0x096 */
+	__u32          address;             /* 0x098 */
+	__u8           access_id;           /* 0x0a1 */
+} per_lowcore_words32  __attribute__((packed));
+
+typedef struct
+{
+	union {
+		per_cr_words32   words;
+	} control_regs  __attribute__((packed));
+	/*
+	 * Use these flags instead of setting em_instruction_fetch
+	 * directly they are used so that single stepping can be
+	 * switched on & off while not affecting other tracing
+	 */
+	unsigned  single_step       : 1;
+	unsigned  instruction_fetch : 1;
+	unsigned                    : 30;
+	/*
+	 * These addresses are copied into cr10 & cr11 if single
+	 * stepping is switched off
+	 */
+	__u32     starting_addr;
+	__u32     ending_addr;
+	union {
+		per_lowcore_words32 words;
+	} lowcore; 
+} per_struct32 __attribute__((packed));
+
+struct user_regs_struct32
+{
+	_psw_t32 psw;
+	u32 gprs[NUM_GPRS];
+	u32 acrs[NUM_ACRS];
+	u32 orig_gpr2;
+	s390_fp_regs fp_regs;
+	/*
+	 * These per registers are in here so that gdb can modify them
+	 * itself as there is no "official" ptrace interface for hardware
+	 * watchpoints. This is the way intel does it.
+	 */
+	per_struct32 per_info;
+	u32  ieee_instruction_pointer; 
+	/* Used to give failing instruction back to user for ieee exceptions */
+};
+
+struct user32 {
+                                  /* We start with the registers, to mimic the way that "memory" is returned
+                                   from the ptrace(3,...) function.  */
+  struct user_regs_struct32 regs; /* Where the registers are actually stored */
+                                  /* The rest of this junk is to help gdb figure out what goes where */
+  u32 u_tsize;	                  /* Text segment size (pages). */
+  u32 u_dsize;	                  /* Data segment size (pages). */
+  u32 u_ssize;	                  /* Stack segment size (pages). */
+  u32 start_code;                 /* Starting virtual address of text. */
+  u32 start_stack;	          /* Starting virtual address of stack area.
+				   This is actually the bottom of the stack,
+				   the top of the stack is always found in the
+				   esp register.  */
+  s32 signal;     		  /* Signal that caused the core dump. */
+  u32 u_ar0;                      /* Used by gdb to help find the values for */
+				  /* the registers. */
+  u32 magic;		          /* To uniquely identify a core file */
+  char u_comm[32];		  /* User command that was responsible */
+};
+
+
+#define PT32_PSWMASK  0x0
+#define PT32_PSWADDR  0x04
+#define PT32_GPR0     0x08
+#define PT32_GPR15    0x44
+#define PT32_ACR0     0x48
+#define PT32_ACR15    0x84
+#define PT32_ORIGGPR2 0x88
+#define PT32_FPC      0x90
+#define PT32_FPR0_HI  0x98
+#define PT32_FPR15_LO 0x114
+#define PT32_CR_9     0x118
+#define PT32_CR_11    0x120
+#define PT32_IEEE_IP  0x13C
+#define PT32_LASTOFF  PT32_IEEE_IP
+#define PT32_ENDREGS  0x140-1
+#define U32OFFSETOF(member) offsetof(struct user32,regs.member)
+#define U64OFFSETOF(member) offsetof(struct user,regs.member)
+#define U6432DIFF(member) (U64OFFSETOF(member) - U32OFFSETOF(member))
+#define PT_SINGLE_STEP   (PT_CR_11+8)
+#define PT32_SINGLE_STEP (PT32_CR_11+4)
+
+#endif /* CONFIG_S390_SUPPORT */
+
 int copy_user(struct task_struct *task,saddr_t useraddr, addr_t copyaddr,
               int len, int tofromuser, int writingtouser)
 {
 	int copylen=0,copymax;
 	addr_t  realuseraddr;
 	saddr_t enduseraddr;
-	
 	unsigned long mask;
-
 #ifdef CONFIG_S390_SUPPORT
-	if (current->thread.flags & S390_FLAG_31BIT) {
-	/* adjust user offsets to 64 bit structure */
-		if (useraddr < PT_PSWADDR / 2)
-			useraddr = 2 * useraddr;
-		else if(useraddr < PT_ACR0 / 2)
-			useraddr = 2 * useraddr + sizeof(addr_t) / 2;
-		else if(useraddr < PT_ACR0 / 2 + (PT_ORIGGPR2 - PT_ACR0))
-			useraddr = useraddr + PT_ACR0 / 2;
-		else if(useraddr < PT_ACR0 / 2 + (sizeof(struct user_regs_struct) - sizeof(addr_t) / 2 - PT_ACR0))
-			useraddr = useraddr + PT_ACR0 / 2 + sizeof(addr_t) / 2; 
-        }
-#endif  
-    
+	int     parent_31bit=current->thread.flags & S390_FLAG_31BIT;
+	int     skip;
+#endif
 	enduseraddr=useraddr+len;
-
-	if (useraddr < 0 || enduseraddr > sizeof(struct user)||
-	   (useraddr < PT_ENDREGS && (useraddr&3))||
-	   (enduseraddr < PT_ENDREGS && (enduseraddr&3)))
+	if ((useraddr<0||useraddr&3||enduseraddr&3)||
+#ifdef CONFIG_S390_SUPPORT
+	    (parent_31bit && enduseraddr > sizeof(struct user32)) ||
+#endif
+	    enduseraddr > sizeof(struct user))
 		return (-EIO);
+
+#ifdef CONFIG_S390_SUPPORT
+	if(parent_31bit)
+	{
+		if(useraddr != PT32_PSWMASK)
+		{
+			if (useraddr == PT32_PSWADDR)
+				useraddr = PT_PSWADDR+4;
+			else if(useraddr <= PT32_GPR15)
+				useraddr = ((useraddr-PT32_GPR0)*2) + PT_GPR0+4;
+			else if(useraddr <= PT32_ACR15)
+				useraddr += PT_ACR0-PT32_ACR0;
+			else if(useraddr == PT32_ORIGGPR2)
+				useraddr = PT_ORIGGPR2+4;
+			else if(useraddr <= PT32_FPR15_LO)
+				useraddr += PT_FPR0-PT32_FPR0_HI;
+			else if(useraddr <= PT32_CR_11)
+				useraddr = ((useraddr-PT32_CR_9)*2) + PT_CR_9+4;
+			else if(useraddr ==  PT32_SINGLE_STEP)
+				useraddr = PT_SINGLE_STEP; 
+			else if(useraddr <= U32OFFSETOF(per_info.ending_addr))	
+				useraddr = (((useraddr-U32OFFSETOF(per_info.starting_addr)))*2) + 
+					U64OFFSETOF(per_info.starting_addr)+4;
+			else if( useraddr == U32OFFSETOF(per_info.lowcore.words.perc_atmid))
+				useraddr = U64OFFSETOF(per_info.lowcore.words.perc_atmid);
+			else if( useraddr == U32OFFSETOF(per_info.lowcore.words.address))
+				useraddr = U64OFFSETOF(per_info.lowcore.words.address)+4;
+			else if(useraddr == U32OFFSETOF(per_info.lowcore.words.access_id))
+				useraddr = U64OFFSETOF(per_info.lowcore.words.access_id);
+			else if(useraddr == PT32_IEEE_IP)
+				useraddr = PT_IEEE_IP+4;
+		}
+	}
+#endif /* CONFIG_S390_SUPPORT */
+
 	while(len>0)
 	{
+#ifdef CONFIG_S390_SUPPORT
+		skip=0;
+#endif
 		mask=PSW_ADDR_MASK;
 		if(useraddr<PT_FPC)
 		{
 			realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr;
-			if(useraddr<PT_PSWMASK)
+			if(useraddr<(PT_PSWMASK+8))
 			{
-				copymax=PT_PSWMASK;
-			}
-			else if(useraddr<(PT_PSWMASK+8))
-			{
-				copymax=(PT_PSWMASK+8);
+				if(parent_31bit)
+				{
+					copymax=PT_PSWMASK+4;
+#ifdef CONFIG_S390_SUPPORT
+					skip=8;
+#endif
+				}
+				else
+				{
+					copymax=PT_PSWMASK+8;
+				}
 				if(writingtouser)
 					mask=PSW_MASK_DEBUGCHANGE;
 			}
@@ -184,10 +322,25 @@
 			{
 				copymax=PT_PSWADDR+8;
 				mask=PSW_ADDR_DEBUGCHANGE;
+#ifdef CONFIG_S390_SUPPORT
+				if(parent_31bit)
+					skip=4;
+#endif
+
 			}
 			else
-				copymax=PT_FPC;
-			
+			{
+#ifdef CONFIG_S390_SUPPORT
+				if(parent_31bit && useraddr <= PT_GPR15+4)
+				{
+					copymax=useraddr+4;
+					if(useraddr<PT_GPR15+4)
+						skip=4;
+				}
+				else
+#endif
+					copymax=PT_FPC;
+			}
 		}
 		else if(useraddr<(PT_FPR15+sizeof(freg_t)))
 		{
@@ -196,7 +349,33 @@
 		}
 		else if(useraddr<sizeof(struct user_regs_struct))
 		{
-			copymax=sizeof(struct user_regs_struct);
+#ifdef CONFIG_S390_SUPPORT
+			if( parent_31bit && useraddr <= PT_IEEE_IP+4)
+			{
+				switch(useraddr)
+				{
+				case PT_CR_11+4:
+				case U64OFFSETOF(per_info.ending_addr)+4:
+				case U64OFFSETOF(per_info.lowcore.words.address)+4:
+					copymax=useraddr+4;
+					break;
+				case  PT_SINGLE_STEP:
+				case  U64OFFSETOF(per_info.lowcore.words.perc_atmid):
+					/* We copy 2 bytes in excess for the atmid member this also gets around */
+					/* alignment for this member in 32 bit */
+					skip=8;
+					copymax=useraddr+4;
+					break;
+				default: 
+					copymax=useraddr+4;
+					skip=4;
+				}
+			}
+			else
+#endif
+			{
+				copymax=sizeof(struct user_regs_struct);
+			}
 			realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]);
 		}
 		else 
@@ -210,7 +389,11 @@
 			return (-EIO);
 		copyaddr+=copylen;
 		len-=copylen;
-		useraddr+=copylen;
+		useraddr+=copylen
+#if CONFIG_S390_SUPPORT
+			+skip
+#endif
+			;
 	}
 	FixPerRegisters(task);
 	return(0);
@@ -227,150 +410,6 @@
 	clear_single_step(child);
 }
 
-asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
-{
-	struct task_struct *child;
-	int ret = -EPERM;
-	unsigned long flags;
-	unsigned long tmp;
-	int copied;
-	ptrace_area   parea; 
-
-	lock_kernel();
-	if (request == PTRACE_TRACEME) 
-	{
-		/* are we already being traced? */
-		if (current->ptrace & PT_PTRACED)
-			goto out;
-		/* set the ptrace bit in the process flags. */
-		current->ptrace |= PT_PTRACED;
-		ret = 0;
-		goto out;
-	}
-	ret = -ESRCH;
-	read_lock(&tasklist_lock);
-	child = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);
-	if (!child)
-		goto out;
-	ret = -EPERM;
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
-	if (request == PTRACE_ATTACH) 
-	{
-		ret = ptrace_attach(child);
-		goto out;
-	}
-	ret = -ESRCH;
-	// printk("child=%lX child->flags=%lX",child,child->flags);
-	/* I added child!=current line so we can get the */
-	/* ieee_instruction_pointer from the user structure DJB */
-	if(child!=current)
-	{
-		if (!(child->ptrace & PT_PTRACED))
-			goto out;
-		if (child->state != TASK_STOPPED) 
-		{
-			if (request != PTRACE_KILL)
-				goto out;
-		}
-		if (child->p_pptr != current)
-			goto out;
-	}
-	switch (request) 
-	{
-		/* If I and D space are separate, these will need to be fixed. */
-	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
-	case PTRACE_PEEKDATA: 
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
-		ret = -EIO;
-		if (copied != sizeof(tmp))
-			goto out;
-		ret = put_user(tmp,(unsigned long *) data);
-		goto out;
-
-		/* read the word at location addr in the USER area. */
-	case PTRACE_PEEKUSR:
-		ret=copy_user(child,addr,data,sizeof(unsigned long),1,0);
-		break;
-
-		/* If I and D space are separate, this will have to be fixed. */
-	case PTRACE_POKETEXT: /* write the word at location addr. */
-	case PTRACE_POKEDATA:
-		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			goto out;
-		ret = -EIO;
-		goto out;
-		break;
-
-	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-		ret=copy_user(child,addr,(addr_t)&data,sizeof(unsigned long),0,1);
-		break;
-
-	case PTRACE_SYSCALL: 	/* continue and stop at next (return from) syscall */
-	case PTRACE_CONT: 	 /* restart after signal. */
-		ret = -EIO;
-		if ((unsigned long) data >= _NSIG)
-			break;
-		if (request == PTRACE_SYSCALL)
-			child->ptrace |= PT_TRACESYS;
-		else
-			child->ptrace &= ~PT_TRACESYS;
-		child->exit_code = data;
-		/* make sure the single step bit is not set. */
-		clear_single_step(child);
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-/*
- * make the child exit.  Best I can do is send it a sigkill. 
- * perhaps it should be put in the status that it wants to 
- * exit.
- */
-	case PTRACE_KILL:
-		ret = 0;
-		if (child->state == TASK_ZOMBIE) /* already dead */
-			break;
-		child->exit_code = SIGKILL;
-		clear_single_step(child);
-		wake_up_process(child);
-		/* make sure the single step bit is not set. */
-		break;
-
-	case PTRACE_SINGLESTEP:  /* set the trap flag. */
-		ret = -EIO;
-		if ((unsigned long) data >= _NSIG)
-			break;
-		child->ptrace &= ~PT_TRACESYS;
-		child->exit_code = data;
-		set_single_step(child);
-		/* give it a chance to run. */
-		wake_up_process(child);
-		ret = 0;
-		break;
-
-	case PTRACE_DETACH:  /* detach a process that was attached. */
-		ret = ptrace_detach(child, data);
-		break;
-
-	case PTRACE_PEEKUSR_AREA:
-	case PTRACE_POKEUSR_AREA:
-		if(copy_from_user(&parea,(void *)addr,sizeof(parea)) == 0)  
-			ret=copy_user(child,parea.kernel_addr,parea.process_addr,
-				 parea.len,1,(request==PTRACE_POKEUSR_AREA));
-		else ret = -EFAULT;
-		break;
-	default:
-		ret = -EIO;
-		break;
-	}
- out:
-	unlock_kernel();
-	return ret;
-}
-
 typedef struct
 {
 __u32	len;
@@ -378,15 +417,20 @@
 __u32	process_addr;
 } ptrace_area_emu31;
 
-asmlinkage int sys32_ptrace(long request, long pid, long addr, s32 data)
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
 {
 	struct task_struct *child;
 	int ret = -EPERM;
-	unsigned long flags;
-	u32 tmp;
 	int copied;
-	ptrace_area   parea; 
-
+#ifdef CONFIG_S390_SUPPORT
+	int           parent_31bit;
+	int           sizeof_parent_long;
+	u8            *dataptr;
+#else
+#define sizeof_parent_long 8
+#define dataptr (u8 *)&data
+#endif
 	lock_kernel();
 	if (request == PTRACE_TRACEME) 
 	{
@@ -401,16 +445,18 @@
 	ret = -ESRCH;
 	read_lock(&tasklist_lock);
 	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
-		goto out;
+		goto out_tsk;
 	if (request == PTRACE_ATTACH) 
 	{
 		ret = ptrace_attach(child);
-		goto out;
+		goto out_tsk;
 	}
 	ret = -ESRCH;
 	// printk("child=%lX child->flags=%lX",child,child->flags);
@@ -419,44 +465,52 @@
 	if(child!=current)
 	{
 		if (!(child->ptrace & PT_PTRACED))
-			goto out;
+			goto out_tsk;
 		if (child->state != TASK_STOPPED) 
 		{
 			if (request != PTRACE_KILL)
-				goto out;
+				goto out_tsk;
 		}
 		if (child->p_pptr != current)
-			goto out;
+			goto out_tsk;
 	}
+#ifdef CONFIG_S390_SUPPORT
+	parent_31bit=(current->thread.flags & S390_FLAG_31BIT);
+	sizeof_parent_long=(parent_31bit ? 4:8);
+	dataptr=&(((u8 *)&data)[parent_31bit ? 4:0]);
+#endif
 	switch (request) 
 	{
 		/* If I and D space are separate, these will need to be fixed. */
 	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
 	case PTRACE_PEEKDATA: 
-		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+	{
+		u8 tmp[8];
+		copied = access_process_vm(child, addr, tmp, sizeof_parent_long, 0);
 		ret = -EIO;
-		if (copied != sizeof(tmp))
-			goto out;
-		ret = put_user(tmp,(u32 *)(unsigned long)data);
-		goto out;
-
+		if (copied != sizeof_parent_long)
+			break;
+		ret = copy_to_user((void *)data,tmp,sizeof_parent_long);
+		ret = ret ? -EFAULT : 0;
+		break;
+	
+	}
 		/* read the word at location addr in the USER area. */
 	case PTRACE_PEEKUSR:
-		ret=copy_user(child,addr,data,sizeof(u32),1,0);
+		ret=copy_user(child,addr,data,sizeof_parent_long,1,0);
 		break;
 
 		/* If I and D space are separate, this will have to be fixed. */
 	case PTRACE_POKETEXT: /* write the word at location addr. */
 	case PTRACE_POKEDATA:
 		ret = 0;
-		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
-			goto out;
+		if (access_process_vm(child, addr,dataptr, sizeof_parent_long, 1) == sizeof_parent_long)
+			break;
 		ret = -EIO;
-		goto out;
 		break;
 
 	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-		ret=copy_user(child,addr,(addr_t)&data,sizeof(u32),0,1);
+		ret=copy_user(child,addr,(addr_t)dataptr,sizeof_parent_long,0,1);
 		break;
 
 	case PTRACE_SYSCALL: 	/* continue and stop at next (return from) syscall */
@@ -503,44 +557,41 @@
 		break;
 
 	case PTRACE_DETACH:  /* detach a process that was attached. */
-		ret = -EIO;
-		if ((unsigned long) data >= _NSIG)
-			break;
-		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
-		child->exit_code = data;
-		write_lock_irqsave(&tasklist_lock, flags);
-		REMOVE_LINKS(child);
-		child->p_pptr = child->p_opptr;
-		SET_LINKS(child);
-		write_unlock_irqrestore(&tasklist_lock, flags);
-		/* make sure the single step bit is not set. */
-		clear_single_step(child);
-		wake_up_process(child);
-		ret = 0;
+		ret = ptrace_detach(child, data);
 		break;
+
 	case PTRACE_PEEKUSR_AREA:
 	case PTRACE_POKEUSR_AREA:
+		if(parent_31bit)
 		{
-		ptrace_area_emu31 * parea31 = (void *)addr;
-		if (!access_ok(VERIFY_READ, parea31, sizeof(*parea31)))
-			return(-EFAULT);
-		ret = __get_user(parea.len, &parea31->len);
-		ret |= __get_user(parea.kernel_addr, &parea31->kernel_addr);
-		ret |= __get_user(parea.process_addr, &parea31->process_addr);
-		if(ret==0)  
-		   ret=copy_user(child,parea.kernel_addr,parea.process_addr,
-				 parea.len,1,(request==PTRACE_POKEUSR_AREA));
-		break;
+			ptrace_area_emu31   parea; 
+			if(copy_from_user(&parea,(void *)addr,sizeof(parea))==0)
+				ret=copy_user(child,parea.kernel_addr,parea.process_addr,
+					      parea.len,1,(request==PTRACE_POKEUSR_AREA));
+			else ret = -EFAULT;
 		}
+		else
+		{
+			ptrace_area   parea; 
+			if(copy_from_user(&parea,(void *)addr,sizeof(parea))==0)
+				ret=copy_user(child,parea.kernel_addr,parea.process_addr,
+					      parea.len,1,(request==PTRACE_POKEUSR_AREA));
+			else ret = -EFAULT;
+		}
+		break;
 	default:
 		ret = -EIO;
 		break;
 	}
+ out_tsk:
+	free_task_struct(child);
  out:
 	unlock_kernel();
 	return ret;
 }
 
+
+
 asmlinkage void syscall_trace(void)
 {
 	lock_kernel();
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/s390_ext.c linux/arch/s390x/kernel/s390_ext.c
--- linux.orig/arch/s390x/kernel/s390_ext.c	2001-07-25 21:12:01.000000000 +0000
+++ linux/arch/s390x/kernel/s390_ext.c	2002-08-12 22:14:07.000000000 +0000
@@ -21,34 +21,31 @@
  * iucv and 0x2603 pfault) this is always the first element. 
  */
 ext_int_info_t *ext_int_hash[256] = { 0, };
-ext_int_info_t ext_int_info_timer;
-ext_int_info_t ext_int_info_hwc;
-ext_int_info_t ext_int_pfault;
 
 int register_external_interrupt(__u16 code, ext_int_handler_t handler) {
         ext_int_info_t *p;
         int index;
 
-        index = code & 0xff;
-        p = ext_int_hash[index];
-        while (p != NULL) {
-                if (p->code == code)
-                        return -EBUSY;
-                p = p->next;
-        }
-        if (code == 0x1004) /* time_init is done before kmalloc works :-/ */
-                p = &ext_int_info_timer;
-        else if (code == 0x2401) /* hwc_init is done too early too */
-                p = &ext_int_info_hwc;
-        else if (code == 0x2603) /* pfault_init is done too early too */
-                p = &ext_int_pfault;
-        else
-                p = (ext_int_info_t *)
-                          kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+	p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
         if (p == NULL)
                 return -ENOMEM;
         p->code = code;
         p->handler = handler;
+        index = code & 0xff;
+        p->next = ext_int_hash[index];
+        ext_int_hash[index] = p;
+        return 0;
+}
+
+int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
+				      ext_int_info_t *p) {
+        int index;
+
+        if (p == NULL)
+                return -EINVAL;
+        p->code = code;
+        p->handler = handler;
+        index = code & 0xff;
         p->next = ext_int_hash[index];
         ext_int_hash[index] = p;
         return 0;
@@ -73,11 +70,33 @@
                 q->next = p->next;
         else
                 ext_int_hash[index] = p->next;
-        if (code != 0x1004 && code != 0x2401 && code != 0x2603)
-                kfree(p);
+	kfree(p);
         return 0;
 }
 
+int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
+					ext_int_info_t *p) {
+	ext_int_info_t *q;
+	int index;
+
+	if (p == NULL || p->code != code || p->handler != handler)
+		return -EINVAL;
+	index = code & 0xff;
+	q = ext_int_hash[index];
+	if (p != q) {
+		while (q != NULL) {
+			if (q->next == p)
+				break;
+			q = q->next;
+		}
+		if (q == NULL)
+			return -ENOENT;
+		q->next = p->next;
+	} else
+		ext_int_hash[index] = p->next;
+	return 0;
+}
+
 EXPORT_SYMBOL(register_external_interrupt);
 EXPORT_SYMBOL(unregister_external_interrupt);
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/s390_ksyms.c linux/arch/s390x/kernel/s390_ksyms.c
--- linux.orig/arch/s390x/kernel/s390_ksyms.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/s390_ksyms.c	2002-08-12 22:14:10.000000000 +0000
@@ -12,6 +12,7 @@
 #include <asm/delay.h>
 #include <asm/pgalloc.h>
 #include <asm/setup.h>
+#include <asm/softirq.h>
 #if CONFIG_IP_MULTICAST
 #include <net/arp.h>
 #endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/setup.c linux/arch/s390x/kernel/setup.c
--- linux.orig/arch/s390x/kernel/setup.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/setup.c	2002-08-12 22:14:15.000000000 +0000
@@ -165,15 +165,15 @@
 static int __init conmode_setup(char *str)
 {
 #if defined(CONFIG_HWC_CONSOLE)
-	if (strncmp(str, "hwc", 4) == 0 && !MACHINE_IS_P390)
+	if (strncmp(str, "hwc", 4) == 0)
                 SET_CONSOLE_HWC;
 #endif
 #if defined(CONFIG_TN3215_CONSOLE)
-	if (strncmp(str, "3215", 5) == 0 && (MACHINE_IS_VM || MACHINE_IS_P390))
+	if (strncmp(str, "3215", 5) == 0)
 		SET_CONSOLE_3215;
 #endif
 #if defined(CONFIG_TN3270_CONSOLE)
-	if (strncmp(str, "3270", 5) == 0 && (MACHINE_IS_VM || MACHINE_IS_P390))
+	if (strncmp(str, "3270", 5) == 0)
 		SET_CONSOLE_3270;
 #endif
         return 1;
@@ -233,31 +233,63 @@
 	}
 }
 
+#ifdef CONFIG_SMP
+extern void machine_restart_smp(char *);
+extern void machine_halt_smp(void);
+extern void machine_power_off_smp(void);
+
+void (*_machine_restart)(char *command) = machine_restart_smp;
+void (*_machine_halt)(void) = machine_halt_smp;
+void (*_machine_power_off)(void) = machine_power_off_smp;
+#else
 /*
  * Reboot, halt and power_off routines for non SMP.
  */
-#ifndef CONFIG_SMP
-void machine_restart(char * __unused)
+static void do_machine_restart_nonsmp(char * __unused)
 {
 	reipl(S390_lowcore.ipl_device);
 }
 
-void machine_halt(void)
+static void do_machine_halt_nonsmp(void)
 {
         if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
                 cpcmd(vmhalt_cmd, NULL, 0);
         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
-void machine_power_off(void)
+static void do_machine_power_off_nonsmp(void)
 {
         if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
                 cpcmd(vmpoff_cmd, NULL, 0);
         signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
+
+void (*_machine_restart)(char *command) = do_machine_restart_nonsmp;
+void (*_machine_halt)(void) = do_machine_halt_nonsmp;
+void (*_machine_power_off)(void) = do_machine_power_off_nonsmp;
 #endif
 
 /*
+ * Reboot, halt and power_off stubs. They just call _machine_restart,
+ * _machine_halt or _machine_power_off. 
+ */
+
+void machine_restart(char *command)
+{
+	_machine_restart(command);
+}
+
+void machine_halt(void)
+{
+	_machine_halt();
+}
+
+void machine_power_off(void)
+{
+	_machine_power_off();
+}
+
+/*
  * Setup function called from init/main.c just after the banner
  * was printed.
  */
@@ -429,6 +461,10 @@
 	lowcore->async_stack = (__u64)
 		__alloc_bootmem(4*PAGE_SIZE, 4*PAGE_SIZE, 0) + 16384;
 	lowcore->jiffy_timer = -1LL;
+	if (MACHINE_HAS_DIAG44)
+		lowcore->diag44_opcode = 0x83000044;
+	else
+		lowcore->diag44_opcode = 0x07000700;
 	set_prefix((__u32)(__u64) lowcore);
         cpu_init();
         boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
@@ -486,7 +522,7 @@
 	}
 	if (cpu_online_map & (1 << n)) {
 		cpuinfo = &safe_get_cpu_lowcore(n)->cpu_data;
-		seq_printf(m, "processor %i: "
+		seq_printf(m, "processor %li: "
 				"version = %02X,  "
 				"identification = %06X,  "
 				"machine = %04X\n",
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/signal.c linux/arch/s390x/kernel/signal.c
--- linux.orig/arch/s390x/kernel/signal.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/signal.c	2002-08-12 22:14:03.000000000 +0000
@@ -333,6 +333,10 @@
 			goto give_sigsegv;
 	}
 
+	/* Set up backchain. */
+	if (__put_user(regs->gprs[15], (addr_t *) frame))
+		goto give_sigsegv;
+
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (addr_t)frame;
 	regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
@@ -386,6 +390,10 @@
 	                          (u16 *)(frame->retcode));
 	}
 
+	/* Set up backchain. */
+	if (__put_user(regs->gprs[15], (addr_t *) frame))
+		goto give_sigsegv;
+
 	/* Set up registers for signal handler */
 	regs->gprs[15] = (addr_t)frame;
 	regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
@@ -567,7 +575,10 @@
                                 /* FALLTHRU */
 
 			default:
-				sig_exit(signr, exit_code, &info);
+				sigaddset(&current->pending.signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
 				/* NOTREACHED */
 			}
 		}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/smp.c linux/arch/s390x/kernel/smp.c
--- linux.orig/arch/s390x/kernel/smp.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/smp.c	2002-08-12 22:14:21.000000000 +0000
@@ -176,61 +176,137 @@
 	return 0;
 }
 
+static inline void do_send_stop(void)
+{
+        u32 dummy;
+        int i;
+
+        /* stop all processors */
+        for (i =  0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        int ccode;
+                        do {
+                                ccode = signal_processor_ps(
+                                   &dummy,
+                                   0,
+                                   i,
+                                   sigp_stop);
+                        } while(ccode == sigp_busy);
+                }
+        }
+}
+
+static inline void do_store_status(void)
+{
+        unsigned long low_core_addr;
+        u32 dummy;
+        int i;
+
+        /* store status of all processors in their lowcores (real 0) */
+        for (i =  0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        int ccode;
+                        low_core_addr = (unsigned long)get_cpu_lowcore(i);
+                        do {
+                                ccode = signal_processor_ps(
+                                   &dummy,
+                                   low_core_addr,
+                                   i,
+                                   sigp_store_status_at_address);
+                        } while(ccode == sigp_busy);
+                }
+        }
+}
 
 /*
- * Various special callbacks
+ * this function sends a 'stop' sigp to all other CPUs in the system.
+ * it goes straight through.
  */
+void smp_send_stop(void)
+{
+        int i;
+        u32 dummy;
+        unsigned long low_core_addr;
+
+        /* write magic number to zero page (absolute 0) */
+        get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
+
+	/* stop other processors. */
+	do_send_stop();
+
+	/* store status of other processors. */
+	do_store_status();
+}
 
-void do_machine_restart(void)
+
+/*
+ * Reboot, halt and power_off routines for SMP.
+ */
+static volatile unsigned long cpu_restart_map;
+
+static void do_machine_restart(void * __unused)
 {
-        smp_send_stop();
-	reipl(S390_lowcore.ipl_device);
+	clear_bit(smp_processor_id(), &cpu_restart_map);
+	if (smp_processor_id() == 0) {
+		/* Wait for all other cpus to enter do_machine_restart. */
+		while (cpu_restart_map != 0);
+		/* Store status of other cpus. */
+		do_store_status();
+		/*
+		 * Finally call reipl. Because we waited for all other
+		 * cpus to enter this function we know that they do
+		 * not hold any s390irq-locks (the cpus have been
+		 * interrupted by an external interrupt and s390irq
+		 * locks are always held disabled).
+		 */
+		reipl(S390_lowcore.ipl_device);
+	}
+	signal_processor(smp_processor_id(), sigp_stop);
 }
 
-void machine_restart(char * __unused) 
+void machine_restart_smp(char * __unused) 
 {
-        if (smp_processor_id() != 0) {
-                smp_ext_bitcall(0, ec_restart);
-		for (;;)
-			enabled_wait();
-        } else
-                do_machine_restart();
+	cpu_restart_map = cpu_online_map;
+        smp_call_function(do_machine_restart, NULL, 0, 0);
+	do_machine_restart(NULL);
 }
 
-void do_machine_halt(void)
+static void do_machine_halt(void * __unused)
 {
-        smp_send_stop();
-        if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
-                cpcmd(vmhalt_cmd, NULL, 0);
-        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+	if (smp_processor_id() == 0) {
+		smp_send_stop();
+		if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+			cpcmd(vmhalt_cmd, NULL, 0);
+		signal_processor(smp_processor_id(),
+				 sigp_stop_and_store_status);
+	}
+	for (;;)
+		enabled_wait();
 }
 
-void machine_halt(void)
+void machine_halt_smp(void)
 {
-        if (smp_processor_id() != 0) {
-                smp_ext_bitcall(0, ec_halt);
-		for (;;)
-			enabled_wait();
-        } else
-                do_machine_halt();
+        smp_call_function(do_machine_halt, NULL, 0, 0);
+	do_machine_halt(NULL);
 }
 
-void do_machine_power_off(void)
+static void do_machine_power_off(void * __unused)
 {
-        smp_send_stop();
-        if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
-                cpcmd(vmpoff_cmd, NULL, 0);
-        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+	if (smp_processor_id() == 0) {
+		smp_send_stop();
+		if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+			cpcmd(vmpoff_cmd, NULL, 0);
+		signal_processor(smp_processor_id(),
+				 sigp_stop_and_store_status);
+	}
+	for (;;)
+		enabled_wait();
 }
 
-void machine_power_off(void)
+void machine_power_off_smp(void)
 {
-        if (smp_processor_id() != 0) {
-                smp_ext_bitcall(0, ec_power_off);
-		for (;;)
-			enabled_wait();
-        } else
-                do_machine_power_off();
+        smp_call_function(do_machine_power_off, NULL, 0, 0);
+	do_machine_power_off(NULL);
 }
 
 /*
@@ -247,17 +323,9 @@
          *
          * For the ec_schedule signal we have to do nothing. All the work
          * is done automatically when we return from the interrupt.
-	 * For the ec_restart, ec_halt and ec_power_off we call the
-         * appropriate routine.
          */
 	bits = xchg(&S390_lowcore.ext_call_fast, 0);
 
-        if (test_bit(ec_restart, &bits))
-		do_machine_restart();
-        if (test_bit(ec_halt, &bits))
-		do_machine_halt();
-        if (test_bit(ec_power_off, &bits))
-		do_machine_power_off();
         if (test_bit(ec_call_function, &bits))
 		do_call_function();
 }
@@ -300,53 +368,6 @@
 }
 
 /*
- * this function sends a 'stop' sigp to all other CPUs in the system.
- * it goes straight through.
- */
-
-void smp_send_stop(void)
-{
-        int i;
-        u32 dummy;
-        unsigned long low_core_addr;
-
-        /* write magic number to zero page (absolute 0) */
-
-        get_cpu_lowcore(smp_processor_id())->panic_magic = __PANIC_MAGIC;
-
-        /* stop all processors */
-
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() != i) {
-                        int ccode;
-                        do {
-                                ccode = signal_processor_ps(
-                                   &dummy,
-                                   0,
-                                   i,
-                                   sigp_stop);
-                        } while(ccode == sigp_busy);
-                }
-        }
-
-        /* store status of all processors in their lowcores (real 0) */
-
-        for (i =  0; i < smp_num_cpus; i++) {
-                if (smp_processor_id() != i) {
-                        int ccode;
-                        low_core_addr = (unsigned long)get_cpu_lowcore(i);
-                        do {
-                                ccode = signal_processor_ps(
-                                   &dummy,
-                                   low_core_addr,
-                                   i,
-                                   sigp_store_status_at_address);
-                        } while(ccode == sigp_busy);
-                }
-        }
-}
-
-/*
  * this function sends a 'reschedule' IPI to another CPU.
  * it goes straight through and wastes no time serializing
  * anything. Worst case is that we lose a reschedule ...
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/sys_s390.c linux/arch/s390x/kernel/sys_s390.c
--- linux.orig/arch/s390x/kernel/sys_s390.c	2001-04-12 02:02:29.000000000 +0000
+++ linux/arch/s390x/kernel/sys_s390.c	2002-08-12 22:14:14.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
+#include <linux/personality.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -203,3 +204,30 @@
 	return -ERESTARTNOHAND;
 }
 
+extern asmlinkage int sys_newuname(struct new_utsname * name);
+
+asmlinkage int s390x_newuname(struct new_utsname * name)
+{
+	int ret = sys_newuname(name);
+
+	if (current->personality == PER_LINUX32 && !ret) {
+		ret = copy_to_user(name->machine, "s390\0\0\0\0", 8);
+		if (ret) ret = -EFAULT;
+	}
+	return ret;
+}
+
+extern asmlinkage long sys_personality(unsigned long);
+
+asmlinkage int s390x_personality(unsigned long personality)
+{
+	int ret;
+
+	if (current->personality == PER_LINUX32 && personality == PER_LINUX)
+		personality = PER_LINUX32;
+	ret = sys_personality(personality);
+	if (ret == PER_LINUX32)
+		ret = PER_LINUX;
+
+	return ret;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/time.c linux/arch/s390x/kernel/time.c
--- linux.orig/arch/s390x/kernel/time.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/time.c	2002-08-12 22:14:10.000000000 +0000
@@ -39,6 +39,7 @@
 
 #define TICK_SIZE tick
 
+static ext_int_info_t ext_int_info_timer;
 static uint64_t init_timer_cc;
 
 extern rwlock_t xtime_lock;
@@ -197,7 +198,8 @@
         tod_to_timeval(set_time_cc, &xtime);
 
         /* request the 0x1004 external interrupt */
-        if (register_external_interrupt(0x1004, do_comparator_interrupt) != 0)
+        if (register_early_external_interrupt(0x1004, do_comparator_interrupt,
+					      &ext_int_info_timer) != 0)
                 panic("Couldn't request external interrupt 0x1004");
 
         /* init CPU timer */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/kernel/traps.c linux/arch/s390x/kernel/traps.c
--- linux.orig/arch/s390x/kernel/traps.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/kernel/traps.c	2002-08-12 22:14:24.000000000 +0000
@@ -60,6 +60,7 @@
 extern int pfault_init(void);
 extern void pfault_fini(void);
 extern void pfault_interrupt(struct pt_regs *regs, __u16 error_code);
+static ext_int_info_t ext_int_pfault;
 #endif
 
 int kstack_depth_to_print = 20;
@@ -499,15 +500,17 @@
 #ifdef CONFIG_PFAULT
 	if (MACHINE_IS_VM) {
 		/* request the 0x2603 external interrupt */
-		if (register_external_interrupt(0x2603, pfault_interrupt) != 0)
+		if (register_early_external_interrupt(0x2603, pfault_interrupt,
+						      &ext_int_pfault) != 0)
 			panic("Couldn't request external interrupt 0x2603");
 		/*
 		 * Try to get pfault pseudo page faults going.
 		 */
 		if (pfault_init() != 0) {
 			/* Tough luck, no pfault. */
-			unregister_external_interrupt(0x2603,
-						      pfault_interrupt);
+			unregister_early_external_interrupt(0x2603,
+							    pfault_interrupt,
+							    &ext_int_pfault);
 		}
 	}
 #endif
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/s390x/mm/init.c linux/arch/s390x/mm/init.c
--- linux.orig/arch/s390x/mm/init.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/s390x/mm/init.c	2002-08-12 22:14:13.000000000 +0000
@@ -44,6 +44,74 @@
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
 char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
 
+pmd_t *pgd_populate(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmd)
+{
+        unsigned long addr = (unsigned long) pgd;
+        unsigned long *pgd_slot =  (unsigned long *) (addr & -8);
+        unsigned long offset = addr & 4;
+	pmd_t *new, *pmd2;
+	int i;
+ 
+        if (offset == 0 && 
+	    ((*pgd_slot & _PGD_ENTRY_INV) != 0 ||
+	     (*pgd_slot & _PGD_ENTRY_LEN(2)) == 0)) {
+                /* Set lower pmd, upper pmd is empty. */
+                *pgd_slot = __pa(pmd) | _PGD_ENTRY_MASK |
+                                _PGD_ENTRY_OFF(0) | _PGD_ENTRY_LEN(1);
+                return pmd;
+        }
+        if (offset == 4 &&
+	    ((*pgd_slot & _PGD_ENTRY_INV) != 0 ||
+	     (*pgd_slot & _PGD_ENTRY_OFF(2)) != 0)) {
+                /* Lower pmd empty, set upper pmd. */
+                *pgd_slot = (__pa(pmd) - 0x2000) | _PGD_ENTRY_MASK |
+                                _PGD_ENTRY_OFF(2) | _PGD_ENTRY_LEN(3);
+                return pmd;
+        }
+        /* We have to enlarge the pmd to 16K if we arrive here. */
+	new = (pmd_t *) __get_free_pages(GFP_KERNEL, 2);
+	if (new == NULL) {
+		pmd_free(pmd);
+		return NULL;
+	}
+	/* Set the PG_arch_1 bit on the first and the third pmd page
+           so that pmd_free_fast can recognize pmds that have been
+           allocated with an order 2 allocation.  */
+	set_bit(PG_arch_1, &virt_to_page(new)->flags);
+	set_bit(PG_arch_1, &virt_to_page(new+PTRS_PER_PMD)->flags);
+	/* Now copy the two pmds to the new memory area. */
+	if (offset == 0) {
+		pmd2 = (pmd_t *)(*pgd_slot & PAGE_MASK) + PTRS_PER_PMD;
+		memcpy(new, pmd, sizeof(pmd_t)*PTRS_PER_PMD);
+		memcpy(new + PTRS_PER_PMD, pmd2, sizeof(pmd_t)*PTRS_PER_PMD);
+	} else {
+		pmd2 = (pmd_t *)(*pgd_slot & PAGE_MASK);
+		memcpy(new, pmd2, sizeof(pmd_t)*PTRS_PER_PMD);
+		memcpy(new + PTRS_PER_PMD, pmd, sizeof(pmd_t)*PTRS_PER_PMD);
+	}
+	*pgd_slot = __pa(new) | _PGD_ENTRY_MASK |
+			_PGD_ENTRY_OFF(0) | _PGD_ENTRY_LEN(3);
+	for (i = 0; i < PTRS_PER_PMD; i++) {
+		pmd_clear(pmd + i);
+		pmd_clear(pmd2 + i);
+	}
+	pmd_free(pmd);
+	pmd_free(pmd2);
+	return new;
+}
+
+void pmd_free_order2(pmd_t *pmd)
+{
+	pmd_t *pmd2 = (pmd_t *) ((unsigned long) pmd ^ 8192);
+
+	clear_bit(PG_arch_1, &virt_to_page(pmd)->flags);
+	if (test_bit(PG_arch_1, &virt_to_page(pmd2)->flags) == 0) {
+		/* The other pmd of the order 2 allocation has already
+		   been freed. Now we can release the order 2 allocation.  */
+		free_pages((unsigned long) pmd & ~8192, 2);
+	}
+}
+
 int do_check_pgt_cache(int low, int high)
 {
         int freed = 0;
@@ -51,11 +119,11 @@
                 do {
                         if(pgd_quicklist) {
 				free_pgd_slow(get_pgd_fast());
-				freed += 4;
+				freed += 2;
 			}
                         if(pmd_quicklist) {
 				pmd_free_slow(pmd_alloc_one_fast(NULL, 0));
-				freed += 4;
+				freed += 2;
 			}
                         if(pte_quicklist) {
 				pte_free_slow(pte_alloc_one_fast(NULL, 0));
@@ -111,51 +179,45 @@
 
 void __init paging_init(void)
 {
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	static const int ssm_mask = 0x04000000L;
+	unsigned long dma_pfn, address, end_mem;
         pgd_t * pg_dir;
-	pmd_t * pm_dir;
-        pte_t * pt_dir;
-        pte_t   pte;
 	int     i,j,k;
-        unsigned long address=0;
-        unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) |
-          _KERN_REGION_TABLE;
-	unsigned long end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE);
-	static const int ssm_mask = 0x04000000L;
-
-	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
-	unsigned long dma_pfn, high_pfn;
 
 	dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
-	high_pfn = max_low_pfn;
 
-	if (dma_pfn > high_pfn)
-		zones_size[ZONE_DMA] = high_pfn;
+	if (dma_pfn > max_low_pfn)
+		zones_size[ZONE_DMA] = max_low_pfn;
 	else {
 		zones_size[ZONE_DMA] = dma_pfn;
-		zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
+		zones_size[ZONE_NORMAL] = max_low_pfn - dma_pfn;
 	}
 
 	/* Initialize mem_map[].  */
 	free_area_init(zones_size);
 
-
 	/*
 	 * map whole physical memory to virtual memory (identity mapping) 
 	 */
-
         pg_dir = swapper_pg_dir;
-	
-        for (i = 0 ; i < PTRS_PER_PGD ; i++,pg_dir++) {
+	address = 0;
+	end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE);
+        for (i = 0 ; i < PTRS_PER_PGD/2 ; i++, pg_dir += 2) {
+		pmd_t *pm_dir;
 
                 if (address >= end_mem) {
                         pgd_clear(pg_dir);
                         continue;
-                }          
+                }
         
 	        pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4);
-                pgd_populate(&init_mm, pg_dir, pm_dir);
+		*((unsigned long *) pg_dir) = __pa(pm_dir) | _PGD_ENTRY_MASK |
+			_PGD_ENTRY_LEN(3) | _PGD_ENTRY_OFF(0);
+
+                for (j = 0 ; j < PTRS_PER_PMD*2 ; j++, pm_dir++) {
+			pte_t *pt_dir;
 
-                for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
                         if (address >= end_mem) {
                                 pmd_clear(pm_dir);
                                 continue; 
@@ -165,7 +227,7 @@
                         pmd_populate(&init_mm, pm_dir, pt_dir);
 	
                         for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
-                                pte = mk_pte_phys(address, PAGE_KERNEL);
+                                pte_t pte = mk_pte_phys(address, PAGE_KERNEL);
                                 if (address >= end_mem) {
                                         pte_clear(&pte); 
                                         continue;
@@ -181,8 +243,8 @@
                              "lctlg 7,7,%0\n\t"
                              "lctlg 13,13,%0\n\t"
                              "ssm   %1"
-			     : :"m" (pgdir_k), "m" (ssm_mask));
-
+			     : :"m" (__pa(swapper_pg_dir) | _KERN_REGION_TABLE),
+			        "m" (ssm_mask));
         local_flush_tlb();
 
         return;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sh/config.in linux/arch/sh/config.in
--- linux.orig/arch/sh/config.in	2002-02-25 19:37:56.000000000 +0000
+++ linux/arch/sh/config.in	2002-08-12 22:14:20.000000000 +0000
@@ -386,3 +386,5 @@
    bool 'Early printk support' CONFIG_SH_EARLY_PRINTK
 fi
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc/config.in linux/arch/sparc/config.in
--- linux.orig/arch/sparc/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc/config.in	2002-08-12 22:14:02.000000000 +0000
@@ -97,11 +97,6 @@
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
 dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
 
-#tristate 'Logical volume manager (LVM) support' CONFIG_BLK_DEV_LVM N
-#if [ "$CONFIG_BLK_DEV_LVM" != "n" ]; then
-#   bool '   LVM information in proc filesystem' CONFIG_LVM_PROC_FS Y
-#fi
-
 source drivers/md/Config.in
 
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
@@ -206,7 +201,7 @@
           tristate '  Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
         fi
       fi
-      tristate '  PPP (point-to-point) support' CONFIG_PPP
+      tristate '  PPP (point-to-point protocol) support' CONFIG_PPP
       if [ ! "$CONFIG_PPP" = "n" ]; then
         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
@@ -271,3 +266,5 @@
 
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc/kernel/devices.c linux/arch/sparc/kernel/devices.c
--- linux.orig/arch/sparc/kernel/devices.c	2002-02-25 19:37:56.000000000 +0000
+++ linux/arch/sparc/kernel/devices.c	2002-08-12 22:14:25.000000000 +0000
@@ -22,8 +22,8 @@
 extern void clock_stop_probe(void); /* tadpole.c */
 extern void sun4c_probe_memerr_reg(void);
 
-unsigned long __init
-device_scan(unsigned long mem_start)
+void __init
+device_scan(void)
 {
 	char node_str[128];
 	int thismid;
@@ -37,46 +37,45 @@
 		int scan;
 		scan = prom_getchild(prom_root_node);
 		/* One can look it up in PROM instead */
-		/* prom_printf("root child is %08lx\n", (unsigned long) scan); */
-		while((scan = prom_getsibling(scan)) != 0) {
-			prom_getstring(scan, "device_type", node_str, sizeof(node_str));
-			if(strcmp(node_str, "cpu") == 0) {
+		while ((scan = prom_getsibling(scan)) != 0) {
+			prom_getstring(scan, "device_type",
+				       node_str, sizeof(node_str));
+			if (strcmp(node_str, "cpu") == 0) {
 				linux_cpus[linux_num_cpus].prom_node = scan;
-				prom_getproperty(scan, "mid", (char *) &thismid, sizeof(thismid));
+				prom_getproperty(scan, "mid",
+						 (char *) &thismid, sizeof(thismid));
 				linux_cpus[linux_num_cpus].mid = thismid;
-				/* prom_printf("Found CPU %d <node=%08lx,mid=%d>\n", linux_num_cpus, (unsigned long) scan, thismid); */
-				printk("Found CPU %d <node=%08lx,mid=%d>\n", linux_num_cpus, (unsigned long) scan, thismid);
+				printk("Found CPU %d <node=%08lx,mid=%d>\n",
+				       linux_num_cpus, (unsigned long) scan, thismid);
 				linux_num_cpus++;
 			}
 		}
-		if(linux_num_cpus == 0) {
-			if (sparc_cpu_model == sun4d) {
-				scan = prom_getchild(prom_root_node);
-				for (scan = prom_searchsiblings(scan, "cpu-unit"); scan;
-				     scan = prom_searchsiblings(prom_getsibling(scan), "cpu-unit")) {
-					int node = prom_getchild(scan);
-
-					prom_getstring(node, "device_type", node_str, sizeof(node_str));
-					if (strcmp(node_str, "cpu") == 0) {
-						prom_getproperty(node, "cpu-id", (char *) &thismid, sizeof(thismid));
-						linux_cpus[linux_num_cpus].prom_node = node;
-						linux_cpus[linux_num_cpus].mid = thismid;
-						/* prom_printf("Found CPU %d <node=%08lx,mid=%d>\n", 
-							       linux_num_cpus, (unsigned long) node, thismid); */
-						printk("Found CPU %d <node=%08lx,mid=%d>\n", 
-						       linux_num_cpus, (unsigned long) node, thismid);
-						linux_num_cpus++;
-					}
+		if (linux_num_cpus == 0 && sparc_cpu_model == sun4d) {
+			scan = prom_getchild(prom_root_node);
+			for (scan = prom_searchsiblings(scan, "cpu-unit"); scan;
+			     scan = prom_searchsiblings(prom_getsibling(scan), "cpu-unit")) {
+				int node = prom_getchild(scan);
+
+				prom_getstring(node, "device_type",
+					       node_str, sizeof(node_str));
+				if (strcmp(node_str, "cpu") == 0) {
+					prom_getproperty(node, "cpu-id",
+							 (char *) &thismid, sizeof(thismid));
+					linux_cpus[linux_num_cpus].prom_node = node;
+					linux_cpus[linux_num_cpus].mid = thismid;
+					printk("Found CPU %d <node=%08lx,mid=%d>\n", 
+					       linux_num_cpus, (unsigned long) node, thismid);
+					linux_num_cpus++;
 				}
 			}
 		}
-		if(linux_num_cpus == 0) {
+		if (linux_num_cpus == 0) {
 			printk("No CPU nodes found, cannot continue.\n");
 			/* Probably a sun4e, Sun is trying to trick us ;-) */
 			halt();
 		}
 		printk("Found %d CPU prom device tree node(s).\n", linux_num_cpus);
-	};
+	}
 
 	cpu_probe();
 #ifdef CONFIG_SUN_AUXIO
@@ -92,5 +91,5 @@
 	if (ARCH_SUN4C_SUN4)
 		sun4c_probe_memerr_reg();
 
-	return mem_start;
+	return;
 }
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- linux.orig/arch/sparc/kernel/sys_sunos.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc/kernel/sys_sunos.c	2002-08-12 22:14:16.000000000 +0000
@@ -488,7 +488,8 @@
 		ret |= __copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
 	}
 	up_read(&uts_sem);
-	return ret;
+
+	return (ret ? -EFAULT : 0);
 }
 
 asmlinkage int sunos_nosys(void)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc/mm/init.c linux/arch/sparc/mm/init.c
--- linux.orig/arch/sparc/mm/init.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc/mm/init.c	2002-08-12 22:14:17.000000000 +0000
@@ -61,13 +61,17 @@
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
 
+/* These are set in {srmmu,sun4c}_paging_init() */
+unsigned long fix_kmap_begin;
+unsigned long fix_kmap_end;
+
 #define kmap_get_fixed_pte(vaddr) \
 	pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
 
 void __init kmap_init(void)
 {
 	/* cache the first kmap pte */
-	kmap_pte = kmap_get_fixed_pte(FIX_KMAP_BEGIN);
+	kmap_pte = kmap_get_fixed_pte(fix_kmap_begin);
 	kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- linux.orig/arch/sparc/mm/srmmu.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc/mm/srmmu.c	2002-08-12 22:14:01.000000000 +0000
@@ -114,8 +114,16 @@
 
 int srmmu_cache_pagetables;
 
-/* XXX Make this dynamic based on ram size - Anton */
-#define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16)
+/* these will be initialized in srmmu_nocache_calcsize() */
+int srmmu_nocache_npages;
+unsigned long srmmu_nocache_size;
+unsigned long srmmu_nocache_end;
+unsigned long pkmap_base;
+unsigned long pkmap_base_end;
+unsigned long srmmu_nocache_bitmap_size;
+extern unsigned long fix_kmap_begin;
+extern unsigned long fix_kmap_end;
+
 #define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4)
 
 void *srmmu_nocache_pool;
@@ -248,7 +256,7 @@
 	spin_lock(&srmmu_nocache_spinlock);
 
 repeat:
-	offset = find_next_zero_bit(srmmu_nocache_bitmap, SRMMU_NOCACHE_BITMAP_SIZE, offset);
+	offset = find_next_zero_bit(srmmu_nocache_bitmap, srmmu_nocache_bitmap_size, offset);
 
 	/* we align on physical address */
 	if (align) {
@@ -258,7 +266,7 @@
 		offset = (va_tmp - SRMMU_NOCACHE_VADDR) >> SRMMU_NOCACHE_BITMAP_SHIFT;
 	}
 
-	if ((SRMMU_NOCACHE_BITMAP_SIZE - offset) < size) {
+	if ((srmmu_nocache_bitmap_size - offset) < size) {
 		printk("Run out of nocached RAM!\n");
 		spin_unlock(&srmmu_nocache_spinlock);
 		return 0;
@@ -322,6 +330,35 @@
 
 void srmmu_early_allocate_ptable_skeleton(unsigned long start, unsigned long end);
 
+extern unsigned long probe_memory(void);	/* in fault.c */
+
+/* Reserve nocache dynamically proportionally to the amount of
+ * system RAM. -- Tomas Szepe <szepe@pinerecords.com>, June 2002
+ */
+void srmmu_nocache_calcsize(void)
+{
+	unsigned long sysmemavail = probe_memory() / 1024;
+
+	srmmu_nocache_npages =
+		sysmemavail / SRMMU_NOCACHE_ALCRATIO / 1024 * 256;
+	if (sysmemavail % (SRMMU_NOCACHE_ALCRATIO * 1024))
+		srmmu_nocache_npages += 256;
+
+	/* anything above 1280 blows up */
+	if (srmmu_nocache_npages > 1280) srmmu_nocache_npages = 1280;
+
+	srmmu_nocache_size = srmmu_nocache_npages * PAGE_SIZE;
+	srmmu_nocache_bitmap_size = srmmu_nocache_npages * 16;
+	srmmu_nocache_end = SRMMU_NOCACHE_VADDR + srmmu_nocache_size;
+	fix_kmap_begin = srmmu_nocache_end;
+	fix_kmap_end = fix_kmap_begin + (KM_TYPE_NR * NR_CPUS - 1) * PAGE_SIZE;
+	pkmap_base = SRMMU_NOCACHE_VADDR + srmmu_nocache_size + 0x40000;
+	pkmap_base_end = pkmap_base + LAST_PKMAP * PAGE_SIZE;
+
+	/* printk("system memory available = %luk\nnocache ram size = %luk\n",
+		sysmemavail, srmmu_nocache_size / 1024); */
+}
+
 void srmmu_nocache_init(void)
 {
 	pgd_t *pgd;
@@ -330,24 +367,24 @@
 	unsigned long paddr, vaddr;
 	unsigned long pteval;
 
-	srmmu_nocache_pool = __alloc_bootmem(SRMMU_NOCACHE_SIZE, PAGE_SIZE, 0UL);
-	memset(srmmu_nocache_pool, 0, SRMMU_NOCACHE_SIZE);
+	srmmu_nocache_pool = __alloc_bootmem(srmmu_nocache_size, PAGE_SIZE, 0UL);
+	memset(srmmu_nocache_pool, 0, srmmu_nocache_size);
 
-	srmmu_nocache_bitmap = __alloc_bootmem(SRMMU_NOCACHE_BITMAP_SIZE, SMP_CACHE_BYTES, 0UL);
-	memset(srmmu_nocache_bitmap, 0, SRMMU_NOCACHE_BITMAP_SIZE);
+	srmmu_nocache_bitmap = __alloc_bootmem(srmmu_nocache_bitmap_size, SMP_CACHE_BYTES, 0UL);
+	memset(srmmu_nocache_bitmap, 0, srmmu_nocache_bitmap_size);
 
 	srmmu_swapper_pg_dir = (pgd_t *)__srmmu_get_nocache(SRMMU_PGD_TABLE_SIZE, SRMMU_PGD_TABLE_SIZE);
 	memset(__nocache_fix(srmmu_swapper_pg_dir), 0, SRMMU_PGD_TABLE_SIZE);
 	init_mm.pgd = srmmu_swapper_pg_dir;
 
-	srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, SRMMU_NOCACHE_END);
+	srmmu_early_allocate_ptable_skeleton(SRMMU_NOCACHE_VADDR, srmmu_nocache_end);
 
 	spin_lock_init(&srmmu_nocache_spinlock);
 
 	paddr = __pa((unsigned long)srmmu_nocache_pool);
 	vaddr = SRMMU_NOCACHE_VADDR;
 
-	while (vaddr < SRMMU_NOCACHE_END) {
+	while (vaddr < srmmu_nocache_end) {
 		pgd = pgd_offset_k(vaddr);
 		pmd = srmmu_pmd_offset(__nocache_fix(pgd), vaddr);
 		pte = srmmu_pte_offset(__nocache_fix(pmd), vaddr);
@@ -1144,6 +1181,7 @@
 	pages_avail = 0;
 	last_valid_pfn = bootmem_init(&pages_avail);
 
+	srmmu_nocache_calcsize();
 	srmmu_nocache_init();
         srmmu_inherit_prom_mappings(0xfe400000,(LINUX_OPPROM_ENDVM-PAGE_SIZE));
 	map_kernel();
@@ -1165,12 +1203,12 @@
 	srmmu_allocate_ptable_skeleton(DVMA_VADDR, DVMA_END);
 #endif
 
-	srmmu_allocate_ptable_skeleton(FIX_KMAP_BEGIN, FIX_KMAP_END);
-	srmmu_allocate_ptable_skeleton(PKMAP_BASE, PKMAP_BASE_END);
+	srmmu_allocate_ptable_skeleton(fix_kmap_begin, fix_kmap_end);
+	srmmu_allocate_ptable_skeleton(pkmap_base, pkmap_base_end);
 
-	pgd = pgd_offset_k(PKMAP_BASE);
-	pmd = pmd_offset(pgd, PKMAP_BASE);
-	pte = pte_offset(pmd, PKMAP_BASE);
+	pgd = pgd_offset_k(pkmap_base);
+	pmd = pmd_offset(pgd, pkmap_base);
+	pte = pte_offset(pmd, pkmap_base);
 	pkmap_page_table = pte;
 
 	flush_cache_all();
@@ -1219,7 +1257,7 @@
 		   "nocache used\t: %d\n",
 		   srmmu_name,
 		   num_contexts,
-		   SRMMU_NOCACHE_SIZE,
+		   srmmu_nocache_size,
 		   (srmmu_nocache_used << SRMMU_NOCACHE_BITMAP_SHIFT));
 }
 
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- linux.orig/arch/sparc/mm/sun4c.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc/mm/sun4c.c	2002-08-12 22:14:08.000000000 +0000
@@ -35,6 +35,7 @@
 #include <asm/mmu_context.h>
 #include <asm/sun4paddr.h>
 #include <asm/highmem.h>
+#include <asm/btfixup.h>
 
 /* Because of our dynamic kernel TLB miss strategy, and how
  * our DVMA mapping allocation works, you _MUST_:
@@ -63,25 +64,17 @@
 
 #define SUN4C_KERNEL_BUCKETS 32
 
-#ifndef MAX
-#define MAX(a,b) ((a)<(b)?(b):(a))
-#endif
-#ifndef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#endif
-
 /* Flushing the cache. */
 struct sun4c_vac_props sun4c_vacinfo;
 unsigned long sun4c_kernel_faults;
 
 /* Invalidate every sun4c cache line tag. */
-void sun4c_flush_all(void)
+static void __init sun4c_flush_all(void)
 {
 	unsigned long begin, end;
 
 	if (sun4c_vacinfo.on)
-		panic("SUN4C: AIEEE, trying to invalidate vac while"
-                      " it is on.");
+		panic("SUN4C: AIEEE, trying to invalidate vac while it is on.");
 
 	/* Clear 'valid' bit in all cache line tags */
 	begin = AC_CACHETAGS;
@@ -93,7 +86,7 @@
 	}
 }
 
-static __inline__ void sun4c_flush_context_hw(void)
+static void sun4c_flush_context_hw(void)
 {
 	unsigned long end = SUN4C_VAC_SIZE;
 
@@ -122,8 +115,17 @@
 	}
 }
 
+/* File local boot time fixups. */
+BTFIXUPDEF_CALL(void, sun4c_flush_page, unsigned long)
+BTFIXUPDEF_CALL(void, sun4c_flush_segment, unsigned long)
+BTFIXUPDEF_CALL(void, sun4c_flush_context, void)
+
+#define sun4c_flush_page(addr) BTFIXUP_CALL(sun4c_flush_page)(addr)
+#define sun4c_flush_segment(addr) BTFIXUP_CALL(sun4c_flush_segment)(addr)
+#define sun4c_flush_context() BTFIXUP_CALL(sun4c_flush_context)()
+
 /* Must be called minimally with interrupts disabled. */
-static __inline__ void sun4c_flush_page_hw(unsigned long addr)
+static void sun4c_flush_page_hw(unsigned long addr)
 {
 	addr &= PAGE_MASK;
 	if ((int)sun4c_get_pte(addr) < 0)
@@ -195,48 +197,6 @@
 	}
 }
 
-/* Bolix one page from the virtual cache. */
-static void sun4c_flush_page(unsigned long addr)
-{
-	addr &= PAGE_MASK;
-
-	if ((sun4c_get_pte(addr) & (_SUN4C_PAGE_NOCACHE | _SUN4C_PAGE_VALID)) !=
-	    _SUN4C_PAGE_VALID)
-		return;
-
-	if (sun4c_vacinfo.do_hwflushes) {
-		__asm__ __volatile__("sta %%g0, [%0] %1;nop;nop;nop;\n\t" : :
-				     "r" (addr), "i" (ASI_HWFLUSHPAGE));
-	} else {
-		unsigned long left = PAGE_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" (left), "=&r" (lsize)
-				     : "0" (addr), "1" (left), "2" (lsize),
-				       "i" (ASI_FLUSHPG)
-				     : "g1", "g2", "g3", "g4", "g5", "o4", "o5", "cc");
-	}
-}
-
 /* Don't inline the software version as it eats too many cache lines if expanded. */
 static void sun4c_flush_page_sw(unsigned long addr)
 {
@@ -387,7 +347,8 @@
 			 prom_getintdefault(prom_root_node, "vac_hwflush", 0);
 
 		if (sun4c_vacinfo.num_bytes != 65536) {
-			prom_printf("WEIRD Sun4C VAC cache size, tell davem");
+			prom_printf("WEIRD Sun4C VAC cache size, "
+				    "tell sparclinux@vger.kernel.org");
 			prom_halt();
 		}
 	}
@@ -427,7 +388,7 @@
 		*daddr = *iaddr;	\
 	} while (0);
 
-static void patch_kernel_fault_handler(void)
+static void __init patch_kernel_fault_handler(void)
 {
 	unsigned long *iaddr, *daddr;
 
@@ -459,10 +420,6 @@
 		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",
@@ -867,33 +824,7 @@
 #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)
-{
-	struct sun4c_mmu_entry *head = &crp->ringhd;
-	unsigned long flags;
-
-	save_and_cli(flags);
-	if (head->next != head) {
-		struct sun4c_mmu_entry *entry = head->next;
-		int savectx = sun4c_get_context();
-
-		flush_user_windows();
-		sun4c_set_context(ctx);
-		sun4c_flush_context_hw();
-		do {
-			struct sun4c_mmu_entry *next = entry->next;
-
-			sun4c_user_unmap(entry);
-			free_user_entry(ctx, entry);
-
-			entry = next;
-		} while (entry != head);
-		sun4c_set_context(savectx);
-	}
-	restore_flags(flags);
-}
-
-static void sun4c_demap_context_sw(struct sun4c_mmu_ring *crp, unsigned char ctx)
+static void sun4c_demap_context(struct sun4c_mmu_ring *crp, unsigned char ctx)
 {
 	struct sun4c_mmu_entry *head = &crp->ringhd;
 	unsigned long flags;
@@ -905,7 +836,7 @@
 
 		flush_user_windows();
 		sun4c_set_context(ctx);
-		sun4c_flush_context_sw();
+		sun4c_flush_context();
 		do {
 			struct sun4c_mmu_entry *next = entry->next;
 
@@ -919,8 +850,8 @@
 	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 int sun4c_user_taken_entries;  /* This is how much we have.             */
+static int max_user_taken_entries;    /* This limits us and prevents deadlock. */
 
 static struct sun4c_mmu_entry *sun4c_kernel_strategy(void)
 {
@@ -934,10 +865,7 @@
 
 	/* Else free one up. */
 	this_entry = sun4c_kernel_ring.ringhd.prev;
-	if (sun4c_vacinfo.do_hwflushes)
-		sun4c_flush_segment_hw(this_entry->vaddr);
-	else
-		sun4c_flush_segment_sw(this_entry->vaddr);
+	sun4c_flush_segment(this_entry->vaddr);
 	sun4c_kernel_unmap(this_entry);
 	free_kernel_entry(this_entry, &sun4c_kernel_ring);
 	this_entry = sun4c_kfree_ring.ringhd.next;
@@ -976,10 +904,7 @@
 	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_flush_segment(entry->vaddr);
 	sun4c_user_unmap(entry);
 	remove_ring(sun4c_context_ring + ctx, entry);
 	remove_lru(entry);
@@ -1068,10 +993,7 @@
 	entry = &mmu_entry_pool[pseg];
 
 	flush_user_windows();
-	if (sun4c_vacinfo.do_hwflushes)
-		sun4c_flush_segment_hw(addr);
-	else
-		sun4c_flush_segment_sw(addr);
+	sun4c_flush_segment(addr);
 	sun4c_kernel_unmap(entry);
 	add_ring(&sun4c_ufree_ring, entry);
 	max_user_taken_entries++;
@@ -1126,17 +1048,10 @@
 	/* 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);
+	sun4c_flush_page(pages);
 #ifndef CONFIG_SUN4	
-		sun4c_flush_page_sw(pages + PAGE_SIZE);
+	sun4c_flush_page(pages + PAGE_SIZE);
 #endif
-	}
 
 	sun4c_put_pte(addr, BUCKET_PTE(pages));
 #ifndef CONFIG_SUN4	
@@ -1145,32 +1060,7 @@
 	return (struct task_struct *) addr;
 }
 
-static void sun4c_free_task_struct_hw(struct task_struct *tsk)
-{
-	unsigned long tsaddr = (unsigned long) tsk;
-	unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr));
-	int entry = BUCKET_NUM(tsaddr);
-
-	if (atomic_dec_and_test(&(tsk)->thread.refcount)) {
-		/* We are deleting a mapping, so the flush here is mandatory. */
-		sun4c_flush_page_hw(tsaddr);
-#ifndef CONFIG_SUN4	
-		sun4c_flush_page_hw(tsaddr + PAGE_SIZE);
-#endif
-		sun4c_put_pte(tsaddr, 0);
-#ifndef CONFIG_SUN4	
-		sun4c_put_pte(tsaddr + PAGE_SIZE, 0);
-#endif
-		sun4c_bucket[entry] = BUCKET_EMPTY;
-		if (entry < sun4c_lowbucket_avail)
-			sun4c_lowbucket_avail = entry;
-
-		free_pages(pages, TASK_STRUCT_ORDER);
-		garbage_collect(entry);
-	}
-}
-
-static void sun4c_free_task_struct_sw(struct task_struct *tsk)
+static void sun4c_free_task_struct(struct task_struct *tsk)
 {
 	unsigned long tsaddr = (unsigned long) tsk;
 	unsigned long pages = BUCKET_PTE_PAGE(sun4c_get_pte(tsaddr));
@@ -1178,9 +1068,9 @@
 
 	if (atomic_dec_and_test(&(tsk)->thread.refcount)) {
 		/* We are deleting a mapping, so the flush here is mandatory. */
-		sun4c_flush_page_sw(tsaddr);
+		sun4c_flush_page(tsaddr);
 #ifndef CONFIG_SUN4	
-		sun4c_flush_page_sw(tsaddr + PAGE_SIZE);
+		sun4c_flush_page(tsaddr + PAGE_SIZE);
 #endif
 		sun4c_put_pte(tsaddr, 0);
 #ifndef CONFIG_SUN4	
@@ -1452,130 +1342,7 @@
 	}
 }
 
-static void sun4c_flush_cache_mm_hw(struct mm_struct *mm)
-{
-	int new_ctx = mm->context;
-
-	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);
-
-					entry = next;
-				} while (entry != head);
-				sun4c_set_context(savectx);
-			}
-			restore_flags(flags);
-		}
-	}
-}
-
-static void sun4c_flush_cache_range_hw(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-	int new_ctx = mm->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;
-
-		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)
-			;
-
-		/* 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)) {
-			int octx = sun4c_get_context();
-
-			sun4c_set_context(new_ctx);
-
-			/* At this point, always, (start >= entry->vaddr) and
-			 * (entry->vaddr < end), once the latter condition
-			 * ceases to hold, or we hit the end of the list, we
-			 * exit the loop.  The ordering of all user allocated
-			 * segmaps makes this all work out so beautifully.
-			 */
-			do {
-				struct sun4c_mmu_entry *next = entry->next;
-				unsigned long realend;
-
-				/* "realstart" is always >= entry->vaddr */
-				realend = entry->vaddr + SUN4C_REAL_PGDIR_SIZE;
-				if (end < realend)
-					realend = end;
-				if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
-					unsigned long page = entry->vaddr;
-					while (page < realend) {
-						sun4c_flush_page_hw(page);
-						page += PAGE_SIZE;
-					}
-				} else {
-					sun4c_flush_segment_hw(entry->vaddr);
-					sun4c_user_unmap(entry);
-					free_user_entry(new_ctx, entry);
-				}
-				entry = next;
-			} while ((entry != head) && (entry->vaddr < end));
-			sun4c_set_context(octx);
-		}
-		restore_flags(flags);
-	}
-}
-
-static void sun4c_flush_cache_page_hw(struct vm_area_struct *vma, unsigned long page)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	int new_ctx = mm->context;
-
-	/* Sun4c has no separate I/D caches so cannot optimize for non
-	 * text page flushes.
-	 */
-	if (new_ctx != NO_CONTEXT) {
-		int octx = sun4c_get_context();
-		unsigned long flags;
-
-		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)
-{
-	unsigned long flags;
-
-	save_and_cli(flags);
-	sun4c_flush_page_hw(page);
-	restore_flags(flags);
-}
-
-static void sun4c_flush_cache_mm_sw(struct mm_struct *mm)
+static void sun4c_flush_cache_mm(struct mm_struct *mm)
 {
 	int new_ctx = mm->context;
 
@@ -1592,7 +1359,7 @@
 				int savectx = sun4c_get_context();
 
 				sun4c_set_context(new_ctx);
-				sun4c_flush_context_sw();
+				sun4c_flush_context();
 				do {
 					struct sun4c_mmu_entry *next = entry->next;
 
@@ -1608,7 +1375,7 @@
 	}
 }
 
-static void sun4c_flush_cache_range_sw(struct mm_struct *mm, unsigned long start, unsigned long end)
+static void sun4c_flush_cache_range(struct mm_struct *mm, unsigned long start, unsigned long end)
 {
 	int new_ctx = mm->context;
 
@@ -1651,11 +1418,11 @@
 				if ((realend - entry->vaddr) <= (PAGE_SIZE << 3)) {
 					unsigned long page = entry->vaddr;
 					while (page < realend) {
-						sun4c_flush_page_sw(page);
+						sun4c_flush_page(page);
 						page += PAGE_SIZE;
 					}
 				} else {
-					sun4c_flush_segment_sw(entry->vaddr);
+					sun4c_flush_segment(entry->vaddr);
 					sun4c_user_unmap(entry);
 					free_user_entry(new_ctx, entry);
 				}
@@ -1667,7 +1434,7 @@
 	}
 }
 
-static void sun4c_flush_cache_page_sw(struct vm_area_struct *vma, unsigned long page)
+static void sun4c_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	int new_ctx = mm->context;
@@ -1682,18 +1449,18 @@
 		flush_user_windows();
 		save_and_cli(flags);
 		sun4c_set_context(new_ctx);
-		sun4c_flush_page_sw(page);
+		sun4c_flush_page(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(unsigned long page)
 {
 	unsigned long flags;
 
 	save_and_cli(flags);
-	sun4c_flush_page_sw(page);
+	sun4c_flush_page(page);
 	restore_flags(flags);
 }
 
@@ -1721,10 +1488,7 @@
 	flush_user_windows();
 	while (sun4c_kernel_ring.num_entries) {
 		next_entry = this_entry->next;
-		if (sun4c_vacinfo.do_hwflushes)
-			sun4c_flush_segment_hw(this_entry->vaddr);
-		else
-			sun4c_flush_segment_sw(this_entry->vaddr);
+		sun4c_flush_segment(this_entry->vaddr);
 		for (ctx = 0; ctx < num_contexts; ctx++) {
 			sun4c_set_context(ctx);
 			sun4c_put_segmap(this_entry->vaddr, invalid_segment);
@@ -1736,7 +1500,7 @@
 	restore_flags(flags);
 }
 
-static void sun4c_flush_tlb_mm_hw(struct mm_struct *mm)
+static void sun4c_flush_tlb_mm(struct mm_struct *mm)
 {
 	int new_ctx = mm->context;
 
@@ -1750,7 +1514,7 @@
 			int savectx = sun4c_get_context();
 
 			sun4c_set_context(new_ctx);
-			sun4c_flush_context_hw();
+			sun4c_flush_context();
 			do {
 				struct sun4c_mmu_entry *next = entry->next;
 
@@ -1765,7 +1529,7 @@
 	}
 }
 
-static void sun4c_flush_tlb_range_hw(struct mm_struct *mm, unsigned long start, unsigned long end)
+static void sun4c_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
 {
 	int new_ctx = mm->context;
 
@@ -1775,7 +1539,7 @@
 		unsigned long flags;
 
 		save_and_cli(flags);
-		/* See commentary in sun4c_flush_cache_range_*(). */
+		/* See commentary in sun4c_flush_cache_range(). */
 		for (entry = head->next;
 		     (entry != head) && ((entry->vaddr+SUN4C_REAL_PGDIR_SIZE) < start);
 		     entry = entry->next)
@@ -1788,7 +1552,7 @@
 			do {
 				struct sun4c_mmu_entry *next = entry->next;
 
-				sun4c_flush_segment_hw(entry->vaddr);
+				sun4c_flush_segment(entry->vaddr);
 				sun4c_user_unmap(entry);
 				free_user_entry(new_ctx, entry);
 
@@ -1800,7 +1564,7 @@
 	}
 }
 
-static void sun4c_flush_tlb_page_hw(struct vm_area_struct *vma, unsigned long page)
+static void sun4c_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
 {
 	struct mm_struct *mm = vma->vm_mm;
 	int new_ctx = mm->context;
@@ -1812,90 +1576,7 @@
 		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);
-	}
-}
-
-static void sun4c_flush_tlb_mm_sw(struct mm_struct *mm)
-{
-	int new_ctx = mm->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) {
-			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;
-
-				sun4c_user_unmap(entry);
-				free_user_entry(new_ctx, entry);
-
-				entry = next;
-			} while (entry != head);
-			sun4c_set_context(savectx);
-		}
-		restore_flags(flags);
-	}
-}
-
-static void sun4c_flush_tlb_range_sw(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
-	int new_ctx = mm->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;
-
-		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)
-			;
-
-		if ((entry != head) && (entry->vaddr < end)) {
-			int octx = sun4c_get_context();
-
-			sun4c_set_context(new_ctx);
-			do {
-				struct sun4c_mmu_entry *next = entry->next;
-
-				sun4c_flush_segment_sw(entry->vaddr);
-				sun4c_user_unmap(entry);
-				free_user_entry(new_ctx, entry);
-
-				entry = next;
-			} while ((entry != head) && (entry->vaddr < end));
-			sun4c_set_context(octx);
-		}
-		restore_flags(flags);
-	}
-}
-
-static void sun4c_flush_tlb_page_sw(struct vm_area_struct *vma, unsigned long page)
-{
-	struct mm_struct *mm = vma->vm_mm;
-	int new_ctx = mm->context;
-
-	if (new_ctx != NO_CONTEXT) {
-		int savectx = sun4c_get_context();
-		unsigned long flags;
-
-		save_and_cli(flags);
-		sun4c_set_context(new_ctx);
-		page &= PAGE_MASK;
-		sun4c_flush_page_sw(page);
+		sun4c_flush_page(page);
 		sun4c_put_pte(page, 0);
 		sun4c_set_context(savectx);
 		restore_flags(flags);
@@ -1919,7 +1600,7 @@
 	sun4c_put_pte(virt_addr, 0);
 }
 
-static void sun4c_alloc_context_hw(struct mm_struct *old_mm, struct mm_struct *mm)
+static void sun4c_alloc_context(struct mm_struct *old_mm, struct mm_struct *mm)
 {
 	struct ctx_list *ctxp;
 
@@ -1939,19 +1620,19 @@
 	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],
+	sun4c_demap_context(&sun4c_context_ring[ctxp->ctx_number],
 			       ctxp->ctx_number);
 }
 
 /* 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)
+static void sun4c_switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, struct task_struct *tsk, int cpu)
 {
 	struct ctx_list *ctx;
 	int dirty = 0;
 
 	if (mm->context == NO_CONTEXT) {
 		dirty = 1;
-		sun4c_alloc_context_hw(old_mm, mm);
+		sun4c_alloc_context(old_mm, mm);
 	} else {
 		/* Update the LRU ring of contexts. */
 		ctx = ctx_list_pool + mm->context;
@@ -1962,69 +1643,12 @@
 		sun4c_set_context(mm->context);
 }
 
-static void sun4c_destroy_context_hw(struct mm_struct *mm)
+static void sun4c_destroy_context(struct mm_struct *mm)
 {
 	struct ctx_list *ctx_old;
 
 	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);
-		add_to_free_ctxlist(ctx_old);
-		mm->context = NO_CONTEXT;
-	}
-}
-
-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) {
-		remove_from_ctx_list(ctxp);
-		add_to_used_ctxlist(ctxp);
-		mm->context = ctxp->ctx_number;
-		ctxp->ctx_mm = mm;
-		return;
-	}
-	ctxp = ctx_used.next;
-	if(ctxp->ctx_mm == old_mm)
-		ctxp = ctxp->next;
-	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);
-}
-
-/* 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 (mm->context == NO_CONTEXT) {
-		dirty = 1;
-		sun4c_alloc_context_sw(old_mm, mm);
-	} else {
-		/* Update the LRU ring of contexts. */
-		ctx = ctx_list_pool + mm->context;
-		remove_from_ctx_list(ctx);
-		add_to_used_ctxlist(ctx);
-	}
-
-	if (dirty || old_mm != mm)
-		sun4c_set_context(mm->context);
-}
-
-static void sun4c_destroy_context_sw(struct mm_struct *mm)
-{
-	struct ctx_list *ctx_old;
-
-	if (mm->context != NO_CONTEXT) {
-		sun4c_demap_context_sw(&sun4c_context_ring[mm->context], mm->context);
+		sun4c_demap_context(&sun4c_context_ring[mm->context], mm->context);
 		ctx_old = ctx_list_pool + mm->context;
 		remove_from_ctx_list(ctx_old);
 		add_to_free_ctxlist(ctx_old);
@@ -2091,7 +1715,7 @@
 
 static void sun4c_pmd_set(pmd_t * pmdp, pte_t * ptep)
 {
-	*pmdp = (PGD_TABLE | (unsigned long) ptep);
+	*pmdp = __pmd(PGD_TABLE | (unsigned long) ptep);
 }
 
 static int sun4c_pte_present(pte_t pte)
@@ -2174,10 +1798,7 @@
 	return (pmd_val(pmd) & PAGE_MASK);
 }
 
-static unsigned long sun4c_pgd_page(pgd_t pgd)
-{
-	return 0;
-}
+static unsigned long sun4c_pgd_page(pgd_t pgd) { return 0; }
 
 /* to find an entry in a page-table-directory */
 static inline pgd_t *sun4c_pgd_offset(struct mm_struct * mm, unsigned long address)
@@ -2271,9 +1892,7 @@
 	return NULL;
 }
 
-static void sun4c_free_pmd_fast(pmd_t * pmd)
-{
-}
+static void sun4c_free_pmd_fast(pmd_t * pmd) { }
 
 static int sun4c_check_pgt_cache(int low, int high)
 {
@@ -2352,6 +1971,9 @@
 extern unsigned long last_valid_pfn;
 extern void sun_serial_setup(void);
 
+extern unsigned long fix_kmap_begin;
+extern unsigned long fix_kmap_end;
+
 void __init sun4c_paging_init(void)
 {
 	int i, cnt;
@@ -2359,6 +1981,9 @@
 	extern struct resource sparc_iomap;
 	unsigned long end_pfn, pages_avail;
 
+	fix_kmap_begin = KERNBASE + SRMMU_MAXMEM; /* Why bother with SRMMU_MAXMEM? */
+	fix_kmap_end = fix_kmap_begin + ((KM_TYPE_NR*NR_CPUS)-1)*PAGE_SIZE;
+
 	kernel_end = (unsigned long) &end;
 	kernel_end += (SUN4C_REAL_PGDIR_SIZE * 4);
 	kernel_end = SUN4C_REAL_PGDIR_ALIGN(kernel_end);
@@ -2466,37 +2091,31 @@
 		    _SUN4C_PAGE_IO | _SUN4C_PAGE_NOCACHE;
 	
 	/* Functions */
-#ifndef CONFIG_SMP
 	BTFIXUPSET_CALL(___xchg32, ___xchg32_sun4c, BTFIXUPCALL_NORM);
-#endif
 	BTFIXUPSET_CALL(do_check_pgt_cache, sun4c_check_pgt_cache, BTFIXUPCALL_NORM);
 	
 	BTFIXUPSET_CALL(flush_cache_all, sun4c_flush_cache_all, BTFIXUPCALL_NORM);
 
 	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);
-		BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram_hw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm_hw, BTFIXUPCALL_NORM);
-		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_mm, sun4c_switch_mm_hw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context_hw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(sun4c_flush_page, sun4c_flush_page_hw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(sun4c_flush_segment, sun4c_flush_segment_hw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(sun4c_flush_context, sun4c_flush_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);
-		BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page_sw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram_sw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm_sw, BTFIXUPCALL_NORM);
-		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_mm, sun4c_switch_mm_sw, BTFIXUPCALL_NORM);
-		BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context_sw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(sun4c_flush_page, sun4c_flush_page_sw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(sun4c_flush_segment, sun4c_flush_segment_sw, BTFIXUPCALL_NORM);
+		BTFIXUPSET_CALL(sun4c_flush_context, sun4c_flush_context_sw, BTFIXUPCALL_NORM);
 	}
 
+	BTFIXUPSET_CALL(flush_tlb_mm, sun4c_flush_tlb_mm, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_cache_mm, sun4c_flush_cache_mm, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(destroy_context, sun4c_destroy_context, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(switch_mm, sun4c_switch_mm, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_cache_page, sun4c_flush_cache_page, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_tlb_page, sun4c_flush_tlb_page, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_tlb_range, sun4c_flush_tlb_range, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(flush_cache_range, sun4c_flush_cache_range, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(free_task_struct, sun4c_free_task_struct, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(__flush_page_to_ram, sun4c_flush_page_to_ram, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(flush_tlb_all, sun4c_flush_tlb_all, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(flush_sig_insns, sun4c_flush_sig_insns, BTFIXUPCALL_NOP);
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/config.in linux/arch/sparc64/config.in
--- linux.orig/arch/sparc64/config.in	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/config.in	2002-08-12 22:14:13.000000000 +0000
@@ -308,3 +308,5 @@
 fi
 
 endmenu
+
+source lib/Config.in
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- linux.orig/arch/sparc64/defconfig	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/defconfig	2002-08-12 22:14:14.000000000 +0000
@@ -417,9 +417,7 @@
 #
 # Device Drivers
 #
-CONFIG_IEEE1394_PCILYNX=m
-# CONFIG_IEEE1394_PCILYNX_LOCALRAM is not set
-# CONFIG_IEEE1394_PCILYNX_PORTS is not set
+# CONFIG_IEEE1394_PCILYNX is not set
 CONFIG_IEEE1394_OHCI1394=m
 
 #
@@ -427,6 +425,7 @@
 #
 # CONFIG_IEEE1394_VIDEO1394 is not set
 CONFIG_IEEE1394_SBP2=m
+# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set
 CONFIG_IEEE1394_ETH1394=m
 CONFIG_IEEE1394_DV1394=m
 CONFIG_IEEE1394_RAWIO=m
@@ -859,6 +858,7 @@
 #
 CONFIG_USB_RIO500=m
 # CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_BRLVGER is not set
 
 #
 # Bluetooth support
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- linux.orig/arch/sparc64/kernel/ioctl32.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/ioctl32.c	2002-08-12 22:14:14.000000000 +0000
@@ -4864,13 +4864,15 @@
 	    (unsigned long)t < ((unsigned long)additional_ioctls) + PAGE_SIZE) {
 		ioctl32_hash_table[hash] = t->next;
 		t->cmd = 0;
+		t->next = 0;
 		return 0;
 	} else while (t->next) {
 		t1 = (struct ioctl_trans *)(long)t->next;
 		if (t1->cmd == cmd && t1 >= additional_ioctls &&
 		    (unsigned long)t1 < ((unsigned long)additional_ioctls) + PAGE_SIZE) {
-			t1->cmd = 0;
 			t->next = t1->next;
+			t1->cmd = 0;
+			t1->next = 0;
 			return 0;
 		}
 		t = t1;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c
--- linux.orig/arch/sparc64/kernel/power.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/power.c	2002-08-12 22:14:14.000000000 +0000
@@ -34,20 +34,28 @@
 #endif /* CONFIG_PCI */
 
 extern void machine_halt(void);
+extern void machine_alt_power_off(void);
+static void (*poweroff_method)(void) = machine_alt_power_off;
 
 extern int serial_console;
 
 void machine_power_off(void)
 {
+	if (!serial_console) {
 #ifdef CONFIG_PCI
-	if (power_reg != 0UL && !serial_console) {
-		/* Both register bits seem to have the
-		 * same effect, so until I figure out
-		 * what the difference is...
-		 */
-		writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
-	}
+		if (power_reg != 0UL) {
+			/* Both register bits seem to have the
+			 * same effect, so until I figure out
+			 * what the difference is...
+			 */
+			writel(POWER_COURTESY_OFF | POWER_SYSTEM_OFF, power_reg);
+		} else
 #endif /* CONFIG_PCI */
+			if (poweroff_method != NULL) {
+				poweroff_method();
+				/* not reached */
+			}
+	}
 	machine_halt();
 }
 
@@ -98,6 +106,7 @@
 found:
 	power_reg = (unsigned long)ioremap(edev->resource[0].start, 0x4);
 	printk("power: Control reg at %016lx ... ", power_reg);
+	poweroff_method = machine_halt; /* able to use the standard poweroff */
 	if (edev->irqs[0] != PCI_IRQ_NONE) {
 		if (kernel_thread(powerd, 0, CLONE_FS) < 0) {
 			printk("Failed to start power daemon.\n");
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- linux.orig/arch/sparc64/kernel/process.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/process.c	2002-08-12 22:14:17.000000000 +0000
@@ -128,6 +128,21 @@
 	panic("Halt failed!");
 }
 
+void machine_alt_power_off(void)
+{
+	sti();
+	mdelay(8);
+	cli();
+#ifdef CONFIG_SUN_CONSOLE
+	if (!serial_console && prom_palette)
+		prom_palette(1);
+#endif
+	if (prom_keyboard)
+		prom_keyboard();
+	prom_halt_power_off();
+	panic("Power-off failed!");
+}
+
 void machine_restart(char * cmd)
 {
 	char *p;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- linux.orig/arch/sparc64/kernel/sparc64_ksyms.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	2002-08-12 22:14:10.000000000 +0000
@@ -136,7 +136,7 @@
 
 #if defined(CONFIG_MCOUNT)
 extern void mcount(void);
-EXPORT_SYMBOL(mcount);
+EXPORT_SYMBOL_NOVERS(mcount);
 #endif
 
 /* Per-CPU information table */
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- linux.orig/arch/sparc64/kernel/sys_sparc32.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/sys_sparc32.c	2002-08-12 22:14:23.000000000 +0000
@@ -512,9 +512,9 @@
 
 	if (!p)
 		return -ENOMEM;
-	err = get_user (p->mtype, &up->mtype);
-	err |= __copy_from_user (p->mtext, &up->mtext, second);
-	if (err)
+	err = -EFAULT;
+	if (get_user (p->mtype, &up->mtype) ||
+	    __copy_from_user (p->mtext, &up->mtext, second))
 		goto out;
 	old_fs = get_fs ();
 	set_fs (KERNEL_DS);
@@ -1056,7 +1056,7 @@
 static long do_readv_writev32(int type, struct file *file,
 			      const struct iovec32 *vector, u32 count)
 {
-	unsigned long tot_len;
+	__kernel_ssize_t32 tot_len;
 	struct iovec iovstack[UIO_FASTIOV];
 	struct iovec *iov=iovstack, *ivp;
 	struct inode *inode;
@@ -1086,13 +1086,19 @@
 	tot_len = 0;
 	i = count;
 	ivp = iov;
+	retval = -EINVAL;
 	while(i > 0) {
-		u32 len;
+		__kernel_ssize_t32 tmp = tot_len;
+		__kernel_ssize_t32 len;
 		u32 buf;
 
 		__get_user(len, &vector->iov_len);
 		__get_user(buf, &vector->iov_base);
+		if (len < 0)	/* size_t not fittina an ssize_t32 .. */
+			goto out;
 		tot_len += len;
+		if (tot_len < tmp) /* maths overflow on the ssize_t32 */
+			goto out;
 		ivp->iov_base = (void *)A(buf);
 		ivp->iov_len = (__kernel_size_t) len;
 		vector++;
@@ -2887,6 +2893,8 @@
 		ret |= __copy_to_user(&oact->sa_mask, &set32, sizeof(sigset_t32));
 		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 		ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
+		if (ret)
+			ret = -EFAULT;
         }
 
         return ret;
@@ -3613,7 +3621,7 @@
 	err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
 			  &arg32->ca32_client.cl32_fhkey[0],
 			  NFSCLNT_KEYMAX);
-	return err;
+	return (err ? -EFAULT : 0);
 }
 
 static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
@@ -3639,7 +3647,7 @@
 		      &arg32->ca32_export.ex32_anon_gid);
 	karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
 	karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
-	return err;
+	return (err ? -EFAULT : 0);
 }
 
 static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
@@ -3687,7 +3695,7 @@
 		err |= __get_user(karg->ca_umap.ug_gdimap[i],
 			      &(((__kernel_gid_t32 *)A(uaddr))[i]));
 
-	return err;
+	return (err ? -EFAULT : 0);
 }
 
 static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
@@ -3704,7 +3712,7 @@
 		      &arg32->ca32_getfh.gf32_ino);
 	err |= __get_user(karg->ca_getfh.gf_version,
 		      &arg32->ca32_getfh.gf32_version);
-	return err;
+	return (err ? -EFAULT : 0);
 }
 
 static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
@@ -3720,7 +3728,7 @@
 			  (NFS_MAXPATHLEN+1));
 	err |= __get_user(karg->ca_getfd.gd_version,
 		      &arg32->ca32_getfd.gd32_version);
-	return err;
+	return (err ? -EFAULT : 0);
 }
 
 static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
@@ -3736,7 +3744,7 @@
 			  (NFS_MAXPATHLEN+1));
 	err |= __get_user(karg->ca_getfs.gd_maxlen,
 		      &arg32->ca32_getfs.gd32_maxlen);
-	return err;
+	return (err ? -EFAULT : 0);
 }
 
 /* This really doesn't need translations, we are only passing
@@ -3744,7 +3752,7 @@
  */
 static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
 {
-	return copy_to_user(res32, kres, sizeof(*res32));
+	return (copy_to_user(res32, kres, sizeof(*res32)) ? -EFAULT : 0);
 }
 
 int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- linux.orig/arch/sparc64/kernel/sys_sunos32.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/sys_sunos32.c	2002-08-12 22:14:23.000000000 +0000
@@ -446,7 +446,7 @@
 	ret |= copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);
 	ret |= copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);
 	up_read(&uts_sem);
-	return ret;
+	return (ret ? -EFAULT : 0);
 }
 
 asmlinkage int sunos_nosys(void)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- linux.orig/arch/sparc64/kernel/time.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/kernel/time.c	2002-08-12 22:14:20.000000000 +0000
@@ -686,7 +686,7 @@
 
 	/* 
 	 * Not having a register set can lead to trouble.
-	 * Also starfire doesnt have a tod clock.
+	 * Also starfire doesn't have a tod clock.
 	 */
 	if (!mregs && !dregs) 
 		return -1;
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/sparc64/prom/misc.c linux/arch/sparc64/prom/misc.c
--- linux.orig/arch/sparc64/prom/misc.c	2002-08-03 00:39:43.000000000 +0000
+++ linux/arch/sparc64/prom/misc.c	2002-08-12 22:14:09.000000000 +0000
@@ -97,6 +97,19 @@
 	goto again; /* PROM is out to get me -DaveM */
 }
 
+void
+prom_halt_power_off(void)
+{
+#ifdef CONFIG_SMP
+	smp_promstop_others();
+	udelay(8000);
+#endif
+	p1275_cmd ("SUNW,power-off", P1275_INOUT(0,0));
+
+	/* if nothing else helps, we just halt */
+	prom_halt ();
+}
+
 /* Set prom sync handler to call function 'funcp'. */
 void
 prom_setcallback(callback_func_t funcp)
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/Makefile linux/arch/x86_64/Makefile
--- linux.orig/arch/x86_64/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/Makefile	2002-08-12 22:14:13.000000000 +0000
@@ -0,0 +1,123 @@
+#
+# x86_64/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+# 19990713  Artur Skawina <skawina@geocities.com>
+#           Added '-march' and '-mpreferred-stack-boundary' support
+# 20000913  Pavel Machek <pavel@suse.cz>
+#	    Converted for x86_64 architecture
+# 20010105  Andi Kleen, add IA32 compiler.
+#           ....and later removed it again....
+#
+# $Id: Makefile,v 1.31 2002/03/22 15:56:07 ak Exp $
+
+#
+# early bootup linking needs 32bit. You can either use real 32bit tools
+# here or 64bit tools switch to 32bit mode.
+# 
+IA32_CC := $(CROSS_COMPILE)gcc -m32 -O2 -fomit-frame-pointer -nostdinc -I $(HPATH)
+IA32_LD := $(CROSS_COMPILE)ld -m elf_i386
+IA32_AS := $(CROSS_COMPILE)gcc -m32 -Wa,--32 -D__ASSEMBLY__ -traditional -c -nostdinc -I $(HPATH) 
+IA32_OBJCOPY := $(CROSS_COMPILE)objcopy
+IA32_CPP := $(CROSS_COMPILE)gcc -m32 -E
+export IA32_CC IA32_LD IA32_AS IA32_OBJCOPY IA32_CPP
+
+
+LD=$(CROSS_COMPILE)ld -m elf_x86_64
+OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+LDFLAGS=-e stext
+LINKFLAGS =-T $(TOPDIR)/arch/x86_64/vmlinux.lds $(LDFLAGS)
+
+CFLAGS += -mno-red-zone
+CFLAGS += -mcmodel=kernel
+CFLAGS += -pipe
+CFLAGS += -fno-reorder-blocks
+# needed for later gcc 3.1
+CFLAGS += -finline-limit=2000
+# needed for earlier gcc 3.1
+CFLAGS += -fno-strength-reduce
+#CFLAGS += -g
+
+# prevent gcc from keeping the stack 16 byte aligned (FIXME)
+#CFLAGS += -mpreferred-stack-boundary=2
+
+HEAD := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o
+
+SUBDIRS := arch/x86_64/tools $(SUBDIRS) arch/x86_64/kernel arch/x86_64/mm arch/x86_64/lib
+CORE_FILES := arch/x86_64/kernel/kernel.o $(CORE_FILES)
+CORE_FILES +=  arch/x86_64/mm/mm.o
+LIBS := $(TOPDIR)/arch/x86_64/lib/lib.a $(LIBS)
+
+ifdef CONFIG_IA32_EMULATION
+SUBDIRS += arch/x86_64/ia32
+CORE_FILES += arch/x86_64/ia32/ia32.o
+endif
+
+ifdef CONFIG_HOSTFS
+SUBDIRS += arch/x86_64/hostfs
+core-$(CONFIG_HOSTFS) += arch/x86_64/hostfs/hostfs.o
+endif
+
+CORE_FILES += $(core-y)
+
+arch/x86_64/tools: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/x86_64/tools 
+
+arch/x86_64/kernel: dummy 
+	$(MAKE) linuxsubdirs SUBDIRS=arch/x86_64/kernel
+
+arch/x86_64/mm: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/x86_64/mm
+
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+vmlinux: arch/x86_64/vmlinux.lds
+
+FORCE: ;
+
+.PHONY: zImage bzImage compressed zlilo bzlilo zdisk bzdisk install \
+		clean archclean archmrproper archdep checkoffset
+
+checkoffset: FORCE
+	make -C arch/$(ARCH)/tools $(TOPDIR)/include/asm-x86_64/offset.h
+
+bzImage: checkoffset vmlinux
+	@$(MAKEBOOT) bzImage
+
+bzImage-padded: checkoffset vmlinux
+	@$(MAKEBOOT) bzImage-padded
+
+tmp:
+	@$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
+
+bzlilo: checkoffset vmlinux
+	@$(MAKEBOOT) BOOTIMAGE=bzImage zlilo
+
+bzdisk: checkoffset vmlinux
+	@$(MAKEBOOT) BOOTIMAGE=bzImage zdisk
+
+install: checkoffset vmlinux
+	@$(MAKEBOOT) BOOTIMAGE=bzImage install
+
+archclean:
+	@$(MAKEBOOT) clean
+	@$(MAKE) -C $(TOPDIR)/arch/x86_64/tools clean
+
+archmrproper:
+	rm -f $(TOPDIR)/arch/x86_64/tools/offset.h
+	rm -f $(TOPDIR)/arch/x86_64/tools/offset.tmp
+	rm -f $(TOPDIR)/include/asm-x86_64/offset.h
+
+archdep:
+	@$(MAKE) -C $(TOPDIR)/arch/x86_64/tools all
+	@$(MAKEBOOT) dep
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/Makefile linux/arch/x86_64/boot/Makefile
--- linux.orig/arch/x86_64/boot/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/Makefile	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,92 @@
+#
+# arch/x86_64/boot/Makefile
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+
+BOOT_INCL =	$(TOPDIR)/include/linux/config.h \
+		$(TOPDIR)/include/linux/autoconf.h \
+		$(TOPDIR)/include/asm/boot.h
+
+zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
+	$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
+	tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) > zImage
+
+bzImage: $(CONFIGURE) bbootsect bsetup compressed/bvmlinux tools/build
+	$(OBJCOPY) compressed/bvmlinux compressed/bvmlinux.out
+	tools/build -b bbootsect bsetup compressed/bvmlinux.out $(ROOT_DEV) > bzImage
+
+bzImage-padded: bzImage
+	dd if=/dev/zero bs=1k count=70 >> bzImage
+
+compressed/vmlinux: $(TOPDIR)/vmlinux
+	@$(MAKE) -C compressed vmlinux
+
+compressed/bvmlinux: $(TOPDIR)/vmlinux
+	@$(MAKE) -C compressed bvmlinux
+
+zdisk: $(BOOTIMAGE)
+	dd bs=8192 if=$(BOOTIMAGE) of=/dev/fd0
+
+zlilo: $(CONFIGURE) $(BOOTIMAGE)
+	if [ -f $(INSTALL_PATH)/vmlinuz ]; then mv $(INSTALL_PATH)/vmlinuz $(INSTALL_PATH)/vmlinuz.old; fi
+	if [ -f $(INSTALL_PATH)/System.map ]; then mv $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+	cat $(BOOTIMAGE) > $(INSTALL_PATH)/vmlinuz
+	cp $(TOPDIR)/System.map $(INSTALL_PATH)/
+	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
+install: $(CONFIGURE) $(BOOTIMAGE)
+	sh -x ./install.sh $(KERNELRELEASE) $(BOOTIMAGE) $(TOPDIR)/System.map "$(INSTALL_PATH)"
+
+tools/build: tools/build.c
+	$(HOSTCC) $(HOSTCFLAGS) -o $@ $<
+
+bootsect: bootsect.o
+	$(IA32_LD) -Ttext 0x0 -s --oformat binary -o $@ $<
+
+bootsect.o: bootsect.s
+	$(IA32_AS) -o $@ $<
+
+bootsect.s: bootsect.S Makefile $(BOOT_INCL)
+	$(IA32_CPP) $(CPPFLAGS) -traditional -D__ASSEMBLY__ $(SVGA_MODE) $(RAMDISK) $< -o $@
+
+bbootsect: bbootsect.o
+	$(IA32_LD) -Ttext 0x0 -s --oformat binary $< -o $@
+
+bbootsect.o: bbootsect.s
+	$(IA32_AS) -o $@ $<
+
+bbootsect.s: bootsect.S Makefile $(BOOT_INCL)
+	$(IA32_CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
+
+setup: setup.o
+	$(IA32_LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $<
+
+setup.o: setup.s
+	$(IA32_AS) -o $@ $<
+
+setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
+	$(IA32_CPP) $(CPPFLAGS) -traditional -D__ASSEMBLY__ $(SVGA_MODE) $(RAMDISK) $< -o $@
+
+bsetup: bsetup.o
+	$(IA32_LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ $<
+
+bsetup.o: bsetup.s
+	$(IA32_AS) -o $@ $<
+
+bsetup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)/include/linux/version.h $(TOPDIR)/include/linux/compile.h
+	$(IA32_CPP) $(CPPFLAGS) -D__BIG_KERNEL__ -D__ASSEMBLY__ -traditional $(SVGA_MODE) $(RAMDISK) $< -o $@
+
+dep:
+
+clean:
+	rm -f tools/build
+	rm -f setup bootsect zImage compressed/vmlinux.out
+	rm -f bsetup bbootsect bzImage compressed/bvmlinux.out
+	@$(MAKE) -C compressed clean
+
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/bootsect.S linux/arch/x86_64/boot/bootsect.S
--- linux.orig/arch/x86_64/boot/bootsect.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/bootsect.S	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,418 @@
+/*
+ *	bootsect.S		Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ *	modified by Drew Eckhardt
+ *	modified by Bruce Evans (bde)
+ *	modified by Chris Noe (May 1999) (as86 -> gas)
+ *
+ * 360k/720k disk support: Andrzej Krzysztofowicz <ankry@green.mif.pg.gda.pl>
+ *
+ * BIG FAT NOTE: We're in real mode using 64k segments.  Therefore segment
+ * addresses must be multiplied by 16 to obtain their respective linear
+ * addresses. To avoid confusion, linear addresses are written using leading
+ * hex while segment addresses are written as segment:offset.
+ *
+ * bde - should not jump blindly, there may be systems with only 512K low
+ * memory.  Use int 0x12 to get the top of memory, etc.
+ *
+ * It then loads 'setup' directly after itself (0x90200), and the system
+ * at 0x10000, using BIOS interrupts. 
+ *
+ * NOTE! currently system is at most (8*65536-4096) bytes long. This should 
+ * be no problem, even in the future. I want to keep it simple. This 508 kB
+ * kernel size should be enough, especially as this doesn't contain the
+ * buffer cache as in minix (and especially now that the kernel is 
+ * compressed :-)
+ *
+ * The loader has been made as simple as possible, and continuous
+ * read errors will result in a unbreakable loop. Reboot by hand. It
+ * loads pretty fast by getting whole tracks at a time whenever possible.
+ */
+
+#include <asm/boot.h>
+
+SETUPSECTS	= 4			/* default nr of setup-sectors */
+BOOTSEG		= 0x07C0		/* original address of boot-sector */
+INITSEG		= DEF_INITSEG		/* we move boot here - out of the way */
+SETUPSEG	= DEF_SETUPSEG		/* setup starts here */
+SYSSEG		= DEF_SYSSEG		/* system loaded at 0x10000 (65536) */
+SYSSIZE		= DEF_SYSSIZE		/* system size: # of 16-byte clicks */
+					/* to be loaded */
+ROOT_DEV	= 0 			/* ROOT_DEV is now written by "build" */
+SWAP_DEV	= 0			/* SWAP_DEV is now written by "build" */
+
+#ifndef SVGA_MODE
+#define SVGA_MODE ASK_VGA
+#endif
+
+#ifndef RAMDISK
+#define RAMDISK 0
+#endif
+
+#ifndef ROOT_RDONLY
+#define ROOT_RDONLY 1
+#endif
+
+.code16
+.text
+
+.global _start
+_start:
+
+# First things first. Move ourself from 0x7C00 -> 0x90000 and jump there.
+
+	movw	$BOOTSEG, %ax
+	movw	%ax, %ds		# %ds = BOOTSEG
+	movw	$INITSEG, %ax
+	movw	%ax, %es		# %ax = %es = INITSEG
+	movw	$256, %cx
+	subw	%si, %si
+	subw	%di, %di
+	cld
+	rep
+	movsw
+	ljmp	$INITSEG, $go
+
+# bde - changed 0xff00 to 0x4000 to use debugger at 0x6400 up (bde).  We
+# wouldn't have to worry about this if we checked the top of memory.  Also
+# my BIOS can be configured to put the wini drive tables in high memory
+# instead of in the vector table.  The old stack might have clobbered the
+# drive table.
+
+go:	movw	$0x4000-12, %di		# 0x4000 is an arbitrary value >=
+					# length of bootsect + length of
+					# setup + room for stack;
+					# 12 is disk parm size.
+	movw	%ax, %ds		# %ax and %es already contain INITSEG
+	movw	%ax, %ss
+	movw	%di, %sp		# put stack at INITSEG:0x4000-12.
+
+# Many BIOS's default disk parameter tables will not recognize
+# multi-sector reads beyond the maximum sector number specified
+# in the default diskette parameter tables - this may mean 7
+# sectors in some cases.
+#
+# Since single sector reads are slow and out of the question,
+# we must take care of this by creating new parameter tables
+# (for the first disk) in RAM.  We will set the maximum sector
+# count to 36 - the most we will encounter on an ED 2.88.  
+#
+# High doesn't hurt.  Low does.
+#
+# Segments are as follows: %cs = %ds = %es = %ss = INITSEG, %fs = 0,
+# and %gs is unused.
+
+	movw	%cx, %fs		# %fs = 0
+	movw	$0x78, %bx		# %fs:%bx is parameter table address
+	pushw	%ds
+	ldsw	%fs:(%bx), %si		# %ds:%si is source
+	movb	$6, %cl			# copy 12 bytes
+	pushw	%di			# %di = 0x4000-12.
+	rep				# don't worry about cld
+	movsw				# already done above
+	popw	%di
+	popw	%ds
+	movb	$36, 0x4(%di)		# patch sector count
+	movw	%di, %fs:(%bx)
+	movw	%es, %fs:2(%bx)
+
+# Get disk drive parameters, specifically number of sectors/track.
+
+# It seems that there is no BIOS call to get the number of sectors.
+# Guess 36 sectors if sector 36 can be read, 18 sectors if sector 18
+# can be read, 15 if sector 15 can be read.  Otherwise guess 9.
+# Note that %cx = 0 from rep movsw above.
+
+	movw	$disksizes, %si		# table of sizes to try
+probe_loop:
+	lodsb
+	cbtw				# extend to word
+	movw	%ax, sectors
+	cmpw	$disksizes+4, %si
+	jae	got_sectors		# If all else fails, try 9
+
+	xchgw	%cx, %ax		# %cx = track and sector
+	xorw	%dx, %dx		# drive 0, head 0
+	movw	$0x0200, %bx		# address = 512, in INITSEG (%es = %cs)
+	movw	$0x0201, %ax		# service 2, 1 sector
+	int	$0x13
+	jc	probe_loop		# try next value
+
+got_sectors:
+	movb	$0x03, %ah		# read cursor pos
+	xorb	%bh, %bh
+	int	$0x10
+	movw	$9, %cx
+	movb	$0x07, %bl		# page 0, attribute 7 (normal)
+					# %bh is set above; int10 doesn't
+					# modify it
+	movw	$msg1, %bp
+	movw	$0x1301, %ax		# write string, move cursor
+	int	$0x10			# tell the user we're loading..
+
+# Load the setup-sectors directly after the moved bootblock (at 0x90200).
+# We should know the drive geometry to do it, as setup may exceed first
+# cylinder (for 9-sector 360K and 720K floppies).
+
+	movw	$0x0001, %ax		# set sread (sector-to-read) to 1 as
+	movw	$sread, %si		# the boot sector has already been read
+	movw	%ax, (%si)
+
+	xorw	%ax, %ax		# reset FDC
+	xorb	%dl, %dl
+	int	$0x13
+	movw	$0x0200, %bx		# address = 512, in INITSEG
+next_step:
+	movb	setup_sects, %al
+	movw	sectors, %cx
+	subw	(%si), %cx		# (%si) = sread
+	cmpb	%cl, %al
+	jbe	no_cyl_crossing
+	movw	sectors, %ax
+	subw	(%si), %ax		# (%si) = sread
+no_cyl_crossing:
+	call	read_track
+	pushw	%ax			# save it
+	call	set_next		# set %bx properly; it uses %ax,%cx,%dx
+	popw	%ax			# restore
+	subb	%al, setup_sects	# rest - for next step
+	jnz	next_step
+
+	pushw	$SYSSEG
+	popw	%es			# %es = SYSSEG
+	call	read_it
+	call	kill_motor
+	call	print_nl
+
+# After that we check which root-device to use. If the device is
+# defined (!= 0), nothing is done and the given device is used.
+# Otherwise, one of /dev/fd0H2880 (2,32) or /dev/PS0 (2,28) or /dev/at0 (2,8)
+# depending on the number of sectors we pretend to know we have.
+
+# Segments are as follows: %cs = %ds = %ss = INITSEG,
+#	%es = SYSSEG, %fs = 0, %gs is unused.
+
+	movw	root_dev, %ax
+	orw	%ax, %ax
+	jne	root_defined
+
+	movw	sectors, %bx
+	movw	$0x0208, %ax		# /dev/ps0 - 1.2Mb
+	cmpw	$15, %bx
+	je	root_defined
+
+	movb	$0x1c, %al		# /dev/PS0 - 1.44Mb
+	cmpw	$18, %bx
+	je	root_defined
+
+	movb	$0x20, %al		# /dev/fd0H2880 - 2.88Mb
+	cmpw	$36, %bx
+	je	root_defined
+
+	movb	$0, %al			# /dev/fd0 - autodetect
+root_defined:
+	movw	%ax, root_dev
+
+# After that (everything loaded), we jump to the setup-routine
+# loaded directly after the bootblock:
+
+	ljmp	$SETUPSEG, $0
+
+# These variables are addressed via %si register as it gives shorter code.
+
+sread:	.word 0				# sectors read of current track
+head:	.word 0				# current head
+track:	.word 0				# current track
+
+# This routine loads the system at address SYSSEG, making sure
+# no 64kB boundaries are crossed. We try to load it as fast as
+# possible, loading whole tracks whenever we can.
+
+read_it:
+	movw	%es, %ax		# %es = SYSSEG when called
+	testw	$0x0fff, %ax
+die:	jne	die			# %es must be at 64kB boundary
+	xorw	%bx, %bx		# %bx is starting address within segment
+rp_read:
+#ifdef __BIG_KERNEL__			# look in setup.S for bootsect_kludge
+	bootsect_kludge = 0x220		# 0x200 + 0x20 which is the size of the
+	lcall	bootsect_kludge		# bootsector + bootsect_kludge offset
+#else
+	movw	%es, %ax
+	subw	$SYSSEG, %ax
+	movw	%bx, %cx
+	shr	$4, %cx
+	add	%cx, %ax		# check offset
+#endif
+	cmpw	syssize, %ax		# have we loaded everything yet?
+	jbe	ok1_read
+
+	ret
+
+ok1_read:
+	movw	sectors, %ax
+	subw	(%si), %ax		# (%si) = sread
+	movw	%ax, %cx
+	shlw	$9, %cx
+	addw	%bx, %cx
+	jnc	ok2_read
+
+	je	ok2_read
+
+	xorw	%ax, %ax
+	subw	%bx, %ax
+	shrw	$9, %ax
+ok2_read:
+	call	read_track
+	call	set_next
+	jmp	rp_read
+
+read_track:
+	pusha
+	pusha	
+	movw	$0xe2e, %ax 		# loading... message 2e = .
+	movw	$7, %bx
+ 	int	$0x10
+	popa		
+
+# Accessing head, track, sread via %si gives shorter code.
+
+	movw	4(%si), %dx		# 4(%si) = track
+	movw	(%si), %cx		# (%si)  = sread
+	incw	%cx
+	movb	%dl, %ch
+	movw	2(%si), %dx		# 2(%si) = head
+	movb	%dl, %dh
+	andw	$0x0100, %dx
+	movb	$2, %ah
+	pushw	%dx			# save for error dump
+	pushw	%cx
+	pushw	%bx
+	pushw	%ax
+	int	$0x13
+	jc	bad_rt
+
+	addw	$8, %sp
+	popa
+	ret
+
+set_next:
+	movw	%ax, %cx
+	addw	(%si), %ax		# (%si) = sread
+	cmp	sectors, %ax
+	jne	ok3_set
+	movw	$0x0001, %ax
+	xorw	%ax, 2(%si)		# change head
+	jne	ok4_set
+	incw	4(%si)			# next track
+ok4_set:
+	xorw	%ax, %ax
+ok3_set:
+	movw	%ax, (%si)		# set sread
+	shlw	$9, %cx
+	addw	%cx, %bx
+	jnc	set_next_fin
+	movw	%es, %ax
+	addb	$0x10, %ah
+	movw	%ax, %es
+	xorw	%bx, %bx
+set_next_fin:
+	ret
+
+bad_rt:
+	pushw	%ax			# save error code
+	call	print_all		# %ah = error, %al = read
+	xorb	%ah, %ah
+	xorb	%dl, %dl
+	int	$0x13
+	addw	$10, %sp
+	popa
+	jmp read_track
+
+# print_all is for debugging purposes.  
+#
+# it will print out all of the registers.  The assumption is that this is
+# called from a routine, with a stack frame like
+#
+#	%dx 
+#	%cx
+#	%bx
+#	%ax
+#	(error)
+#	ret <- %sp
+ 
+print_all:
+	movw	$5, %cx			# error code + 4 registers
+	movw	%sp, %bp
+print_loop:
+	pushw	%cx			# save count remaining
+	call	print_nl		# <-- for readability
+	cmpb	$5, %cl
+	jae	no_reg			# see if register name is needed
+	
+	movw	$0xe05 + 'A' - 1, %ax
+	subb	%cl, %al
+	int	$0x10
+	movb	$'X', %al
+	int	$0x10
+	movb	$':', %al
+	int	$0x10
+no_reg:
+	addw	$2, %bp			# next register
+	call	print_hex		# print it
+	popw	%cx
+	loop	print_loop
+	ret
+
+print_nl:
+	movw	$0xe0d, %ax		# CR
+	int	$0x10
+	movb	$0xa, %al		# LF
+	int 	$0x10
+	ret
+
+# print_hex is for debugging purposes, and prints the word
+# pointed to by %ss:%bp in hexadecimal.
+
+print_hex:
+	movw	$4, %cx			# 4 hex digits
+	movw	(%bp), %dx		# load word into %dx
+print_digit:
+	rolw	$4, %dx			# rotate to use low 4 bits
+	movw	$0xe0f, %ax		# %ah = request
+	andb	%dl, %al		# %al = mask for nybble
+	addb	$0x90, %al		# convert %al to ascii hex
+	daa				# in only four instructions!
+	adc	$0x40, %al
+	daa
+	int	$0x10
+	loop	print_digit
+	ret
+
+# This procedure turns off the floppy drive motor, so
+# that we enter the kernel in a known state, and
+# don't have to worry about it later.
+# NOTE: Doesn't save %ax or %dx; do it yourself if you need to.
+
+kill_motor:
+	movw	$0x3f2, %dx
+	xorb	%al, %al
+	outb	%al, %dx
+	ret
+
+sectors:	.word 0
+disksizes:	.byte 36, 18, 15, 9
+msg1:		.byte 13, 10
+		.ascii "Loading"
+
+# XXX: This is a fairly snug fit.
+
+.org 497
+setup_sects:	.byte SETUPSECTS
+root_flags:	.word ROOT_RDONLY
+syssize:	.word SYSSIZE
+swap_dev:	.word SWAP_DEV
+ram_size:	.word RAMDISK
+vid_mode:	.word SVGA_MODE
+root_dev:	.word ROOT_DEV
+boot_flag:	.word 0xAA55
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/compressed/Makefile linux/arch/x86_64/boot/compressed/Makefile
--- linux.orig/arch/x86_64/boot/compressed/Makefile	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/compressed/Makefile	2002-08-12 22:14:18.000000000 +0000
@@ -0,0 +1,43 @@
+#
+# linux/arch/i386/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux
+#
+
+HEAD = head.o
+SYSTEM = $(TOPDIR)/vmlinux
+
+OBJECTS = $(HEAD) misc.o
+
+IA32_CFLAGS := -O2 -DSTDC_HEADERS
+
+#
+# ZIMAGE_OFFSET is the load offset of the compression loader
+# BZIMAGE_OFFSET is the load offset of the high loaded compression loader
+#
+BZIMAGE_OFFSET = 0x100000
+
+BZLINKFLAGS = -Ttext $(BZIMAGE_OFFSET) $(ZLDFLAGS)
+
+all: vmlinux
+
+bvmlinux: piggy.o $(OBJECTS)
+	$(IA32_LD) $(BZLINKFLAGS) -o bvmlinux $(OBJECTS) piggy.o
+
+head.o: head.S
+	$(IA32_AS) -c head.S
+
+misc.o: misc.c
+	$(IA32_CC) $(IA32_CFLAGS) -c misc.c
+
+piggy.o:	$(SYSTEM)
+	tmppiggy=_tmp_$$$$piggy; \
+	rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk; \
+	$(OBJCOPY) $(SYSTEM) $$tmppiggy; \
+	gzip -f -9 < $$tmppiggy > $$tmppiggy.gz; \
+	echo "SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data) input_data = .; *(.data) input_data_end = .; }}" > $$tmppiggy.lnk; \
+	$(IA32_LD) -r -o piggy.o -b binary $$tmppiggy.gz -b elf32-i386 -T $$tmppiggy.lnk; \
+	rm -f $$tmppiggy $$tmppiggy.gz $$tmppiggy.lnk
+
+clean:
+	rm -f vmlinux bvmlinux _tmp_*
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/compressed/head.S linux/arch/x86_64/boot/compressed/head.S
--- linux.orig/arch/x86_64/boot/compressed/head.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/compressed/head.S	2002-08-12 22:14:02.000000000 +0000
@@ -0,0 +1,142 @@
+/*
+ *  linux/boot/head.S
+ *
+ *  Copyright (C) 1991, 1992, 1993  Linus Torvalds
+ *
+ *  $Id: head.S,v 1.3 2001/04/20 00:59:28 ak Exp $	 		
+ */
+
+/*
+ *  head.S contains the 32-bit startup code.
+ *
+ * NOTE!!! Startup happens at absolute address 0x00001000, which is also where
+ * the page directory will exist. The startup code will be overwritten by
+ * the page directory. [According to comments etc elsewhere on a compressed
+ * kernel it will end up at 0x1000 + 1Mb I hope so as I assume this. - AC]
+ *
+ * Page 0 is deliberately kept safe, since System Management Mode code in 
+ * laptops may need to access the BIOS data stored there.  This is also
+ * useful for future device drivers that either access the BIOS via VM86 
+ * mode.
+ */
+
+/*
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996	
+ */
+.code32
+.text
+
+#include <linux/linkage.h>
+#include <asm/segment.h>
+
+	.code32
+	.globl startup_32
+	
+startup_32:
+	cld
+	cli
+	movl $(__KERNEL_DS),%eax
+	movl %eax,%ds
+	movl %eax,%es
+	movl %eax,%fs
+	movl %eax,%gs
+
+	lss SYMBOL_NAME(stack_start),%esp
+	xorl %eax,%eax
+1:	incl %eax		# check that A20 really IS enabled
+	movl %eax,0x000000	# loop forever if it isn't
+	cmpl %eax,0x100000
+	je 1b
+
+/*
+ * Initialize eflags.  Some BIOS's leave bits like NT set.  This would
+ * confuse the debugger if this code is traced.
+ * XXX - best to initialize before switching to protected mode.
+ */
+	pushl $0
+	popfl
+/*
+ * Clear BSS
+ */
+	xorl %eax,%eax
+	movl $ SYMBOL_NAME(_edata),%edi
+	movl $ SYMBOL_NAME(_end),%ecx
+	subl %edi,%ecx
+	cld
+	rep
+	stosb
+/*
+ * Do the decompression, and jump to the new kernel..
+ */
+	subl $16,%esp	# place for structure on the stack
+	movl %esp,%eax
+	pushl %esi	# real mode pointer as second arg
+	pushl %eax	# address of structure as first arg
+	call SYMBOL_NAME(decompress_kernel)
+	orl  %eax,%eax 
+	jnz  3f
+	addl $8,%esp
+	xorl %ebx,%ebx
+	ljmp $(__KERNEL_CS), $0x100000
+
+/*
+ * We come here, if we were loaded high.
+ * We need to move the move-in-place routine down to 0x1000
+ * and then start it with the buffer addresses in registers,
+ * which we got from the stack.
+ */
+3:
+	movl %esi,%ebx	
+	movl $move_routine_start,%esi
+	movl $0x1000,%edi
+	movl $move_routine_end,%ecx
+	subl %esi,%ecx
+	addl $3,%ecx
+	shrl $2,%ecx
+	cld
+	rep
+	movsl
+
+	popl %esi	# discard the address
+	addl $4,%esp	# real mode pointer
+	popl %esi	# low_buffer_start
+	popl %ecx	# lcount
+	popl %edx	# high_buffer_start
+	popl %eax	# hcount
+	movl $0x100000,%edi
+	cli		# make sure we don't get interrupted
+	ljmp $(__KERNEL_CS), $0x1000 # and jump to the move routine
+
+/*
+ * Routine (template) for moving the decompressed kernel in place,
+ * if we were high loaded. This _must_ PIC-code !
+ */
+move_routine_start:
+	movl %ecx,%ebp
+	shrl $2,%ecx
+	rep
+	movsl
+	movl %ebp,%ecx
+	andl $3,%ecx
+	rep
+	movsb
+	movl %edx,%esi
+	movl %eax,%ecx	# NOTE: rep movsb won't move if %ecx == 0
+	addl $3,%ecx
+	shrl $2,%ecx
+	rep
+	movsl
+	movl %ebx,%esi	# Restore setup pointer
+	xorl %ebx,%ebx
+	ljmp $(__KERNEL_CS), $0x100000
+move_routine_end:
+
+
+/* Stack for uncompression */ 	
+	.align 32
+user_stack:	 	
+	.fill 4096,4,0
+stack_start:	
+	.long user_stack+4096
+	.word __KERNEL_DS
+
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/compressed/misc.c linux/arch/x86_64/boot/compressed/misc.c
--- linux.orig/arch/x86_64/boot/compressed/misc.c	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/compressed/misc.c	2002-08-12 22:14:10.000000000 +0000
@@ -0,0 +1,431 @@
+/*
+ * misc.c
+ * 
+ * This is a collection of several routines from gzip-1.0.3 
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+ * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
+ */
+
+#include "miscsetup.h"
+#include <asm/io.h>
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+#undef memset
+#undef memcpy
+#define memzero(s, n)     memset ((s), 0, (n))
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000		/* Window size must be at least 32k, */
+				/* and a power of two */
+
+static uch *inbuf;	     /* input buffer */
+static uch window[WSIZE];    /* Sliding window buffer */
+
+static unsigned insize = 0;  /* valid bytes in inbuf */
+static unsigned inptr = 0;   /* index of next byte to be processed in inbuf */
+static unsigned outcnt = 0;  /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+#define get_byte()  (inptr < insize ? inbuf[inptr++] : fill_inbuf())
+		
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (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
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+  
+/*
+ * This is set up by the setup-routine at boot-time
+ */
+static unsigned char *real_mode; /* Pointer to real-mode data */
+
+#define EXT_MEM_K   (*(unsigned short *)(real_mode + 0x2))
+#ifndef STANDARD_MEMORY_BIOS_CALL
+#define ALT_MEM_K   (*(unsigned long *)(real_mode + 0x1e0))
+#endif
+#define SCREEN_INFO (*(struct screen_info *)(real_mode+0))
+
+extern char input_data[];
+extern int input_len;
+
+static long bytes_out = 0;
+static uch *output_data;
+static unsigned long output_ptr = 0;
+
+ 
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+ 
+static void puts(const char *);
+  
+extern int end;
+static long free_mem_ptr = (long)&end;
+static long free_mem_end_ptr;
+
+#define INPLACE_MOVE_ROUTINE  0x1000
+#define LOW_BUFFER_START      0x2000
+#define LOW_BUFFER_MAX       0x90000
+#define HEAP_SIZE             0x3000
+static unsigned int low_buffer_end, low_buffer_size;
+static int high_loaded =0;
+static uch *high_buffer_start /* = (uch *)(((ulg)&end) + HEAP_SIZE)*/;
+
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
+
+#include "../../../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+	void *p;
+
+	if (size <0) error("Malloc error\n");
+	if (free_mem_ptr <= 0) error("Memory error\n");
+
+	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+
+	p = (void *)free_mem_ptr;
+	free_mem_ptr += size;
+
+	if (free_mem_ptr >= free_mem_end_ptr)
+		error("\nOut of memory\n");
+
+	return p;
+}
+
+static void free(void *where)
+{	/* Don't care */
+}
+
+static void gzip_mark(void **ptr)
+{
+	*ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+	free_mem_ptr = (long) *ptr;
+}
+ 
+static void scroll(void)
+{
+	int i;
+
+	memcpy ( vidmem, vidmem + cols * 2, ( lines - 1 ) * cols * 2 );
+	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
+		vidmem[i] = ' ';
+}
+
+static void puts(const char *s)
+{
+	int x,y,pos;
+	char c;
+
+	x = SCREEN_INFO.orig_x;
+	y = SCREEN_INFO.orig_y;
+
+	while ( ( c = *s++ ) != '\0' ) {
+		if ( c == '\n' ) {
+			x = 0;
+			if ( ++y >= lines ) {
+				scroll();
+				y--;
+			}
+		} else {
+			vidmem [ ( x + cols * y ) * 2 ] = c; 
+			if ( ++x >= cols ) {
+				x = 0;
+				if ( ++y >= lines ) {
+					scroll();
+					y--;
+				}
+			}
+		}
+	}
+
+	SCREEN_INFO.orig_x = x;
+	SCREEN_INFO.orig_y = y;
+
+	pos = (x + cols * y) * 2;	/* Update cursor position */
+	outb_p(14, vidport);
+	outb_p(0xff & (pos >> 9), vidport+1);
+	outb_p(15, vidport);
+	outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+void* memset(void* s, int c, size_t n)
+{
+	int i;
+	char *ss = (char*)s;
+
+	for (i=0;i<n;i++) ss[i] = c;
+	return s;
+}
+
+void* memcpy(void* __dest, __const void* __src,
+			    size_t __n)
+{
+	int i;
+	char *d = (char *)__dest, *s = (char *)__src;
+
+	for (i=0;i<__n;i++) d[i] = s[i];
+	return __dest;
+}
+
+/* ===========================================================================
+ * Fill the input buffer. This is called only when the buffer is empty
+ * and at least one byte is really needed.
+ */
+static int fill_inbuf(void)
+{
+	if (insize != 0) {
+		error("ran out of input data\n");
+	}
+
+	inbuf = input_data;
+	insize = input_len;
+	inptr = 1;
+	return inbuf[0];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+static void flush_window_low(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+    
+    in = window;
+    out = &output_data[output_ptr]; 
+    for (n = 0; n < outcnt; n++) {
+	    ch = *out++ = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window_high(void)
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in,  ch;
+    in = window;
+    for (n = 0; n < outcnt; n++) {
+	ch = *output_data++ = *in++;
+	if ((ulg)output_data == low_buffer_end) output_data=high_buffer_start;
+	c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void flush_window(void)
+{
+	if (high_loaded) flush_window_high();
+	else flush_window_low();
+}
+
+static void error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted");
+
+	while(1);	/* Halt */
+}
+
+void setup_normal_output_buffer(void)
+{
+#ifdef STANDARD_MEMORY_BIOS_CALL
+	if (EXT_MEM_K < 1024) error("Less than 2MB of memory.\n");
+#else
+	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < 1024) error("Less than 2MB of memory.\n");
+#endif
+	output_data = (char *)0x100000; /* Points to 1M */
+	free_mem_end_ptr = (long)real_mode;
+}
+
+struct moveparams {
+	uch *low_buffer_start;  int lcount;
+	uch *high_buffer_start; int hcount;
+};
+
+void setup_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+	high_buffer_start = (uch *)(((ulg)&end) + HEAP_SIZE);
+#ifdef STANDARD_MEMORY_BIOS_CALL
+	if (EXT_MEM_K < (3*1024)) error("Less than 4MB of memory.\n");
+#else
+	if ((ALT_MEM_K > EXT_MEM_K ? ALT_MEM_K : EXT_MEM_K) < (3*1024)) error("Less than 4MB of memory.\n");
+#endif	
+	mv->low_buffer_start = output_data = (char *)LOW_BUFFER_START;
+	low_buffer_end = ((unsigned int)real_mode > LOW_BUFFER_MAX
+	  ? LOW_BUFFER_MAX : (unsigned int)real_mode) & ~0xfff;
+	low_buffer_size = low_buffer_end - LOW_BUFFER_START;
+	high_loaded = 1;
+	free_mem_end_ptr = (long)high_buffer_start;
+	if ( (0x100000 + low_buffer_size) > ((ulg)high_buffer_start)) {
+		high_buffer_start = (uch *)(0x100000 + low_buffer_size);
+		mv->hcount = 0; /* say: we need not to move high_buffer */
+	}
+	else mv->hcount = -1;
+	mv->high_buffer_start = high_buffer_start;
+}
+
+void close_output_buffer_if_we_run_high(struct moveparams *mv)
+{
+	if (bytes_out > low_buffer_size) {
+		mv->lcount = low_buffer_size;
+		if (mv->hcount)
+			mv->hcount = bytes_out - low_buffer_size;
+	} else {
+		mv->lcount = bytes_out;
+		mv->hcount = 0;
+	}
+}
+
+void check_cpu(void)
+{
+	int res = 0;
+	asm volatile( " \n\
+	movl $3,%%edx		# at least 386 \n\
+	pushfl			# push EFLAGS \n\
+	popl %%eax		# get EFLAGS \n\
+	movl %%eax,%%ecx		# save original EFLAGS \n\
+	xorl $0x40000,%%eax	# flip AC bit in EFLAGS \n\
+	pushl %%eax		# copy to EFLAGS \n\
+	popfl			# set EFLAGS \n\
+	pushfl			# get new EFLAGS \n\
+	popl %%eax		# put it in eax \n\
+	xorl %%ecx,%%eax		# change in flags \n\
+	andl $0x40000,%%eax	# check if AC bit changed \n\
+	je 1f \n\
+\n\
+	movl $4,%%edx		# at least 486 \n\
+	movl %%ecx,%%eax \n\
+	xorl $0x200000,%%eax	# check ID flag \n\
+	pushl %%eax \n\
+	popfl			# if we are on a straight 486DX, SX, or \n\
+	pushfl			# 487SX we can't change it \n\
+	popl %%eax \n\
+	xorl %%ecx,%%eax \n\
+	pushl %%ecx		# restore original EFLAGS \n\
+	popfl \n\
+	andl $0x200000,%%eax \n\
+	je 1f \n\
+\n\
+	/* get vendor info */ \n\
+#	xorl %%eax,%%eax			# call CPUID with 0 -> return vendor ID \n\
+#	cpuid \n\
+#	movl $5, %%edx \n\
+#	cmpl $0x41757468,%%ebx		# check thats amd \n\
+#	jne 1f \n\
+\n\
+	mov $0x80000000,%%eax		# Is extended cpuid supported?\n\
+	cpuid\n\
+	test $0x80000000,%%eax\n\
+	movl $5, %%edx \n\
+	jz 1f\n\
+\n\
+	movl $0x80000001,%%eax \n\
+	cpuid \n\
+	andl $0x20000000,%%edx \n\
+	movl $6, %%edx \n\
+	jz 1f \n\
+\n\
+	movl $7, %%edx \n\
+1:" : "=d" (res) : : "eax", "ebx", "ecx" );
+
+	switch (res) {
+	case 3: puts( "386" );
+		break;
+	case 4: puts( "486" );
+		break;
+	case 5: puts( "no extended cpuid" );
+		break;
+	case 6: puts( "non-64bit 586+" );
+		break;
+	case 7: puts( "64bit" );
+		break;
+	default:puts( "internal error" );
+		break;
+	}
+	if (res !=7)
+		error( "Sorry, your CPU is not capable of running 64-bit kernel." );
+}
+
+int decompress_kernel(struct moveparams *mv, void *rmode)
+{
+	real_mode = rmode;
+
+	if (SCREEN_INFO.orig_video_mode == 7) {
+		vidmem = (char *) 0xb0000;
+		vidport = 0x3b4;
+	} else {
+		vidmem = (char *) 0xb8000;
+		vidport = 0x3d4;
+	}
+
+	lines = SCREEN_INFO.orig_video_lines;
+	cols = SCREEN_INFO.orig_video_cols;
+
+	if (free_mem_ptr < 0x100000) setup_normal_output_buffer();
+	else setup_output_buffer_if_we_run_high(mv);
+
+	makecrc();
+	puts("Checking CPU type...");
+	check_cpu();
+	puts(".\nDecompressing Linux...");
+	gunzip();
+	puts("done.\nBooting the kernel.\n");
+	if (high_loaded) close_output_buffer_if_we_run_high(mv);
+	return high_loaded;
+}
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/compressed/miscsetup.h linux/arch/x86_64/boot/compressed/miscsetup.h
--- linux.orig/arch/x86_64/boot/compressed/miscsetup.h	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/compressed/miscsetup.h	2002-08-12 22:14:17.000000000 +0000
@@ -0,0 +1,39 @@
+#define NULL 0
+typedef unsigned int size_t; 
+
+
+struct screen_info {
+	unsigned char  orig_x;			/* 0x00 */
+	unsigned char  orig_y;			/* 0x01 */
+	unsigned short dontuse1;		/* 0x02 -- EXT_MEM_K sits here */
+	unsigned short orig_video_page;		/* 0x04 */
+	unsigned char  orig_video_mode;		/* 0x06 */
+	unsigned char  orig_video_cols;		/* 0x07 */
+	unsigned short unused2;			/* 0x08 */
+	unsigned short orig_video_ega_bx;	/* 0x0a */
+	unsigned short unused3;			/* 0x0c */
+	unsigned char  orig_video_lines;	/* 0x0e */
+	unsigned char  orig_video_isVGA;	/* 0x0f */
+	unsigned short orig_video_points;	/* 0x10 */
+
+	/* VESA graphic mode -- linear frame buffer */
+	unsigned short lfb_width;		/* 0x12 */
+	unsigned short lfb_height;		/* 0x14 */
+	unsigned short lfb_depth;		/* 0x16 */
+	unsigned long  lfb_base;		/* 0x18 */
+	unsigned long  lfb_size;		/* 0x1c */
+	unsigned short dontuse2, dontuse3;	/* 0x20 -- CL_MAGIC and CL_OFFSET here */
+	unsigned short lfb_linelength;		/* 0x24 */
+	unsigned char  red_size;		/* 0x26 */
+	unsigned char  red_pos;			/* 0x27 */
+	unsigned char  green_size;		/* 0x28 */
+	unsigned char  green_pos;		/* 0x29 */
+	unsigned char  blue_size;		/* 0x2a */
+	unsigned char  blue_pos;		/* 0x2b */
+	unsigned char  rsvd_size;		/* 0x2c */
+	unsigned char  rsvd_pos;		/* 0x2d */
+	unsigned short vesapm_seg;		/* 0x2e */
+	unsigned short vesapm_off;		/* 0x30 */
+	unsigned short pages;			/* 0x32 */
+						/* 0x34 -- 0x3f reserved for future expansion */
+};
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/install.sh linux/arch/x86_64/boot/install.sh
--- linux.orig/arch/x86_64/boot/install.sh	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/install.sh	2002-08-12 22:14:05.000000000 +0000
@@ -0,0 +1,39 @@
+#!/bin/sh
+#
+# arch/i386/boot/install.sh
+#
+# This file is subject to the terms and conditions of the GNU General Public
+# License.  See the file "COPYING" in the main directory of this archive
+# for more details.
+#
+# Copyright (C) 1995 by Linus Torvalds
+#
+# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
+#
+# "make install" script for i386 architecture
+#
+# Arguments:
+#   $1 - kernel version
+#   $2 - kernel image file
+#   $3 - kernel map file
+#   $4 - default install path (blank if root directory)
+#
+
+# User may have a custom install script
+
+if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
+
+# Default install - same as make zlilo
+
+if [ -f $4/vmlinuz ]; then
+	mv $4/vmlinuz $4/vmlinuz.old
+fi
+
+if [ -f $4/System.map ]; then
+	mv $4/System.map $4/System.old
+fi
+
+cat $2 > $4/vmlinuz
+cp $3 $4/System.map
+
+if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
diff -Naur -X /home/marcelo/lib/dontdiff linux.orig/arch/x86_64/boot/setup.S linux/arch/x86_64/boot/setup.S
--- linux.orig/arch/x86_64/boot/setup.S	1970-01-01 00:00:00.000000000 +0000
+++ linux/arch/x86_64/boot/setup.S	2002-08-12 22:14:24.000000000 +0000
@@ -0,0 +1,863 @@
+/*
+ *	setup.S		Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * setup.s is responsible for getting the system data from the BIOS,
+ * and putting them into the appropriate places in system memory.
+ * both setup.s and system has been loaded by the bootblock.
+ *
+ * This code asks the bios for memory/disk/other parameters, and
+ * puts them in a "safe" place: 0x90000-0x901FF, ie where the
+ * boot-block used to be. It is then up to the protected mode
+ * system to read them from there before the area is overwritten
+ * for buffer-blocks.
+ *
+ * Move PS/2 aux init code to psaux.c
+ * (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
+ *
+ * some changes and additional features by Christoph Niemann,
+ * March 1993/June 1994 (Christoph.Niemann@linux.org)
+ *
+ * add APM BIOS checking by Stephen Rothwell, May 1994
+ * (sfr@canb.auug.org.au)
+ *
+ * High load stuff, initrd support and position independency
+ * by Hans Lermen & Werner Almesberger, February 1996
+ * <lermen@elserv.ffm.fgan.de>, <almesber@lrc.epfl.ch>
+ *
+ * Video handling moved to video.S by Martin Mares, March 1996
+ * <mj@k332.feld.cvut.cz>
+ *
+ * Extended memory detection scheme retwiddled by orc@pell.chi.il.us (david
+ * parsons) to avoid loadlin confusion, July 1997
+ *
+ * Transcribed from Intel (as86) -> AT&T (gas) by Chris Noe, May 1999.
+ * <stiker@northlink.com>
+ *
+ * Fix to work around buggy BIOSes which dont use carry bit correctly
+ * and/or report extended memory in CX/DX for e801h memory size detection 
+ * call.  As a result the kernel got wrong figures.  The int15/e801h docs
+ * from Ralf Brown interrupt list seem to indicate AX/BX should be used
+ * anyway.  So to avoid breaking many machines (presumably there was a reason
+ * to orginally use CX/DX instead of AX/BX), we do a kludge to see
+ * if CX/DX have been changed in the e801 call and if so use AX/BX .
+ * Michael Miller, April 2001 <michaelm@mjmm.org>
+ *
+ */
+
+#include <linux/config.h>
+#include <asm/segment.h>
+#include <linux/version.h>
+#include <linux/compile.h>
+#include <asm/boot.h>
+#include <asm/e820.h>
+
+/* Signature words to ensure LILO loaded us right */
+#define SIG1	0xAA55
+#define SIG2	0x5A5A
+
+INITSEG  = DEF_INITSEG		# 0x9000, we move boot here, out of the way
+SYSSEG   = DEF_SYSSEG		# 0x1000, system loaded at 0x10000 (65536).
+SETUPSEG = DEF_SETUPSEG		# 0x9020, this is the current segment
+				# ... and the former contents of CS
+
+DELTA_INITSEG = SETUPSEG - INITSEG	# 0x0020
+
+.code16
+.globl begtext, begdata, begbss, endtext, enddata, endbss
+
+.text
+begtext:
+.data
+begdata:
+.bss
+begbss:
+.text
+
+start:
+	jmp	trampoline
+
+# This is the setup header, and it must start at %cs:2 (old 0x9020:2)
+
+		.ascii	"HdrS"		# header signature
+		.word	0x0202		# header version number (>= 0x0105)
+					# or else old loadlin-1.5 will fail)
+realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
+start_sys_seg:	.word	SYSSEG
+		.word	kernel_version	# pointing to kernel version string
+					# above section of header is compatible
+					# with loadlin-1.5 (header v1.5). Don't
+					# change it.
+
+type_of_loader:	.byte	0		# = 0, old one (LILO, Loadlin,
+					#      Bootlin, SYSLX, bootsect...)
+					# See Documentation/i386/boot.txt for
+					# assigned ids
+	
+# flags, unused bits must be zero (RFU) bit within loadflags
+loadflags:
+LOADED_HIGH	= 1			# If set, the kernel is loaded high
+CAN_USE_HEAP	= 0x80			# If set, the loader also has set
+					# heap_end_ptr to tell how much
+					# space behind setup.S can be used for
+					# heap purposes.
+					# Only the loader knows what is free
+#ifndef __BIG_KERNEL__
+		.byte	0
+#else
+		.byte	LOADED_HIGH
+#endif
+
+setup_move_size: .word  0x8000		# size to move, when setup is not
+					# loaded at 0x90000. We will move setup 
+					# to 0x90000 then just before jumping
+					# into the kernel. However, only the
+					# loader knows how much data behind
+					# us also needs to be loaded.
+
+code32_start:				# here loaders can put a different
+					# start address for 32-bit code.
+#ifndef __BIG_KERNEL__
+		.long	0x1000		#   0x1000 = default for zImage
+#else
+		.long	0x100000	# 0x100000 = default for big kernel
+#endif
+
+ramdisk_image:	.long	0		# address of loaded ramdisk image
+					# Here the loader puts the 32-bit
+					# address where it loaded the image.
+					# This only will be read by the kernel.
+
+ramdisk_size:	.long	0		# its size in bytes
+
+bootsect_kludge:
+		.word  bootsect_helper, SETUPSEG
+
+heap_end_ptr:	.word	modelist+1024	# (Header version 0x0201 or later)
+					# space from here (exclusive) down to
+					# end of setup code can be used by setup
+					# for local heap purposes.
+
+pad1:		.word	0
+cmd_line_ptr:	.long 0			# (Header version 0x0202 or later)
+					# If nonzero, a 32-bit pointer
+					# to the kernel command line.
+					# The command line should be
+					# located between the start of
+					# setup and the end of low
+					# memory (0xa0000), or it may
+					# get overwritten before it
+					# gets read.  If this field is
+					# used, there is no longer
+					# anything magical about the
+					# 0x90000 segment; the setup
+					# can be located anywhere in
+					# low memory 0x10000 or higher.
+
+trampoline:	call	start_of_setup
+		.space	1024
+# End of setup header #####################################################
+
+start_of_setup:
+# Bootlin depends on this being done early
+	movw	$0x01500, %ax
+	movb	$0x81, %dl
+	int	$0x13
+
+#ifdef SAFE_RESET_DISK_CONTROLLER
+# Reset the disk controller.
+	movw	$0x0000, %ax
+	movb	$0x80, %dl
+	int	$0x13
+#endif
+
+# Set %ds = %cs, we know that SETUPSEG = %cs at this point
+	movw	%cs, %ax		# aka SETUPSEG
+	movw	%ax, %ds
+# Check signature at end of setup
+	cmpw	$SIG1, setup_sig1
+	jne	bad_sig
+
+	cmpw	$SIG2, setup_sig2
+	jne	bad_sig
+
+	jmp	good_sig1
+
+# Routine to print asciiz string at ds:si
+prtstr:
+	lodsb
+	andb	%al, %al
+	jz	fin
+
+	call	prtchr
+	jmp	prtstr
+
+fin:	ret
+
+# Space printing
+prtsp2:	call	prtspc		# Print double space
+prtspc:	movb	$0x20, %al	# Print single space (note: fall-thru)
+
+# Part of above routine, this one just prints ascii al
+prtchr:	pushw	%ax
+	pushw	%cx
+	xorb	%bh, %bh
+	movw	$0x01, %cx
+	movb	$0x0e, %ah
+	int	$0x10
+	popw	%cx
+	popw	%ax
+	ret
+
+beep:	movb	$0x07, %al
+	jmp	prtchr
+	
+no_sig_mess: .string	"No setup signature found ..."
+
+good_sig1:
+	jmp	good_sig
+
+# We now have to find the rest of the setup code/data
+bad_sig:
+	movw	%cs, %ax			# SETUPSEG
+	subw	$DELTA_INITSEG, %ax		# INITSEG
+	movw	%ax, %ds
+	xorb	%bh, %bh
+	movb	(497), %bl			# get setup sect from bootsect
+	subw	$4, %bx				# LILO loads 4 sectors of setup
+	shlw	$8, %bx				# convert to words (1sect=2^8 words)
+	movw	%bx, %cx
+	shrw	$3, %bx				# convert to segment
+	addw	$SYSSEG, %bx
+	movw	%bx, %cs:start_sys_seg
+# Move rest of setup code/data to here
+	movw	$2048, %di			# four sectors loaded by LILO
+	subw	%si, %si
+	movw	%cs, %ax			# aka SETUPSEG
+	movw	%ax, %es
+	movw	$SYSSEG, %ax
+	movw	%ax, %ds
+	rep
+	movsw
+	movw	%cs, %ax			# aka SETUPSEG
+	movw	%ax, %ds
+	cmpw	$SIG1, setup_sig1
+	jne	no_sig
+
+	cmpw	$SIG2, setup_sig2
+	jne	no_sig
+
+	jmp	good_sig
+
+no_sig:
+	lea	no_sig_mess, %si
+	call	prtstr
+
+no_sig_loop:
+	jmp	no_sig_loop
+
+good_sig:
+	movw	%cs, %ax			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
+	movw	%ax, %ds
+# Check if an old loader tries to load a big-kernel
+	testb	$LOADED_HIGH, %cs:loadflags	# Do we have a big kernel?
+	jz	loader_ok			# No, no danger for old loaders.
+
+	cmpb	$0, %cs:type_of_loader 		# Do we have a loader that
+						# can deal with us?
+	jnz	loader_ok			# Yes, continue.
+
+	pushw	%cs				# No, we have an old loader,
+	popw	%ds				# die. 
+	lea	loader_panic_mess, %si
+	call	prtstr
+
+	jmp	no_sig_loop
+
+loader_panic_mess: .string "Wrong loader, giving up..."
+
+loader_ok:
+# Get memory size (extended mem, kB)
+
+	xorl	%eax, %eax
+	movl	%eax, (0x1e0)
+#ifndef STANDARD_MEMORY_BIOS_CALL
+	movb	%al, (E820NR)
+# Try three different memory detection schemes.  First, try
+# e820h, which lets us assemble a memory map, then try e801h,
+# which returns a 32-bit memory size, and finally 88h, which
+# returns 0-64m
+
+# method E820H:
+# the memory map from hell.  e820h returns memory classified into
+# a whole bunch of different types, and allows memory holes and
+# everything.  We scan through this memory map and build a list
+# of the first 32 memory areas, which we return at [E820MAP].
+# This is documented at http://www.teleport.com/~acpi/acpihtml/topic245.htm
+
+#define SMAP  0x534d4150
+
+meme820:
+	xorl	%ebx, %ebx			# continuation counter
+	movw	$E820MAP, %di			# point into the whitelist
+						# so we can have the bios
+						# directly write into it.
+
+jmpe820:
+	movl	$0x0000e820, %eax		# e820, upper word zeroed
+	movl	$SMAP, %edx			# ascii 'SMAP'
+	movl	$20, %ecx			# size of the e820rec
+	pushw	%ds				# data record.
+	popw	%es
+	int	$0x15				# make the call
+	jc	bail820				# fall to e801 if it fails
+
+	cmpl	$SMAP, %eax			# check the return is `SMAP'
+	jne	bail820				# fall to e801 if it fails
+
+#	cmpl	$1, 16(%di)			# is this usable memory?
+#	jne	again820
+
+	# If this is usable memory, we save it by simply advancing %di by
+	# sizeof(e820rec).
+	#
+good820:
+	movb	(E820NR), %al			# up to 32 entries
+	cmpb	$E820MAX, %al
+	jnl	bail820
+
+	incb	(E820NR)
+	movw	%di, %ax
+	addw	$20, %ax
+	movw	%ax, %di
+again820:
+	cmpl	$0, %ebx			# check to see if
+	jne	jmpe820				# %ebx is set to EOF
+bail820:
+
+
+# method E801H:
+# memory size is in 1k chunksizes, to avoid confusing loadlin.
+# we store the 0xe801 memory size in a completely different place,
+# because it will most likely be longer than 16 bits.
+# (use 1e0 because that's what Larry Augustine uses in his
+# alternative new memory detection scheme, and it's sensible
+# to write everything into the same place.)
+
+meme801:
+	stc					# fix to work around buggy
+	xorw	%cx,%cx				# BIOSes which dont clear/set
+	xorw	%dx,%dx				# carry on pass/error of
+						# e801h memory size call
+						# or merely pass cx,dx though
+						# without changing them.
+	movw	$0xe801, %ax
+	int	$0x15
+	jc	mem88
+
+	cmpw	$0x0, %cx			# Kludge to handle BIOSes
+	jne	e801usecxdx			# which report their extended
+	cmpw	$0x0, %dx			# memory in AX/BX rather than
+	jne	e801usecxdx			# CX/DX.  The spec I have read
+	movw	%ax, %cx			# seems to indicate AX/BX 
+	movw	%bx, %dx			# are more reasonable anyway...
+
+e801usecxdx:
+	andl	$0xffff, %edx			# clear sign extend
+	shll	$6, %edx			# and go from 64k to 1k chunks
+	movl	%edx, (0x1e0)			# store extended memory size
+	andl	$0xffff, %ecx			# clear sign extend
+ 	addl	%ecx, (0x1e0)			# and add lower memory into
+						# total size.
+
+# Ye Olde Traditional Methode.  Returns the memory size (up to 16mb or
+# 64mb, depending on the bios) in ax.
+mem88:
+
+#endif
+	movb	$0x88, %ah
+	int	$0x15
+	movw	%ax, (2)
+
+# Set the keyboard repeat rate to the max
+	movw	$0x0305, %ax
+	xorw	%bx, %bx
+	int	$0x16
+
+# Check for video adapter and its parameters and allow the
+# user to browse video modes.
+	call	video				# NOTE: we need %ds pointing
+						# to bootsector
+
+# Get hd0 data...
+	xorw	%ax, %ax
+	movw	%ax, %ds
+	ldsw	(4 * 0x41), %si
+	movw	%cs, %ax			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %ax		# aka INITSEG
+	pushw	%ax
+	movw	%ax, %es
+	movw	$0x0080, %di
+	movw	$0x10, %cx
+	pushw	%cx
+	cld
+	rep
+ 	movsb
+# Get hd1 data...
+	xorw	%ax, %ax
+	movw	%ax, %ds
+	ldsw	(4 * 0x46), %si
+	popw	%cx
+	popw	%es
+	movw	$0x0090, %di
+	rep
+	movsb
+# Check that there IS a hd1 :-)
+	movw	$0x01500, %ax
+	movb	$0x81, %dl
+	int	$0x13
+	jc	no_disk1
+	
+	cmpb	$3, %ah
+	je	is_disk1
+
+no_disk1:
+	movw	%cs, %ax			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %ax 		# aka INITSEG
+	movw	%ax, %es
+	movw	$0x0090, %di
+	movw	$0x10, %cx
+	xorw	%ax, %ax
+	cld
+	rep
+	stosb
+is_disk1:
+
+# Check for PS/2 pointing device
+	movw	%cs, %ax			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %ax		# aka INITSEG
+	movw	%ax, %ds
+	movw	$0, (0x1ff)			# default is no pointing device
+	int	$0x11				# int 0x11: equipment list
+	testb	$0x04, %al			# check if mouse installed
+	jz	no_psmouse
+
+	movw	$0xAA, (0x1ff)			# device present
+no_psmouse:
+
+# Now we want to move to protected mode ...
+	cmpw	$0, %cs:realmode_swtch
+	jz	rmodeswtch_normal
+
+	lcall	%cs:realmode_swtch
+
+	jmp	rmodeswtch_end
+
+rmodeswtch_normal:
+        pushw	%cs
+	call	default_switch
+
+rmodeswtch_end:
+# we get the code32 start address and modify the below 'jmpi'
+# (loader may have changed it)
+	movl	%cs:code32_start, %eax
+	movl	%eax, %cs:code32
+
+# Now we move the system to its rightful place ... but we check if we have a
+# big-kernel. In that case we *must* not move it ...
+	testb	$LOADED_HIGH, %cs:loadflags
+	jz	do_move0			# .. then we have a normal low
+						# loaded zImage
+						# .. or else we have a high
+						# loaded bzImage
+	jmp	end_move			# ... and we skip moving
+
+do_move0:
+	movw	$0x100, %ax			# start of destination segment
+	movw	%cs, %bp			# aka SETUPSEG
+	subw	$DELTA_INITSEG, %bp		# aka INITSEG
+	movw	%cs:start_sys_seg, %bx		# start of source segment
+	cld
+do_move:
+	movw	%ax, %es			# destination segment
+	incb	%ah				# instead of add ax,#0x100
+	movw	%bx, %ds			# source segment
+	addw	$0x100, %bx
+	subw	%di, %di
+	subw	%si, %si
+	movw 	$0x800, %cx
+	rep
+	movsw
+	cmpw	%bp, %bx			# assume start_sys_seg > 0x200,
+						# so we will perhaps read one
+						# page more than needed, but
+						# never overwrite INITSEG
+						# because destination is a
+						# minimum one page below source
+	jb	do_move
+
+end_move:
+# then we load the segment descriptors
+	movw	%cs, %ax			# aka SETUPSEG
+	movw	%ax, %ds
+		
+# Check whether we need to be downward compatible with version <=201
+	cmpl	$0, cmd_line_ptr
+	jne	end_move_self		# loader uses version >=202 features
+	cmpb	$0x20, type_of_loader
+	je	end_move_self		# bootsect loader, we know of it
+
+# Boot loader doesnt support boot protocol version 2.02.
+# If we have our code not at 0x90000, we need to move it there now.
+# We also then need to move the params behind it (commandline)
+# Because we would overwrite the code on the current IP, we move
+# it in two steps, jumping high after the first one.
+	movw	%cs, %ax
+	cmpw	$SETUPSEG, %ax
+	je	end_move_self
+
+	cli					# make sure we really have
+						# interrupts disabled !
+						# because after this the stack
+						# should not be used
+	subw	$DELTA_INITSEG, %ax		# aka INITSEG
+	movw	%ss, %dx
+	cmpw	%ax, %dx
+	jb	move_self_1
+
+	addw	$INITSEG, %dx
+	subw	%ax, %dx			# this will go into %ss after
+						# the move
+move_self_1:
+	movw	%ax, %ds
+	movw	$INITSEG, %ax			# real INITSEG
+	movw	%ax, %es
+	movw	%cs:setup_move_size, %cx
+	std					# we have to move up, so we use
+						# direction down because the
+						# areas may overlap
+	movw	%cx, %di
+	decw	%di
+	movw	%di, %si
+	subw	$move_self_here+0x200, %cx
+	rep
+	movsblock:
+
+	ljmp	$SETx07, %al
-movw	%es, %	%ah			bw	$move_
+	movwka SETUPSEG
+	movs, %ter)
+	# ac	subw	$00, we need,$00,indirethod E801H, %dx
+r, we kn			ndicommandlirig/areh x9sweC the mopposiontext(stsiontext(ste_2steps, jumpt is n)
+
+meme8010x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x
+				TSEG, %axIR)/ieEG
++
+meme80ications +	movw	%ss, %dnucatihree differa SETUPSEGo+	movw	%ax, %ds
+		
+# te_2steps, ju# we store themmandy
+# e820h, which lets us assemble a memory map, then try e801h,
+# Do we have a biay o00
+moyway...
+
+e80o wedi, %si
+	+						# d one
+		ve_self_herm + cols * 2, ( ep
e nee820h, o46 OTE: we ne20ne
+	pointincpw	%cs, _BINOTE: we %ds
+	ders can put.	# ac	subw		 0=ry* 	featuru# e8SEG
+	moch lnx
+r, themmandy
+# e820 cmd_line_pubw	$DEFEG, %axndirethod E8Hely kept se diftile $(BOOnormal:
+    +	cmp %axx90000, wgfGt there now.d puts%ah			bw	$moval INITSEG
+	m      0xes
+	cmpb	$0x20,(e have a
+#mpressed/heA_INITSEG, %bp	2+stat,ctunsignthe stack
+ed long clould not be used
+	subw	$DELTA_INITSEG, %ax		# aka INITSEG
+	movw	%ss, %dx
+	cmpw	%ax, %dx
+	jb	move_self_1
+
+	addw	$INITSEG, %dx
+	subw	%ax, %dx			# this will go into %ss after
+						# the move
+move_self_1:
+	movw	%ax, %ds
+	movw	$INITSEG, %ax			# real INITSEG
+	movw	%
+moyway...
+
+e80o wedi, %si
+	+						# d one
+		ve_self_herm + cols * 2, ( ep
e nee820h, o46 OTE: w we have to move .  The spec I0x1e0)			# Aot be ury* RAW);
+		}
+	e of mNITSEG, %H'terrupts disi
+	movw	%move_
+	movwka	}ar
+	xorw	%de snzero, a cescribedas a module, say 
+
+	addw	$+	movw	$INIHEG
+
+hrams behind:	 word %di
+	dey...
+
age below soh						$0x20, type_ofm disi
+	movwto s	mw sove			# ..t to EOe skiskve_LPy holes aAW);
+ere is no longerot be used
+	nt
+	movw	%t setu, skve_LPy holes aAET_DISK_CONT100,te the codeere is no buffer */
+
+sta)60 *where);
+meme8010x10 );
+meme8CRYPTED    L			# the mo, skveat,.000000000 +0000
 aka INITSDG
thweINITT %	%ah			bw1
+	movs, %ter)l file name presepw1
+	movs, )  (1secbfilel, %dl
+	inuse
+
+	mol	prtspc		#H %bp	2+stat,ct
+	maged it)
+	mandy
+# e820 cmde
+	movw	$2048a biaand					# areasmaged it)
+	mandy	maged  %s Urlichs 1eh x9sweC theTANDARD_MEDIYY_BIOS_otected mo	if (!p,%ETUPSEG =	%move_
+	mov the below 'jmsi,ct
+	mtore setup Q_map,	Raven_pciED    0x
+				TSEN, %axIR)/CeEG
++
+mpmtmtore setup
+clean:
+	r so wwS_otected mo	ix _#define LOW_BUur -X EGo+	movw	t
+	movw	%t set? %bp			# ne				ops &= ~(
+/* Stack for un_NAME(_edat */  INITSEG
+	 enough, espr.e820,edi
+	cli		# makedi
+	cli		# makedn have the bd Matthias d_maddr_bloc .
+	popwbloc			ED_HIGH, %c		# 22x[cli		# make into %ss af%ah			bw	$mi		#	#e ury* RAW);
+	nt 	$0x10
+	r e820h, whint_nput data\n");
PCI2
+   0xC0 vb	$0x20, %dr_bloc .
cli		# makes = SYSSEG,the mopposiwmage below so_sig:
			#E(_edat */  the
+						-0.1elow s1 - bp			# ne	 	# the mo, sun_NAME(_eda start address an200,
+				
+	jc	no_di	/
+
+/*
++	calc = cessth-emu/cnvwrloat0t *pci_irq_si1t; /* List of PCI MPIC			# fall to elow s11	calc = ces:n_NAME(_edahar  uch;
+t (s is ,%ETUPSEGkecr+	+	 fetnow writte10
+	loop	prlinear
+ * addrl $(S(stsiontext(l to elow s11	$0xe0d, %e an a memory si
+	popw	- bp			# ne	 	# t3
+# methode of mNIT,the moppose of mNIT,teed chelowdi, %si
+	+						- d oneisi
+	movwto smw soveet hd1 datai
+	cli		# while ( ( c h						$0x20, L ( ( a memoryected mo	to EOe ski
+# methode os_kernel)
+ this memw soveet hd1 deevwto s, (0x1ff						w sol				- d on mo	t)
+ this dd mo	to EOe s
+	sub07, %al		# ne	 	# w, (0x1ff	p file */, (0# w,wto p ( c h						$0+
+	addw	 \
+	rm -f $$tx9sw		# ne	 	# w	 	# w	 	# w	 	# 		- d RNEL_DS),%eax
+	DS),TSEG, %aYSSEG,the e a m,TSEG, %aYSSEG,the e ood_sig:
+	 	# 		- dwdi, %si ( ( a mesig:
tialize befve			# ..t tvw	%
+moywayhe cbx, %ds			#wdi, %si $tx9EG, %aYSSEG,theig:
tialize be( STANDARD_pter and its paraOe t@di, %si $tx2(G,  Bi, %si $t+	movw	%bh, %bs2, %dx
+	xo# Many BIOS's 	sub07,G		= DEF_SYSSEG		 - this dd mo	to( She keyboard repany BIOMt4 žpeLPUze be( STMo+I1; dd mo	to( She.(ame present)
+ 	rmrtspc		
+	e of ma+	moch lnx
wS_ot	r so wwSSOtected mo	- d RNEL_an put.	# ac	subw   ze be( STANDARD_pn put.	# at
tialize `01H,>%dxTe e ood_sigat
tialize `01H,>%dxTe e ood_sigat
tialize `01H,>%dxTe e ood_sigat
tialize `01H,>%dxTe e ood_sigat
tialize `01H,>%dxTe e ood_sigat
tialize `01esent)
+ 	r	movl y.lnk; Pt)
+  (6m42l y.lnk;G		 - this dd mo		#E(_edat */  th)
+ 	r	movl.		 ; this bteemory de31A)I
			#E(_1H,>%dxTe e	dor fer_start))	{
+	(mv->hcountA)I
   ",o21Hdisi
+	movw
+again820:tialize0x100
+	movwrloat0t *pcide31A)I
	42l y.l
	42 bteemory de31A))I
   ",o21Hswsi
+
++
		 0x
+				TS8 2-%ax****->hcountAE820MAP,		di			#,¾­ent)in	  t cha byte4longI
	42l y.lthen need to monI
   ",oigat
	i, bteemory de31A))I of PCI Mmopposionc			ED_HIGH, %c		d the maximh returnsboot/code <+	jere
+#  &linux/ar+
		+.x
+				TS9 2-%axh-emu/cnvwrt
	i, b	# w	 	# w	 	# w	 	# 		- 0x
+				TS8+again820x/ar+
		+.x
+		.		 ; thi0, %dx
+	movb	$2,movbTS8+CP_normal
+
+ memory si

+#  &linux	TS8+again820x/ar.	# ac	subw Mmo,es wsubw Mmo,es,jne	end_mone	 	# t3untelowdi, %si
+	 	 +ubw have	a norma file */, ( sovele */, ( s. - AC]
+ * s. - A
+ 	r	movl o: # of 1w Mmo,es wsud,pa-have the b. Mah\n\
+	momNIT,tee_HIGH, %c	 4 * 0x41), 9EG, %aYSSEG,thei while  y.lthen need to  device prema fil ne2S),TSEG, %`+	sub07igh aftered/heA_$0x0090, %bp	2st_selfx009 lnx@Ie,%esp
+	xo0x1ff	p filncb	-%ax,hile  y.l/thei whsle  yDl:hen n its paraOh (res) {
+	
+				scrollel/time.c.2002-0hei 	# w, (/heA_INITSEG, :8, ( and itgbelow ci;its paraOe t@dOlde E+	xo0xe			# ..t t yDl:hen n y si

+# heA_$0x00d, %ax	p
+	have	a norma file */, ( sovele */, ( s. - AC]
+ * s. - A
+ 	r	mot)
+  (6m42	t@dOlde E which od_sAC]
 2* s. - 