diff -u --recursive --new-file v2.4.5/linux/CREDITS linux/CREDITS
--- v2.4.5/linux/CREDITS	Tue May 22 19:54:04 2001
+++ linux/CREDITS	Thu Jun 28 14:58:05 2001
@@ -454,6 +454,11 @@
 E: xavyer@ix.netcom.com
 D: USB Serial Empeg Empeg-car Mark I/II Driver
 
+N: Matthias Bruestle
+E: m@mbsks.franken.de
+D: REINER SCT cyberJack pinpad/e-com USB chipcard reader driver
+S: Germany
+
 N: Ray Burr
 E: ryb@nightmare.com
 D: Original author of Amiga FFS filesystem
@@ -1136,13 +1141,11 @@
 S: USA
 
 N: Benjamin Herrenschmidt
-E: bh40@calva.net
+E: benh@kernel.crashing.org
 E: benh@mipsys.com
-D: PowerMac booter (BootX)
-D: Additional PowerBook support
-D: Apple "Core99" machines support (ibook,g4,...)
-S: 22, rue des Marguettes
-S: 75012 Paris
+D: Various parts of PPC & PowerMac
+S: 122, boulevard Baille
+S: 13005 Marseille
 S: France
 
 N: Sebastian Hetze
@@ -1356,13 +1359,15 @@
 E: davej@suse.de
 W: http://www.suse.de/~davej
 D: Moved PCI bridge tuning to userspace (Powertweak).
-D: Centaur/IDT Winchip/Winchip 2 tweaks.
+D: Various x86 (& clones) setup code hacking.
 D: AFFS fixes for 2.3.x
-D: Misc clean ups and other random hacking.
-S: 28, Laura Street,
-S: Treforest, Pontypridd,
-S: Mid Glamorgan, CF37 1NW,
-S: Wales, United Kingdom
+D: Various Janitorial hacks. (kernel-janitor.sourceforge.net)
+S: c/o SuSE Linux UK Ltd
+S: The Kinetic Centre
+S: Theobald Street
+S: Borehamwood
+S: Herts, WD6 4PJ
+S: United Kingdom
 
 N: Ani Joshi
 E: ajoshi@shell.unixbox.com
@@ -1518,6 +1523,17 @@
 S: L3R 8B2
 S: Canada
 
+N: Maxim Krasnyansky
+E: maxk@qualcomm.com
+W: http://vtun.sf.net
+W: http://bluez.sf.net
+D: Author of the Universal TUN/TAP driver
+D: Author of the Linux Bluetooth Subsystem (BlueZ)
+D: Various other kernel patches, cleanups and fixes
+S: 2213 La Terrace Circle
+S: San Jose, CA 95123
+S: USA
+
 N: Andreas S. Krebs
 E: akrebs@altavista.net
 D: CYPRESS CY82C693 chipset IDE, Digital's PC-Alpha 164SX boards
@@ -1742,6 +1758,8 @@
 
 N: Paul Mackerras
 E: paulus@samba.org
+D: PPP driver
+D: Linux for PowerPC
 D: Linux port for PCI Power Macintosh
 
 N: Pat Mackinlay
@@ -1975,6 +1993,13 @@
 S: Richardson, Texas 75081
 S: USA
 
+N: Patrick Mochel
+E: mochel@transmeta.com
+D: PCI Power Management, ACPI work
+S: 3940 Freedom Circle
+S: Santa Clara, CA 95054
+S: USA
+
 N: Eberhard Moenkeberg
 E: emoenke@gwdg.de
 D: CDROM driver "sbpcd" (Matsushita/Panasonic/Soundblaster)
@@ -2697,9 +2722,7 @@
 N: Marcelo W. Tosatti
 E: marcelo@conectiva.com.br
 W: http://bazar.conectiva.com.br/~marcelo/
-D: Miscellaneous kernel hacker
-D: Cyclom 2X driver, drbd hacker
-D: linuxconf apache & proftpd module maintainer
+D: Miscellaneous kernel hacker (mostly VM/MM work)
 S: Conectiva S.A.
 S: R. Tocantins, 89 - Cristo Rei
 S: 80050-430 - Curitiba - Paraná
@@ -2883,6 +2906,14 @@
 S: X/OS Experts in Open Systems BV
 S: Kruislaan 419
 S: 1098 VA Amsterdam 
+S: The Netherlands
+
+N: Jeroen Vreeken
+E: pe1rxq@amsat.org
+W: http://www.chello.nl/~j.vreeken/
+D: SE401 usb webcam driver
+S: Maastrichterweg 63
+S: 5554 GG Valkenswaard
 S: The Netherlands
 
 N: Peter Shaobo Wang
diff -u --recursive --new-file v2.4.5/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.5/linux/Documentation/Changes	Sat May 19 17:43:05 2001
+++ linux/Documentation/Changes	Wed Jun 27 13:37:05 2001
@@ -320,7 +320,7 @@
 
 LVM toolset
 -----------
-o  <http://linux.msede.com/lvm/>
+o  <http://www.sistina.com/lvm/>
 
 Pcmcia-cs
 ---------
@@ -347,7 +347,7 @@
 
 PPP
 ---
-o  <ftp://ftp.samba.org/ppp/ppp-2.4.0.tar.gz>
+o  <ftp://ftp.samba.org/pub/ppp/ppp-2.4.0.tar.gz>
 
 Isdn4k-utils
 ------------
diff -u --recursive --new-file v2.4.5/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.5/linux/Documentation/Configure.help	Thu May 24 15:03:06 2001
+++ linux/Documentation/Configure.help	Mon Jul  2 14:07:55 2001
@@ -7537,6 +7537,40 @@
   configure your card and that /etc/pcmcia/wireless.opts works :
     http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
 
+Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards
+CONFIG_AIRO
+  This is the standard Linux driver to support Cisco/Aironet ISA
+  and PCI 802.11 wireless cards.
+  It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
+  - with or without encryption) as well as card before the Cisco
+  aquisition (Aironet 4500, Aironet 4800, Aironet 4800B).
+
+  This driver support both the standard Linux Wireless Extensions
+  and Cisco proprietary API, so both the Linux Wireless Tools and the
+  Cisco Linux utilities can be used to configure the card.
+
+  The driver can be compiled as a module and will be named "airo.o".
+
+Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards
+CONFIG_AIRO_CS
+  This is the standard Linux driver to support Cisco/Aironet PCMCIA
+  802.11 wireless cards. This driver is the same as the Aironet
+  driver part of the Linux Pcmcia package.
+  It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X
+  - with or without encryption) as well as card before the Cisco
+  aquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also
+  supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom
+  802.11b cards.
+
+  This driver support both the standard Linux Wireless Extensions
+  and Cisco proprietary API, so both the Linux Wireless Tools and the
+  Cisco Linux utilities can be used to configure the card.
+
+  To use your PC-cards, you will need supporting software from David
+  Hinds' pcmcia-cs package (see the file Documentation/Changes for
+  location). You also want to check out the PCMCIA-HOWTO, available
+  from http://www.linuxdoc.org/docs.html#howto .
+
 Aviator/Raytheon 2.4MHz wireless support
 CONFIG_PCMCIA_RAYCS
   Say Y here if you intend to attach an Aviator/Raytheon PCMCIA
@@ -9423,6 +9457,15 @@
   module, say M here and read Documentation/modules.txt as well as
   Documentation/networking/net-modules.txt.
 
+New Tulip bus configuration (EXPERIMENTAL)
+CONFIG_TULIP_MWI
+  This configures your Tulip card specifically for the card and
+  system cache line size type you are using.
+
+  This is experimental code, not yet tested on many boards.
+
+  If unsure, say N.
+
 Digi Intl. RightSwitch support
 CONFIG_DGRS
   This is support for the Digi International RightSwitch series of
@@ -10182,91 +10225,150 @@
 Memory Technology Device (MTD) support
 CONFIG_MTD
   Memory Technology Devices are flash, RAM and similar chips, often
-  used for solid state file systems on embedded devices. This option
+  used for solid state filesystems on embedded devices. This option
   will provide the generic support for MTD drivers to register
   themselves with the kernel and for potential users of MTD devices
   to enumerate the devices which are present and obtain a handle on
   them. It will also allow you to select individual drivers for 
-  particular hardware and users of MTD device. If unsure, say N.
+  particular hardware and users of MTD devices. If unsure, say N.
 
 MTD debugging support
 CONFIG_MTD_DEBUG
   This turns on low-level debugging for the entire MTD sub-system.
+  Normally, you should say 'N'.
+
+MTD partitioning support
+CONFIG_MTD_PARTITIONS
+  If you have a device which needs to divide its flash chip(s) up
+  into multiple 'partitions', each of which appears to the user as
+  a separate MTD device, you require this option to be enabled. If
+  unsure, say 'Y'.
+
+  Note, however, that you don't need this option for the DiskOnChip
+  devices. Partitioning on NFTL 'devices' is a different - that's the
+  'normal' form of partitioning used on a block device.
+
+RedBoot partition table parsing
+CONFIG_MTD_REDBOOT_PARTS
+  RedBoot is a ROM monitor and bootloader which deals with multiple
+  'images' in flash devices by putting a table in the last erase
+  block of the device, similar to a partition table, which gives
+  the offsets, lengths and names of all the images stored in the 
+  flash. 
+
+  If you need code which can detect and parse this table, and register
+  MTD 'partitions' corresponding to each image in the table, enable
+  this option. 
+
+  You will still need the parsing functions to be called by the driver
+  for your particular device. It won't happen automatically. The 
+  SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for 
+  example.
+
+Compaq bootldr partition table parsing
+CONFIG_MTD_BOOTLDR_PARTS
+  The Compaq bootldr deals with multiple 'images' in flash devices
+  by putting a table in one of the first erase blocks of the device,
+  similar to a partition table, which gives the offsets, lengths and
+  names of all the images stored in the flash. 
+
+  If you need code which can detect and parse this table, and register
+  MTD 'partitions' corresponding to each image in the table, enable
+  this option. 
+
+  You will still need the parsing functions to be called by the driver
+  for your particular device. It won't happen automatically. The 
+  SA1100 map driver (CONFIG_MTD_SA1100) has an option for this, for 
+  example.
+
+ARM Firmware Suite flash layout / partition parsing
+CONFIG_MTD_AFS_PARTS
+  The ARM Firmware Suite allows the user to divide flash devices into
+  multiple 'images'. Each such image has a header containing its name
+  and offset/size etc. 
+
+  If you need code which can detect and parse these tables, and register
+  MTD 'partitions' corresponding to each image detected, enable
+  this option. 
+
+  You will still need the parsing functions to be called by the driver
+  for your particular device. It won't happen automatically. The 
+  'armflash' map driver (CONFIG_MTD_ARMFLASH) does this, for example.
 
 MTD debugging verbosity
 CONFIG_MTD_DEBUG_VERBOSE
   Determines the verbosity level of the MTD debugging messages.
 
-M-Systems Disk-On-Chip 1000 support
-CONFIG_MTD_DOC1000
-  This provides an MTD device driver for the M-Systems DiskOnChip
-  1000 devices, which are obsolete so you probably want to say 'N'.
 
-M-Systems Disk-On-Chip 2000 and Millennium support
-CONFIG_MTD_DOC2000
-  This provides an MTD device driver for the M-Systems DiskOnChip
-  2000 and Millennium devices. Originally designed for the DiskOnChip
-  2000, it also now includes support for the DiskOnChip Millennium.
-  If you have problems with this driver and the DiskOnChip Millennium,
-  you may wish to try the alternative Millennium driver below. To use
-  the alternative driver, you will need to undefine DOC_SINGLE_DRIVER
-  in the drivers/mtd/docprobe.c source code.
+Direct chardevice access to MTD devices
+CONFIG_MTD_CHAR
+  This provides a character device for each MTD device present in
+  the system, allowing the user to read and write directly to the
+  memory chips, and also use ioctl() to obtain information about
+  the device, or to erase parts of it.
 
-  If you use this device, you probably also want to enable the NFTL
-  'NAND Flash Translation Layer' option below, which is used to emulate
-  a block device by using a kind of filesystem on the flash chips.
+Caching block device access to MTD devices
+CONFIG_MTD_BLOCK
+  Although most flash chips have an erase size too large to be useful
+  as block devices, it is possible to use MTD devices which are based
+  on RAM chips in this manner. This block device is a user of MTD devices
+  performing that function.
+
+  At the moment, it is also required for the Journalling Flash File
+  System(s) to obtain a handle on the MTD device when it's mounted
+  (although JFFS and JFFS2 don't actually use any of the functionality
+  of the mtdblock device).
 
-Alternative Disk-On-Chip Millennium support
-CONFIG_MTD_DOC2001
-  This provides an alternative MTD device driver for the M-Systems
-  DiskOnChip Millennium devices. Use this if you have problems with
-  the combined DiskOnChip 2000 and Millennium driver above. To get
-  the DiskOnChip probe code to load and use this driver instead of
-  the other one, you will need to undefine DOC_SINGLE_DRIVER near
-  the beginning of drivers/mtd/docprobe.c
+  Later, it may be extended to perform read/erase/modify/write cycles
+  on flash chips to emulate a smaller block size. Needless to say,
+  this is very unsafe, but could be useful for filesystems which are
+  almost never written to.
 
-  If you use this device, you probably also want to enable the NFTL
-  'NAND Flash Translation Layer' option below, which is used to emulate
-  a block device by using a kind of filesystem on the flash chips.
+  You do not need this option for use with the DiskOnChip devices. For
+  those, enable NFTL support (CONFIG_NFTL) instead.
 
-Ramix PMC551 PCI Mezzanine ram card support
-CONFIG_MTD_PMC551
-  This provides a MTD device driver for the Ramix PMC551 RAM PCI card
-  from Ramix Inc. (http://www.ramix.com/products/memory/pmc551.html).
-  These devices come in memory configurations from 32M - 1G.  If you
-  have one, you probably want to enable this.
+Readonly block device access to MTD devices
+CONFIG_MTD_BLOCK_RO
+  This allows you to mount read-only filesystems (such as cramfs) from
+  an MTD device, without the overhead (and danger) of the caching 
+  driver. 
 
-  If this driver is compiled as a module you get the ability to select the
-  size of the aperture window pointing into the devices memory.  What this
-  means is that if you have a 1G card, normally the kernel will use a 1G
-  memory map as it's view of the device.  As a module, you can select a
-  1M window into the memory and the driver will "slide" the window around
-  the PMC551's memory.  This was particularly useful on the 2.2 kernels
-  on PPC architectures as there was limited kernel space to deal with.
+  You do not need this option for use with the DiskOnChip devices. For
+  those, enable NFTL support (CONFIG_NFTL) instead.
 
-Use extra onboard system memory as MTD device
-CONFIG_MTD_SLRAM
-  If your CPU cannot cache all of the physical memory in your machine,
-  you can still use it for storage or swap by using this driver to
-  present it to the system as a Memory Technology Device.
+FTL (Flash Translation Layer) support
+CONFIG_FTL
+  This provides support for the original Flash Translation Layer which
+  is part of the PCMCIA specification. It uses a kind of pseudo-
+  filesystem on a flash device to emulate a block device with 512-byte
+  sectors, on top of which you put a 'normal' filesystem.
 
-PMC551 256M DRAM Bugfix
-CONFIG_MTD_PMC551_BUGFIX
-  Some of Ramix's PMC551 boards with 256M configurations have invalid
-  column and row mux values. This option will fix them, but will break
-  other memory configurations.  If unsure say N.
+  You may find that the algorithms used in this code are patented
+  unless you live in the Free World where software patents aren't
+  legal - in the USA you are only permitted to use this on PCMCIA
+  hardware, although under the terms of the GPL you're obviously
+  permitted to copy, modify and distribute the code as you wish. Just
+  not use it.
 
-PMC551 Debugging
-CONFIG_MTD_PMC551_DEBUG
-  This option makes the PMC551 more verbose during it's operation and is
-  only really useful if you are developing on this driver or suspect a
-  possible hardware or driver bug.  If unsure say N.
+NFTL (NAND Flash Translation Layer) support
+CONFIG_NFTL
+  This provides support for the NAND Flash Translation Layer which is
+  used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
+  filesystem on a flash device to emulate a block device with 512-byte
+  sectors, on top of which you put a 'normal' filesystem.
 
-Debugging RAM test driver
-CONFIG_MTD_MTDRAM
-  This enables a test MTD device driver which uses vmalloc() to
-  provide storage. You probably want to say 'N' unless you're
-  testing stuff.
+  You may find that the algorithms used in this code are patented
+  unless you live in the Free World where software patents aren't
+  legal - in the USA you are only permitted to use this on DiskOnChip
+  hardware, although under the terms of the GPL you're obviously
+  permitted to copy, modify and distribute the code as you wish. Just
+  not use it.
+
+Write support for NFTL (EXPERIMENTAL)
+CONFIG_NFTL_RW
+  If you're lucky, this will actually work. Don't whinge if it doesn't.
+  Send mail to the MTD mailing list <linux-mtd@lists.infradead.org> if
+  you want to help to make it more reliable.
 
 Common Flash Interface (CFI) support
 CONFIG_MTD_CFI
@@ -10277,12 +10379,135 @@
   option. Visit (http://www.amd.com/products/nvd/overview/cfi.html)
   for more information on CFI.
 
-CFI support for Intel/Sharp Extended Command Set chips
+CFI Advanced configuration options
+CONFIG_MTD_CFI_ADV_OPTIONS
+  If you need to specify a specific endianness for access to flash
+  chips, or if you wish to reduce the size of the kernel by including
+  support for only specific arrangements of flash chips, say 'Y'. This
+  option does not directly affect the code, but will enable other 
+  configuration options which allow you to do so.
+
+  If unsure, say 'N'.
+
+Specific CFI Flash geometry selection
+CONFIG_MTD_CFI_GEOMETRY
+  This option does not affect the code directly, but will enable 
+  some other configuration options which would allow you to reduce
+  the size of the kernel by including support for only certain 
+  arrangements of CFI chips. If unsure, say 'N' and all options 
+  which are supported by the current code will be enabled.
+
+Support 8-bit buswidth
+CONFIG_MTD_CFI_B1
+  If you wish to support CFI devices on a physical bus which is
+  8 bits wide, say 'Y'.
+
+Support 16-bit buswidth
+CONFIG_MTD_CFI_B2
+  If you wish to support CFI devices on a physical bus which is
+  16 bits wide, say 'Y'.
+
+Support 32-bit buswidth
+CONFIG_MTD_CFI_B4
+  If you wish to support CFI devices on a physical bus which is
+  32 bits wide, say 'Y'.
+
+Support 1-chip flash interleave
+CONFIG_MTD_CFI_I1
+  If your flash chips are not interleaved - i.e. you only have one
+  flash chip addressed by each bus cycle, then say 'Y'.
+
+Support 2-chip flash interleave
+CONFIG_MTD_CFI_I2
+  If your flash chips are interleaved in pairs - i.e. you have two
+  flash chips addressed by each bus cycle, then say 'Y'.
+
+Support 4-chip flash interleave
+CONFIG_MTD_CFI_I4
+  If your flash chips are interleaved in fours - i.e. you have four
+  flash chips addressed by each bus cycle, then say 'Y'.
+
+Flash cmd/query data swapping
+CONFIG_MTD_CFI_NOSWAP
+  This option defines the way in which the CPU attempts to arrange
+  data bits when writing the 'magic' commands to the chips. Saying
+  'NO', which is the default when CONFIG_MTD_CFI_ADV_OPTIONS isn't
+  enabled, means that the CPU will not do any swapping; the chips
+  are expected to be wired to the CPU in 'host-endian' form. 
+  Specific arrangements are possible with the BIG_ENDIAN_BYTE and
+  LITTLE_ENDIAN_BYTE, if the bytes are reversed. 
+
+  If you have a LART, on which the data (and address) lines were
+  connected in a fashion which ensured that the nets were as short
+  as possible, resulting in a bit-shuffling which seems utterly
+  random to the untrained eye, you need the LART_ENDIAN_BYTE option.
+
+  Yes, there really exists something sicker than PDP-endian :)
+
+CFI support for Intel/Sharp Extended Commands
 CONFIG_MTD_CFI_INTELEXT
   The Common Flash Interface defines a number of different command
   sets which a CFI-compliant chip may claim to implement. This code
   provides support for one of those command sets, used on Intel
-  Strataflash and other parts.
+  StrataFlash and other parts.
+
+CFI support for AMD/Fujitsu Standard Commands
+CONFIG_MTD_CFI_AMDSTD
+  The Common Flash Interface defines a number of different command
+  sets which a CFI-compliant chip may claim to implement. This code
+  provides support for one of those command sets, used on chips 
+  chips including the AMD Am29LV320.
+
+CFI support for Intel/Sharp Standard Commands
+CONFIG_MTD_CFI_INTELSTD
+  The Common Flash Interface defines a number of different command
+  sets which a CFI-compliant chip may claim to implement. This code
+  provides support for one of those command sets.
+
+pre-CFI Sharp chip support
+CONFIG_MTD_SHARP
+  This option enables support for flash chips using Sharp-compatible
+  commands, including some which are not CFI-compatible and hence 
+  cannot be used with the CONFIG_MTD_CFI_INTELxxx options.
+
+AMD compatible flash chip support (non-CFI)
+CONFIG_MTD_AMDSTD
+  This option enables support for flash chips using AMD-compatible
+  commands, including some which are not CFI-compatible and hence 
+  cannot be used with the CONFIG_MTD_CFI_AMDSTD option.
+
+  It also works on AMD compatible chips that do conform to CFI.
+
+Support for RAM chips in bus mapping
+CONFIG_MTD_RAM
+  This option enables basic support for RAM chips accessed through 
+  a bus mapping driver.
+
+Support for ROM chips in bus mapping
+CONFIG_MTD_ROM
+  This option enables basic support for ROM chips accessed through 
+  a bus mapping driver.
+
+CONFIG_MTD_JEDEC
+  Enable older older JEDEC flash interface devices for self programming
+  flash. It is commonly used in older AMD chips. It is only called
+  JEDEC because the JEDEC association (http://www.jedec.org/)
+  distributes the identification codes for the chips. WARNING!!!! This
+  code does not compile and is incomplete as are the specific JEDEC
+  devices drivers.
+
+CFI Flash device mapped on StrongARM SA11x0
+CONFIG_MTD_SA1100
+  This enables access to the flash chips on most platforms based on the
+  SA1100 and SA1110, including the Assabet and the Compaq iPAQ. If you
+  have such a board, say 'Y'.
+
+CONFIG_MTD_SA1100_REDBOOT_PARTITIONS
+  Enabling this option will cause the kernel to look for a RedBoot 
+  FIS (Flash Image System) table in the last erase block of the flash
+  chips detected. If you are using RedBoot on your SA11x0-based board
+  and want Linux to present 'partitions' matching the images which
+  RedBoot has listed, say 'Y'. 
 
 Flash chip mapping in physical memory
 CONFIG_MTD_PHYSMAP
@@ -10295,18 +10520,18 @@
 Physical start location of flash chip mapping
 CONFIG_MTD_PHYSMAP_START
   This is the physical memory location at which the flash chips
-  are mapped on your particular target board. Refer to the 
+  are mapped on your particular target board. Refer to the
   memory map which should hopefully be in the documentation for
   your board.
 
 Physical length of flash chip mapping
 CONFIG_MTD_PHYSMAP_LEN
   This is the total length of the mapping of the flash chips on
-  your particular board. If there is space, or aliases, in the 
+  your particular board. If there is space, or aliases, in the
   physical memory map between the chips, this could be larger
   than the total amount of flash present. Refer to the memory
   map which should hopefully be in the documentation for your
-  board. 
+  board.
 
 CONFIG_MTD_PHYSMAP_BUSWIDTH
   This is the total width of the data bus of the flash devices
@@ -10314,14 +10539,12 @@
   bits, you would set the bus width octect value to 4. This is
   used internally by the CFI drivers.
 
-Flash chip mapping on Mixcom piggyback card
-CONFIG_MTD_MIXMEM
-  This supports the paging arrangement for access to flash chips
-  on the MixCOM piggyback card, allowing the flash chip drivers
-  to get on with their job of driving the flash chips without
-  having to know about the paging. If you have one of these boards,
-  you probably want to enable this mapping driver. More info is at
-  (http://www.itc.hu/).
+Flash chip mapping on Sun Microsystems boardsets
+CONFIG_MTD_SUN_UFLASH
+  This provides a 'mapping' driver which supports the way in 
+  which user-programmable flash chips are connected on various 
+  Sun Microsystems boardsets.  This driver will require CFI support 
+  in the kernel, so if you did not enable CFI previously, do that now.
 
 Flash chip mapping on Nora
 CONFIG_MTD_NORA
@@ -10332,13 +10555,6 @@
   PNC-2000 is the name of Network Camera product from PHOTRON
   Ltd. in Japan. It uses CFI-compliant flash.
 
-Flash chip mapping on Octagon 5066 SBC
-CONFIG_MTD_OCTAGON
-  This provides a 'mapping' driver which supports the way in which
-  the flash chips are connected in the Octagon-5066 Single Board
-  Computer. More information on the board is available at
-  (http://www.octagonsystems.com/Products/5066/5066.html).
-
 Flash chip mapping on RPXlite PPC board
 CONFIG_MTD_RPXLITE
   The RPXLite PowerPC board has CFI-compliant chips mapped in
@@ -10347,6 +10563,89 @@
   to communicate with the chips on the RPXLite board. More at
   (http://www.embeddedplanet.com/rpx_lite_specification_sheet.htm).
 
+Flash chip mapping on AMD SC520 CDP board
+CONFIG_MTD_SC520CDP
+  The SC520 CDP board has two banks of CFI-compliant chips and one
+  Dual-in-line JEDEC chip. This 'mapping' driver supports that
+  arrangement, implementing three MTD devices.
+
+Flash chip mapping on Arcom Control Systems' SBC-MediaGX
+CONFIG_MTD_SBC_MEDIAGX
+  This provides a driver for the on-board flash of Arcom Control
+  Systems' SBC-MediaGX development board. By default the flash
+  is split into 3 partitions which are accessed as separate MTD
+  devices. This board utilizes Intel StrataFlash. More info at
+  (http://www.arcomcontrols.com/products/icp/pc104/processors/).
+
+Flash chip mapping on Arcom Control Systems' ELAN-104NC
+CONFIG_MTD_ELAN_104NC
+  This provides a driver for the on-board flash of the Arcom Control
+  System's ELAN-104NC development board. By default the flash
+  is split into 3 partitions which are accessed as separate MTD
+  devices. This board utilizes Intel StrataFlash. More info at
+  (http://www.arcomcontrols.com/products/icp/pc104/processors/).
+
+Flash chip mapping on Compaq iPAQ/Bitsy
+CONFIG_MTD_BITSY
+  This provides a driver for the on-board flash found in Compaq's
+  iPAQ Palm PC and their research prototype the Itsy. iPAQ info at
+  (http://www5.compaq.com/products/handhelds/pocketpc/) and the
+  Itsy (http://www.research.digital.com/wrl/projects/Itsy/index.html).
+ 
+Flash chip mapping on Compaq iPAQ/Bitsy
+CONFIG_MTD_DC21285
+  This provides a driver for the flash accessed using Intel's
+  21285 bridge used with Intel's StrongARM processors. More info at
+  (http://developer.intel.com/design/bridge/quicklist/dsc-21285.htm).
+
+Flash chip mapping on ITE QED-4N-S01B, Globespan IVR or custom board
+CONFIG_MTD_CSTM_MIPS_IXX
+  This provides a mapping driver for the Integrated Tecnology
+  Express, Inc (ITE) QED-4N-S01B eval board and the Globespan IVR Reference
+  Board. It provides the necessary addressing, length, buswidth, vpp code 
+  and addition setup of the flash device for these boards. In addition,
+  this mapping driver can be used for other boards via setting of the
+  CONFIG_MTD_CSTM_MIPS_IXX_START/LEN/BUSWIDTH parameters.  This mapping
+  will provide one mtd device using one partition.  The start address can
+  be offset from the beginning of flash and the len can be less than the
+  total flash device size to allow a window into the flash.  Both CFI and 
+  JEDEC probes are called.
+
+Physical start location of flash mapping
+CONFIG_MTD_CSTM_MIPS_IXX_START
+  This is the physical memory location that the MTD driver will
+  use for the flash chips on your particular target board. 
+  Refer to the memory map which should hopefully be in the 
+  documentation for your board.
+
+Physical length of flash mapping
+CONFIG_MTD_CSTM_MIPS_IXX_LEN
+  This is the total length that the MTD driver will use for the 
+  flash chips on your particular board.  Refer to the memory
+  map which should hopefully be in the documentation for your
+  board. 
+
+Physical bus width of flash mapping
+CONFIG_MTD_CSTM_MIPS_IXX_BUSWIDTH
+  This is the total bus width of the mapping of the flash chips
+  on your particular board.
+
+Flash chip mapping on Mixcom piggyback card
+CONFIG_MTD_MIXMEM
+  This supports the paging arrangement for access to flash chips
+  on the MixCOM piggyback card, allowing the flash chip drivers
+  to get on with their job of driving the flash chips without
+  having to know about the paging. If you have one of these boards,
+  you probably want to enable this mapping driver. More info is at
+  (http://www.itc.hu/).
+
+Flash chip mapping on Octagon 5066 SBC
+CONFIG_MTD_OCTAGON
+  This provides a 'mapping' driver which supports the way in which
+  the flash chips are connected in the Octagon-5066 Single Board
+  Computer. More information on the board is available at
+  (http://www.octagonsystems.com/Products/5066/5066.html).
+
 Flash chip mapping on Tempustech VMAX SBC301
 CONFIG_MTD_VMAX
   This provides a 'mapping' driver which supports the way in which
@@ -10354,57 +10653,168 @@
   Board Computer. More information on the board is available at
   (http://www.tempustech.com/tt301.htm).
 
-Direct chardevice access to MTD devices
-CONFIG_MTD_CHAR
-  This provides a character device for each MTD device present in
-  the system, allowing the user to read and write directly to the
-  memory chips, and also use ioctl() to obtain information about
-  the device, or to erase parts of it.
+Support for NAND flash devices
+CONFIG_MTD_NAND
+  This enables support for accessing all type of NAND flash
+  devices. 
+
+Support for software ECC algorithm
+CONFIG_MTD_NAND_ECC
+  This enables software-based ECC for use with NAND flash chips. It
+  can detect and correct 1 bit errors per 256 byte blocks. This
+  should be used to increase the reliability of the data stored and
+  read on the device.
+
+Support for verify read after write
+CONFIG_MTD_NAND_VERIFY_WRITE
+  This adds an extra check when data is written to the flash. The
+  NAND flash device internally checks only bits transitioning
+  from 1 to 0. There is a rare possibility that even though the
+  device thinks the write was successful, a bit could have been
+  flipped accidentaly due to device wear, gamma rays, whatever.
+  Enable this if you are really paranoid.
 
-Pseudo-blockdevice access to MTD devices
-CONFIG_MTD_BLOCK
-  Although flash chips have an erase size too large to useful as
-  block devices, it is possible to use MTD devices which are based
-  on RAM chips in this manner. This blockdevice user of MTD devices
-  performs that function. At the moment, it is also required for 
-  the Journalling Flash File System to obtain a handle on the MTD 
-  device when it's mounted - although the JFFS doesn't actually use
-  any of the functions of the mtdblock device.
+Support for the SPIA board
+CONFIG_MTD_NAND_SPIA
+  If you had to ask, you don't have one. Say 'N'.
 
-  Later, it may be extended to perform read/erase/modify/write cycles
-  on flash chips to emulate a smaller block size. Needless to say,
-  this is very unsafe, but could be useful for file systems which are
-  almost never written to.
+M-Systems Disk-On-Chip 1000 support
+CONFIG_MTD_DOC1000
+  This provides an MTD device driver for the M-Systems DiskOnChip
+  1000 devices, which are obsolete so you probably want to say 'N'.
 
-FTL (Flash Translation Layer) support
-CONFIG_FTL
-  This provides support for the original Flash Translation Layer which
-  is part of the PCMCIA specification. It uses a kind of pseudo-
-  file system on a flash device to emulate a block device with 512-byte
-  sectors, on top of which you put a 'normal' file system. You may find
-  that the algorithms used in this code are patented unless you live
-  in the Free World where software patents aren't legal - in the USA
-  you are only permitted to use this on PCMCIA hardware, although 
-  under the terms of the GPL you're obviously permitted to copy,
-  modify and distribute the code as you wish. Just not use it.
+M-Systems Disk-On-Chip 2000 and Millennium support
+CONFIG_MTD_DOC2000
+  This provides an MTD device driver for the M-Systems DiskOnChip
+  2000 and Millennium devices. Originally designed for the DiskOnChip 
+  2000, it also now includes support for the DiskOnChip Millennium. 
+  If you have problems with this driver and the DiskOnChip Millennium,
+  you may wish to try the alternative Millennium driver below. To use
+  the alternative driver, you will need to undefine DOC_SINGLE_DRIVER
+  in the drivers/mtd/devices/docprobe.c source code.
 
-NFTL (NAND Flash Translation Layer) support
-CONFIG_NFTL
-  This provides support for the NAND Flash Translation Layer which is
-  used on M-Systems' DiskOnChip devices. It uses a kind of pseudo-
-  file system on a flash device to emulate a block device with 512-byte
-  sectors, on top of which you put a 'normal' file system. You may find
-  that the algorithms used in this code are patented unless you live
-  in the Free World where software patents aren't legal - in the USA
-  you are only permitted to use this on DiskOnChip hardware, although 
-  under the terms of the GPL you're obviously permitted to copy,
-  modify and distribute the code as you wish. Just not use it.
+  If you use this device, you probably also want to enable the NFTL
+  'NAND Flash Translation Layer' option below, which is used to emulate
+  a block device by using a kind of filesystem on the flash chips.
 
-Write support for NFTL (EXPERIMENTAL)
-CONFIG_NFTL_RW
-  If you're lucky, this will actually work. Don't whine if it doesn't.
-  Contact (dwmw2@infradead.org) if you want to help to make it more
-  reliable.
+Alternative Disk-On-Chip Millennium support
+CONFIG_MTD_DOC2001
+  This provides an alternative MTD device driver for the M-Systems 
+  DiskOnChip Millennium devices. Use this if you have problems with
+  the combined DiskOnChip 2000 and Millennium driver above. To get
+  the DiskOnChip probe code to load and use this driver instead of
+  the other one, you will need to undefine DOC_SINGLE_DRIVER near
+  the beginning of drivers/mtd/devices/docprobe.c 
+
+  If you use this device, you probably also want to enable the NFTL
+  'NAND Flash Translation Layer' option below, which is used to emulate
+  a block device by using a kind of filesystem on the flash chips.
+
+Probe for DiskOnChip devices
+CONFIG_MTD_DOCPROBE
+  This isn't a real config option, it's derived. 
+
+Advanced detection options for DiskOnChip
+CONFIG_MTD_DOCPROBE_ADVANCED
+  This option allows you to specify nonstandard address at which to
+  probe for a DiskOnChip, or to change the detection options. You're
+  unlikely to need any of this unless you're using LinuxBIOS. Say 'N'.
+
+Probe for 0x55 0xAA BIOS Extension Signature.
+CONFIG_MTD_DOCPROBE_55AA
+  Check for the 0x55 0xAA signature of a DiskOnChip, and do not continue
+  with probing if it is absent. The signature will always be present for
+  a DiskOnChip 2000 or a normal DiskOnChip Millennium. Only if you have
+  overwritten the first block of a DiskOnChip Millennium will it be 
+  absent. Enable this option if you are using LinuxBIOS or if you need
+  to recover a DiskOnChip Millennium on which you have managed to wipe
+  the first block.
+
+Physical address of DiskOnChip
+CONFIG_MTD_DOCPROBE_ADDRESS
+  By default, the probe for DiskOnChip devices will look for a DiskOnChip
+  at every multiple of 0x2000 between 0xC8000 and 0xEE000. This option 
+  allows you to specify a single address at which to probe for the device,
+  which is useful if you have other devices in that range which get upset
+  when they're probed. 
+
+  (Note that on PowerPC, the normal probe will only check at 0xE4000000.)
+
+  Normally, you should leave this set to zero, to allow the probe at the
+  normal addresses.
+
+Probe high addresses
+CONFIG_MTD_DOCPROBE_HIGH
+  By default, the probe for DiskOnChip devices will look for a DiskOnChip
+  at every multiple of 0x2000 between 0xC8000 and 0xEE000. This option 
+  changes to make it probe between 0xFFFC8000 and 0xFFFEE000. Unless
+  you're using LinuxBIOS, this is unlikely to be useful to you. Say 'N'. 
+
+Ramix PMC551 PCI Mezzanine ram card support
+CONFIG_MTD_PMC551
+  This provides a MTD device driver for the Ramix PMC551 RAM PCI card
+  from Ramix Inc. (http://www.ramix.com/products/memory/pmc551.html).
+  These devices come in memory configurations from 32M - 1G.  If you
+  have one, you probably want to enable this.
+
+  If this driver is compiled as a module you get the ability to select the
+  size of the aperture window pointing into the devices memory.  What this 
+  means is that if you have a 1G card, normally the kernel will use a 1G
+  memory map as it's view of the device.  As a module, you can select a
+  1M window into the memory and the driver will "slide" the window around
+  the PMC551's memory.  This was particularly useful on the 2.2 kernels 
+  on PPC architectures as there was limited kernel space to deal with.
+
+PMC551 256M DRAM Bugfix
+CONFIG_MTD_PMC551_BUGFIX
+  Some of Ramix's PMC551 boards with 256M configurations have invalid column
+  and row mux values. This option will fix them, but will break other memory
+  configurations.  If unsure say N.
+
+PMC551 Debugging
+CONFIG_MTD_PMC551_DEBUG
+  This option makes the PMC551 more verbose during it's operation and is only
+  really usefull if you are developing on this driver or suspect a possible
+  hardware or driver bug.  If unsure say N.
+
+Use extra onboard system memory as MTD device
+CONFIG_MTD_SLRAM
+  If your CPU cannot cache all of the physical memory in your machine,
+  you can still use it for storage or swap by using this driver to
+  present it to the system as a Memory Technology Device.
+
+Debugging RAM test driver
+CONFIG_MTD_MTDRAM
+  This enables a test MTD device driver which uses vmalloc() to
+  provide storage. You probably want to say 'N' unless you're
+  testing stuff.
+
+MTDRAM erase block size in KiB
+CONFIG_MTDRAM_ERASE_SIZE
+  This allows you to configure the size of the erase blocks in the
+  device emulated by the MTDRAM driver. If the MTDRAM driver is built
+  as a module, it is also possible to specify this as a parameter when
+  loading the module.
+
+MTDRAM device size in KiB
+CONFIG_MTDRAM_TOTAL_SIZE
+  This allows you to configure the total size of the MTD device
+  emulated by the MTDRAM driver. If the MTDRAM driver is built
+  as a module, it is also possible to specify this as a parameter when
+  loading the module.
+
+SRAM absolute position
+CONFIG_MTDRAM_ABS_POS
+  If you have system RAM accessible by the CPU but not used by Linux
+  in normal operation, you can give the physical address at which the
+  available RAM starts, and the MTDRAM driver will use it instead of
+  allocating space from Linux's available memory. Otherwise, leave 
+  this set to zero. Most people will want to leave this as zero.
+
+Flash chip mapping on the Flaga Digital Module
+CONFIG_MTD_CFI_FLAGADM
+  Mapping for the Flaga digital module. If you don´t have one, ignore this
+  setting.
 
 Support for USB
 CONFIG_USB
@@ -10709,9 +11119,10 @@
 
 USB Handspring Visor Driver
 CONFIG_USB_SERIAL_VISOR
-  Say Y here if you want to connect to your HandSpring Visor through
-  its USB docking station. See http://usbvisor.sourceforge.net for
-  more information on using this driver.
+  Say Y here if you want to connect to your HandSpring Visor, Palm m500
+  or m505 through its USB docking station.
+  See http://usbvisor.sourceforge.net for more information on using this
+  driver.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -10841,6 +11252,29 @@
   The module will be called mct_u232.o.  If you want to compile it as
   a module, say M here and read Documentation/modules.txt.
 
+USB Prolific 2303 Single Port Serial Driver
+CONFIG_USB_SERIAL_PL2303
+  Say Y here if you want to use the PL2303 USB Serial single port
+  adapter from Prolific.
+
+  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 pl2303.o.  If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+
+USB REINER SCT cyberJack pinpad/e-com chipcard reader
+CONFIG_USB_SERIAL_CYBERJACK
+  Say Y here if you want to use a cyberJack pinpad/e-com USB chipcard
+  reader. This is an interface to ISO 7816 compatible contactbased
+  chipcards, e.g. GSM SIMs.
+ 
+  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 cyberjack.o. If you want to compile it as
+  a module, say M here and read Documentation/modules.txt.
+ 
+  If unsure, say N.
+
 USB Edgeport Serial Driver
 CONFIG_USB_SERIAL_EDGEPORT
   Say Y here if you want to use any of the following devices from
@@ -10946,6 +11380,22 @@
   module, say M here and read Documentation/modules.txt.
 
 
+USB SE401 Camera support
+CONFIG_USB_SE401
+  Say Y here if you want to connect this type of camera to your
+  computer's USB port. See Documentation/usb/se401.txt for more
+  information and for a list of supported cameras.
+  
+  This driver uses the Video For Linux API. You must say Y or M to
+  "Video For Linux" (under Multimedia Devices) to use this driver.
+  Information on this API and pointers to "v4l" programs may be found
+  on the WWW at http://roadrunner.swansea.uk.linux.org/v4l.shtml .
+
+  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 se401.o. If you want to compile it as a
+  module, say M here and read Documentation/modules.txt.
+
 USB ADMtek Pegasus-based ethernet device support
 CONFIG_USB_PEGASUS
   Say Y if you want to use your USB ethernet device. Supported
@@ -10972,6 +11422,20 @@
   The module will be called pegasus.o. If you want to compile it as a
   module, say M here and read Documentation/modules.txt.
 
+USB CATC NetMate-based Ethernet device support
+CONFIG_USB_CATC
+  Say Y if you want to use one of the following 10Mbps USB Ethernet
+  device based on the EL1210A chip. Supported devices are:
+    Belkin F5U111
+    CATC NetMate
+    CATC NetMate II
+    smartBridges smartNIC
+
+  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 catc.o. If you want to compile it as a
+  module, say M here and read <file:Documentation/modules.txt>.
+
 USB Kodak DC-2xx Camera support
 CONFIG_USB_DC2XX
   Say Y here if you want to connect this type of still camera to
@@ -11128,12 +11592,13 @@
 
 Microtek USB scanner support
 CONFIG_USB_MICROTEK
-  Say Y here if you want support for the Microtek X6USB and possibly
-  some other scanners by that vendor. The scanner will appear as a
-  scsi generic device to the rest of the system.
-  A patched version of SANE is necessary to use the
-  scanner. It's available at 
-  http://fachschaft.cup.uni-muenchen.de/~neukum/scanner.html
+  Say Y here if you want support for the Microtek X6USB and
+  possibly the Phantom 336CX, Phantom C6 and ScanMaker V6U(S)L.
+  Support for anything but the X6 is experimetal.
+  Please report failures and successes.
+  The scanner will appear as a scsi generic device to the rest
+  of the system. Scsi support is required for this driver to compile
+  and work. SANE 1.0.4 or newer is needed to make use of your scanner.
   This driver can be compiled as a module.
 
 USB Bluetooth support
@@ -11724,12 +12189,13 @@
 
   If unsure, say N.
 
-System V and Coherent file system support (read only)
+System V, Version 7, Xenix and Coherent filesystem support (read only)
 CONFIG_SYSV_FS
   SCO, Xenix and Coherent are commercial Unix systems for Intel
-  machines. Saying Y here would allow you to read from their floppies
-  and hard disk partitions. If you also want to write to these media,
-  say Y to "SYSV file system write support" below.
+  machines, and Version 7 was used on the DEC PDP-11. Saying Y
+  here would allow you to read from their floppies and hard disk
+  partitions. If you also want to write to these media, say Y to
+  "SYSV file system write support" below.
 
   If you have floppies or hard disk partitions like that, it is likely
   that they contain binaries from those other Unix systems; in order
@@ -11738,7 +12204,9 @@
   Xenix, Wyse, UnixWare, Dell Unix and System V programs under Linux
   and is often needed to run commercial software that's only available
   for those systems. It's available via FTP (user: anonymous) from
-  ftp://tsx-11.mit.edu/pub/linux/BETA ).
+  ftp://tsx-11.mit.edu/pub/linux/BETA ). NOTE: that will work only for
+  binaries from Intel-based systems; PDP ones will have to wait until
+  somebody ports Linux to -11 ;-)
 
   If you only intend to mount files from some other Unix over the
   network using NFS, you don't need the System V file system support
@@ -13241,8 +13709,8 @@
 Apple Desktop Bus support
 CONFIG_ADB
   Apple Desktop Bus (ADB) support is for support of devices which
-  are connected to the to an ADB port.  ADB devices tend to have
-  4 pins.  If you have an Apple Macintosh prior to the iMac, or a
+  are connected to an ADB port.  ADB devices tend to have 4 pins.
+  If you have an Apple Macintosh prior to the iMac, or a
   "Blue and White G3", you probably want to say Y here.  Otherwise
   say N.
 
@@ -13730,7 +14198,7 @@
   will issue the hlt instruction if nothing is to be done, thereby
   sending the processor to sleep and saving power.
 
-ACPI Support
+ACPI support
 CONFIG_ACPI
   ACPI/OSPM support for Linux is currently under development. As such, 
   this support is preliminary and EXPERIMENTAL. Configuring ACPI support
@@ -13760,6 +14228,57 @@
   The ACPI mailing list may also be of interest:
   http://phobos.fs.tum.de/acpi/index.html
 
+ACPI Debug Statements
+CONFIG_ACPI_DEBUG
+  The ACPI driver can optionally report errors with a great deal
+  of verbosity. Saying Y enables these statements. This will increase
+  your kernel size by around 50K.
+
+ACPI Bus Manager
+CONFIG_ACPI_BUSMGR
+  The ACPI Bus Manager enumerates devices in the ACPI namespace, and
+  handles PnP messages. All ACPI devices use its services, so using them
+  requires saying Y here.
+
+ACPI System Driver
+CONFIG_ACPI_SYS
+  This driver will enable your system to shut down using ACPI, and dump
+  your ACPI DSDT table using /proc/acpi/dsdt.
+
+ACPI Processor Driver
+CONFIG_ACPI_CPU
+  This driver installs ACPI as the idle handler for Linux, and uses ACPI
+  C2 and C3 processor states to save power, on systems that support it.
+
+ACPI Button
+CONFIG_ACPI_BUTTON
+  This driver registers for events based on buttons, such as the power,
+  sleep, and lid switch. In the future, a daemon will read 
+  /proc/acpi/event and perform user-defined actions such as shutting
+  down the system. Until then, you can cat it, and see output when
+  a button is pressed.
+
+ACPI AC Adapter
+CONFIG_ACPI_AC
+  This driver adds support for the AC Adapter object, which indicates
+  whether a system is on AC, or not. Typically, only laptops have this
+  object, since desktops are always on AC.
+
+ACPI Embedded Controller
+CONFIG_ACPI_EC
+  This driver is required on some systems for the proper operation of the
+  battery and thermal drivers. If you are compiling for a laptop, say Y.
+
+ACPI Control Method Battery
+CONFIG_ACPI_CMBATT
+  This driver adds support for battery information through
+  /proc/acpi/battery. If you have a laptop with a battery, say Y.
+
+ACPI Thermal
+CONFIG_ACPI_THERMAL
+  This driver handles overheating conditions on laptops. It is HIGHLY
+  recommended, as your laptop CPU may be damaged without it.
+
 Advanced Power Management BIOS support
 CONFIG_APM
   APM is a BIOS specification for saving power using several different
@@ -14883,17 +15402,20 @@
 
   If unsure, say Y.
 
-ACI mixer (miroPCM12/PCM20)
+ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)
 CONFIG_SOUND_ACI_MIXER
   ACI (Audio Command Interface) is a protocol used to communicate with
-  the microcontroller on some sound cards produced by miro, e.g. the
-  miroSOUND PCM12 and PCM20. The main function of the ACI is to
-  control the mixer and to get a product identification. 
-
-  This Voxware ACI driver currently only supports the ACI functions on
-  the miroSOUND PCM12 and PCM20 cards. On the PCM20, ACI also controls
-  the radio tuner. This is supported in the video4linux
-  radio-miropcm20 driver.
+  the microcontroller on some sound cards produced by miro and Cardinal
+  Technologies. The main function of the ACI is to control the mixer
+  and to get a product identification. 
+
+  This Voxware ACI driver currently supports the ACI functions on the
+  miroSOUND PCM1-pro, PCM12 and PCM20 radio. On the PCM20 radio, ACI
+  also controls the radio tuner. This is supported in the video4linux
+  miropcm20 driver (say M or Y here and go back to "Multimedia devices"
+  -> "Radio Adapters").
+
+  This driver is also available as a module and will be called aci.o.
 
 SB32/AWE support
 CONFIG_SOUND_AWE32_SYNTH
@@ -15618,6 +16140,20 @@
   isdn4k-utils package. Please read the file
   Documentation/isdn/README.act2000 for more information.
 
+Auvertech TurboPAM support
+CONFIG_ISDN_DRV_TPAM
+  This enables support for the Auvertech TurboPAM ISDN-card.
+  For running this card, additional firmware is necessary, which has
+  to be downloaded into the card using a utility which is distributed
+  separately from the Auvertech's web site: http://www.auvertech.fr.
+
+  Please redirect all support questions to support@auvertech.fr.
+
+  If you want to compile this as a module ( = code which can be
+  inserted in and removed from the running kernel whenever you want),
+  say M here and read Documentation/modules.txt. The module will be
+  called tpam.o.
+
 Hypercope HYSDN cards (Champ, Ergo, Metro) support (module)
 CONFIG_HYSDN
   Say Y here if you have one of Hypercope's active PCI ISDN cards
@@ -16711,11 +17247,11 @@
   say M here and read Documentation/modules.txt. The module will be
   called i2c-parport.o.
 
-Miro PCM20 Radio
+miroSOUND PCM20 radio
 CONFIG_RADIO_MIROPCM20
-  Choose Y here if you have this FM radio card. You also need to say Y
-  to "ACI mixer (miroPCM12/PCM20)" (in "additional low level sound
-  drivers") for this to work.
+  Choose Y here if you have this sound card. You also need to say Y
+  to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound")
+  for this to work.
 
   In order to control your radio card, you will need to use programs
   that are compatible with the Video for Linux API. Information on 
@@ -16725,7 +17261,21 @@
   If you want to compile this driver as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want),
   say M here and read Documentation/modules.txt. The module will be
-  called radio-miropcm20.o
+  called miropcm20.o
+
+miroSOUND PCM20 radio RDS user interface (EXPERIMENTAL)
+CONFIG_RADIO_MIROPCM20_RDS
+  Choose Y here if you want to see RDS/RBDS information like RadioText,
+  Programme Service name, Clock Time and date, Programme TYpe and
+  Traffic Announcement/Programme identification. You also need to say
+  Y to "miroSOUND PCM20 radio" and devfs!
+
+  It's not possible to read the raw RDS packets from the device, so
+  the driver cant provide an V4L interface for this. But the
+  availability of RDS is reported over V4L by the basic driver already.
+  Here RDS can be read from files in /dev/v4l/rds.
+
+  As module the driver will be called miropcm20-rds.o.
 
 GemTek Radio Card
 CONFIG_RADIO_GEMTEK
diff -u --recursive --new-file v2.4.5/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.4.5/linux/Documentation/DocBook/Makefile	Mon May  7 12:14:56 2001
+++ linux/Documentation/DocBook/Makefile	Mon Jul  2 13:56:40 2001
@@ -1,7 +1,7 @@
 BOOKS	:= wanbook.sgml z8530book.sgml mcabook.sgml videobook.sgml \
 	   kernel-api.sgml parportbook.sgml kernel-hacking.sgml \
 	   kernel-locking.sgml via-audio.sgml mousedrivers.sgml sis900.sgml \
-	   deviceiobook.sgml
+	   deviceiobook.sgml procfs-guide.sgml
 
 PS	:=	$(patsubst %.sgml, %.ps, $(BOOKS))
 PDF	:=	$(patsubst %.sgml, %.pdf, $(BOOKS))
@@ -9,6 +9,7 @@
 IMG-parportbook := parport-share.fig parport-multi.fig parport-structure.fig
 EPS-parportbook := $(patsubst %.fig, %.eps, $(IMG-parportbook))
 JPG-parportbook := $(patsubst %.fig, %.jpeg, $(IMG-parportbook))
+C-procfs-example = procfs_example.sgml
 
 books:	$(BOOKS)
 
@@ -28,6 +29,15 @@
 %.jpeg: %.fig
 	-fig2dev -Ljpeg $< $@
 
+%.sgml: %.c
+	echo "<programlisting>" > $@
+	expand --tabs=8 < $< | \
+	sed -e "s/&/\\&amp;/g" \
+	    -e "s/</\\&lt;/g" \
+	    -e "s/>/\\&gt;/g" >> $@
+	echo "</programlisting>" >> $@
+
+
 $(TOPDIR)/scripts/docproc:
 	$(MAKE) -C $(TOPDIR)/scripts docproc
 
@@ -67,6 +77,9 @@
 	$(TOPDIR)/scripts/docgen $(TOPDIR)/drivers/media/video/videodev.c \
 		<videobook.tmpl >videobook.sgml
 
+procfs-guide.sgml:  procfs-guide.tmpl procfs_example.sgml
+	$(TOPDIR)/scripts/docgen < procfs-guide.tmpl >$@
+
 APISOURCES :=	$(TOPDIR)/drivers/media/video/videodev.c \
 		$(TOPDIR)/arch/i386/kernel/irq.c \
 		$(TOPDIR)/arch/i386/kernel/mca.c \
@@ -128,6 +141,7 @@
 	-$(RM) $(BOOKS)
 	-$(RM) $(DVI) $(AUX) $(TEX) $(LOG) $(OUT)
 	-$(RM) $(JPG-parportbook) $(EPS-parportbook)
+	-$(RM) $(C-procfs-example)
 
 mrproper: clean
 	-$(RM) $(PS) $(PDF)
diff -u --recursive --new-file v2.4.5/linux/Documentation/DocBook/procfs-guide.tmpl linux/Documentation/DocBook/procfs-guide.tmpl
--- v2.4.5/linux/Documentation/DocBook/procfs-guide.tmpl	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/procfs-guide.tmpl	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,625 @@
+<!-- -*- sgml -*- -->
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V3.1//EN"[
+<!ENTITY procfsexample SYSTEM "procfs_example.sgml">
+]>
+
+<book id="LKProcfsGuide">
+  <bookinfo>
+    <title>Linux Kernel Procfs Guide</title>
+
+    <authorgroup>
+      <author>
+	<firstname>Erik</firstname>
+	<othername>(J.A.K.)</othername>
+	<surname>Mouw</surname>
+	<affiliation>
+	  <orgname>Delft University of Technology</orgname>
+	  <orgdiv>Faculty of Information Technology and Systems</orgdiv>
+	  <address>
+            <email>J.A.K.Mouw@its.tudelft.nl</email>
+            <pob>PO BOX 5031</pob>
+            <postcode>2600 GA</postcode>
+            <city>Delft</city>
+            <country>The Netherlands</country>
+          </address>
+	</affiliation>
+      </author>
+    </authorgroup>
+
+    <revhistory>
+      <revision>
+	<revnumber>1.0&nbsp;</revnumber>
+	<date>May 30, 2001</date>
+	<revremark>Initial revision posted to linux-kernel</revremark>
+      </revision>
+      <revision>
+	<revnumber>1.1&nbsp;</revnumber>
+	<date>June 3, 2001</date>
+	<revremark>Revised after comments from linux-kernel</revremark>
+      </revision>
+    </revhistory>
+
+    <copyright>
+      <year>2001</year>
+      <holder>Erik Mouw</holder>
+    </copyright>
+
+
+    <legalnotice>
+      <para>
+        This documentation 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.
+      </para>
+      
+      <para>
+        This documentation 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.
+      </para>
+      
+      <para>
+        You should have received a copy of the GNU General Public
+        License along with this program; if not, write to the Free
+        Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+        MA 02111-1307 USA
+      </para>
+      
+      <para>
+        For more details see the file COPYING in the source
+        distribution of Linux.
+      </para>
+    </legalnotice>
+  </bookinfo>
+
+
+
+
+  <toc>
+  </toc>
+
+
+
+
+  <preface>
+    <title>Preface</title>
+
+    <para>
+      This guide describes the use of the procfs file system from
+      within the Linux kernel. The idea to write this guide came up on
+      the #kernelnewbies IRC channel (see <ulink
+      url="http://www.kernelnewbies.org/">http://www.kernelnewbies.org/</ulink>),
+      when Jeff Garzik explained the use of procfs and forwarded me a
+      message Alexander Viro wrote to the linux-kernel mailing list. I
+      agreed to write it up nicely, so here it is.
+    </para>
+
+    <para>
+      I'd like to thank Jeff Garzik
+      <email>jgarzik@mandrakesoft.com</email> and Alexander Viro
+      <email>viro@math.psu.edu</email> for their input, Tim Waugh
+      <email>twaugh@redhat.com</email> for his <ulink
+      url="http://people.redhat.com/twaugh/docbook/selfdocbook/">Selfdocbook</ulink>,
+      and Marc Joosen <email>marcj@historia.et.tudelft.nl</email> for
+      proofreading.
+    </para>
+
+    <para>
+      This documentation was written while working on the LART
+      computing board (<ulink
+      url="http://www.lart.tudelft.nl/">http://www.lart.tudelft.nl/</ulink>),
+      which is sponsored by the Mobile Multi-media Communications
+      (<ulink
+      url="http://www.mmc.tudelft.nl/">http://www.mmc.tudelft.nl/</ulink>)
+      and Ubiquitous Communications (<ulink
+      url="http://www.ubicom.tudelft.nl/">http://www.ubicom.tudelft.nl/</ulink>)
+      projects.
+    </para>
+
+    <para>
+      Erik
+    </para>
+  </preface>
+
+
+
+
+  <chapter id="intro">
+    <title>Introduction</title>
+
+    <para>
+      The <filename class="directory">/proc</filename> file system
+      (procfs) is a special file system in the linux kernel. It's a
+      virtual file system: it is not associated with a block device
+      but exists only in memory. The files in the procfs are there to
+      allow userland programs access to certain information from the
+      kernel (like process information in <filename
+      class="directory">/proc/[0-9]+/</filename>), but also for debug
+      purposes (like <filename>/proc/ksyms</filename>).
+    </para>
+
+    <para>
+      This guide describes the use of the procfs file system from
+      within the Linux kernel. It starts by introducing all relevant
+      functions to manage the files within the file system. After that
+      it shows how to communicate with userland, and some tips and
+      tricks will be pointed out. Finally a complete example will be
+      shown.
+    </para>
+
+    <para>
+      Note that the files in <filename
+      class="directory">/proc/sys</filename> are sysctl files: they
+      don't belong to procfs and are governed by a completely
+      different API described in the Kernel API book.
+    </para>
+  </chapter>
+
+
+
+
+  <chapter id="managing">
+    <title>Managing procfs entries</title>
+    
+    <para>
+      This chapter describes the functions that various kernel
+      components use to populate the procfs with files, symlinks,
+      device nodes, and directories.
+    </para>
+
+    <para>
+      A minor note before we start: if you want to use any of the
+      procfs functions, be sure to include the correct header file! 
+      This should be one of the first lines in your code:
+    </para>
+
+    <programlisting>
+#include &lt;linux/proc_fs.h&gt;
+    </programlisting>
+
+
+
+
+    <sect1 id="regularfile">
+      <title>Creating a regular file</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>create_proc_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        This function creates a regular file with the name
+        <parameter>name</parameter>, file mode
+        <parameter>mode</parameter> in the directory
+        <parameter>parent</parameter>. To create a file in the root of
+        the procfs, use <constant>NULL</constant> as
+        <parameter>parent</parameter> parameter. When successful, the
+        function will return a pointer to the freshly created
+        <structname>struct proc_dir_entry</structname>; otherwise it
+        will return <constant>NULL</constant>. <xref
+        linkend="userland"> describes how to do something useful with
+        regular files.
+      <para>
+
+      <para>
+        Note that it is specifically supported that you can pass a
+        path that spans multiple directories. For example
+        <function>create_proc_entry</function>(<parameter>"drivers/via0/info"</parameter>)
+        will create the <filename class="directory">via0</filename>
+        directory if necessary, with standard
+        <constant>0755</constant> permissions.
+      </para>
+
+    <para>
+      If you only want to be able to read the file, the function
+      <function>create_proc_read_entry</function> described in <xref
+      linkend="convenience"> may be used to create and initialise
+      the procfs entry in one single call.
+    </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a symlink</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry*
+	  <function>proc_symlink</function></funcdef> <paramdef>const
+	  char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry*
+	  <parameter>parent</parameter></paramdef> <paramdef>const
+	  char* <parameter>dest</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        This creates a symlink in the procfs directory
+        <parameter>parent</parameter> that points from
+        <parameter>name</parameter> to
+        <parameter>dest</parameter>. This translates in userland to
+        <literal>ln -s</literal> <parameter>dest</parameter>
+        <parameter>name</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a device</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>proc_mknod</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	  <paramdef>kdev_t <parameter>rdev</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        Creates a device file <parameter>name</parameter> with mode
+        <parameter>mode</parameter> in the procfs directory
+        <parameter>parent</parameter>. The device file will work on
+        the device <parameter>rdev</parameter>, which can be generated
+        by using the <literal>MKDEV</literal> macro from
+        <literal>linux/kdev_t.h</literal>. The
+        <parameter>mode</parameter> parameter
+        <emphasis>must</emphasis> contain <constant>S_IFBLK</constant>
+        or <constant>S_IFCHR</constant> to create a device
+        node. Compare with userland <literal>mknod
+        --mode=</literal><parameter>mode</parameter>
+        <parameter>name</parameter> <parameter>rdev</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Creating a directory</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>proc_mkdir</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        Create a directory <parameter>name</parameter> in the procfs
+        directory <parameter>parent</parameter>.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Removing an entry</title>
+      
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>void <function>remove_proc_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        Removes the entry <parameter>name</parameter> in the directory
+        <parameter>parent</parameter> from the procfs. Entries are
+        removed by their <emphasis>name</emphasis>, not by the
+        <structname>struct proc_dir_entry</structname> returned by the
+        various create functions. Note that this function doesn't
+        recursively remove entries.
+      </para>
+
+      <para>
+        Be sure to free the <structfield>data</structfield> entry from
+        the <structname>struct proc_dir_entry</structname> before
+        <function>remove_proc_entry</function> is called (that is: if
+        there was some <structfield>data</structfield> allocated, of
+        course). See <xref linkend="usingdata"> for more information
+        on using the <structfield>data</structfield> entry.
+      </para>
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="userland">
+    <title>Communicating with userland</title>
+    
+    <para>
+       Instead of reading (or writing) information directly from
+       kernel memory, procfs works with <emphasis>call back
+       functions</emphasis> for files: functions that are called when
+       a specific file is being read or written. Such functions have
+       to be initialised after the procfs file is created by setting
+       the <structfield>read_proc</structfield> and/or
+       <structfield>write_proc</structfield> fields in the
+       <structname>struct proc_dir_entry*</structname> that the
+       function <function>create_proc_entry</function> returned:
+    </para>
+
+    <programlisting>
+struct proc_dir_entry* entry;
+
+entry->read_proc = read_proc_foo;
+entry->write_proc = write_proc_foo;
+    </programlisting>
+
+    <para>
+      If you only want to use a the
+      <structfield>read_proc</structfield>, the function
+      <function>create_proc_read_entry</function> described in <xref
+      linkend="convenience"> may be used to create and initialise the
+      procfs entry in one single call.
+    </para>
+
+
+
+    <sect1>
+      <title>Reading data</title>
+
+      <para>
+        The read function is a call back function that allows userland
+        processes to read data from the kernel. The read function
+        should have the following format:
+      </para>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>int <function>read_func</function></funcdef>
+	  <paramdef>char* <parameter>page</parameter></paramdef>
+	  <paramdef>char** <parameter>start</parameter></paramdef>
+	  <paramdef>off_t <parameter>off</parameter></paramdef>
+	  <paramdef>int <parameter>count</parameter></paramdef>
+	  <paramdef>int* <parameter>eof</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The read function should write its information into the
+        <parameter>page</parameter>. For proper use, the function
+        should start writing at an offset of
+        <parameter>off</parameter> in <parameter>page</parameter> and
+        write at most <parameter>count</parameter> bytes, but because
+        most read functions are quite simple and only return a small
+        amount of information, these two parameters are usually
+        ignored (it breaks pagers like <literal>more</literal> and
+        <literal>less</literal>, but <literal>cat</literal> still
+        works).
+      </para>
+
+      <para>
+        If the <parameter>off</parameter> and
+        <parameter>count</parameter> parameters are properly used,
+        <parameter>eof</parameter> should be used to signal that the
+        end of the file has been reached by writing
+        <literal>1</literal> to the memory location
+        <parameter>eof</parameter> points to.
+      </para>
+
+      <para>
+        The parameter <parameter>start</parameter> doesn't seem to be
+        used anywhere in the kernel. The <parameter>data</parameter>
+        parameter can be used to create a single call back function for
+        several files, see <xref linkend="usingdata">.
+      </para>
+
+      <para>
+        The <function>read_func</function> function must return the
+        number of bytes written into the <parameter>page</parameter>.
+      </para>
+
+      <para>
+        <xref linkend="example"> shows how to use a read call back
+        function.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Writing data</title>
+
+      <para>
+        The write call back function allows a userland process to write
+        data to the kernel, so it has some kind of control over the
+        kernel. The write function should have the following format:
+      </para>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>int <function>write_func</function></funcdef>
+	  <paramdef>struct file* <parameter>file</parameter></paramdef>
+	  <paramdef>const char* <parameter>buffer</parameter></paramdef>
+	  <paramdef>unsigned long <parameter>count</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+
+      <para>
+        The write function should read <parameter>count</parameter>
+        bytes at maximum from the <parameter>buffer</parameter>. Note
+        that the <parameter>buffer</parameter> doesn't live in the
+        kernel's memory space, so it should first be copied to kernel
+        space with <function>copy_from_user</function>. The
+        <parameter>file</parameter> parameter is usually
+        ignored. <xref linkend="usingdata"> shows how to use the
+        <parameter>data</parameter> parameter.
+      </para>
+
+      <para>
+        Again, <xref linkend="example"> shows how to use this call back
+        function.
+      </para>
+    </sect1>
+
+
+
+
+    <sect1 id="usingdata">
+      <title>A single call back for many files</title>
+
+      <para>
+         When a large number of almost identical files is used, it's
+         quite inconvenient to use a separate call back function for
+         each file. A better approach is to have a single call back
+         function that distinguishes between the files by using the
+         <structfield>data</structfield> field in <structname>struct
+         proc_dir_entry</structname>. First of all, the
+         <structfield>data</structfield> field has to be initialised:
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+struct my_file_data *file_data;
+
+file_data = kmalloc(sizeof(struct my_file_data), GFP_KERNEL);
+entry->data = file_data;
+      </programlisting>
+     
+      <para>
+          The <structfield>data</structfield> field is a <type>void
+          *</type>, so it can be initialised with anything.
+      </para>
+
+      <para>
+        Now that the <structfield>data</structfield> field is set, the
+        <function>read_proc</function> and
+        <function>write_proc</function> can use it to distinguish
+        between files because they get it passed into their
+        <parameter>data</parameter> parameter:
+      </para>
+
+      <programlisting>
+int foo_read_func(char *page, char **start, off_t off,
+                  int count, int *eof, void *data)
+{
+        int len;
+
+        if(data == file_data) {
+                /* special case for this file */
+        } else {
+                /* normal processing */
+        }
+
+        return len;
+}
+      </programlisting>
+
+      <para>
+        Be sure to free the <structfield>data</structfield> data field
+        when removing the procfs entry.
+      </para>
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="tips">
+    <title>Tips and tricks</title>
+
+
+
+
+    <sect1 id="convenience">
+      <title>Convenience functions</title>
+
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>struct proc_dir_entry* <function>create_proc_read_entry</function></funcdef>
+	  <paramdef>const char* <parameter>name</parameter></paramdef>
+	  <paramdef>mode_t <parameter>mode</parameter></paramdef>
+	  <paramdef>struct proc_dir_entry* <parameter>parent</parameter></paramdef>
+	  <paramdef>read_proc_t* <parameter>read_proc</parameter></paramdef>
+	  <paramdef>void* <parameter>data</parameter></paramdef>
+	</funcprototype>
+      </funcsynopsis>
+      
+      <para>
+        This function creates a regular file in exactly the same way
+        as <function>create_proc_entry</function> from <xref
+        linkend="regularfile"> does, but also allows to set the read
+        function <parameter>read_proc</parameter> in one call. This
+        function can set the <parameter>data</parameter> as well, like
+        explained in <xref linkend="usingdata">.
+      </para>
+    </sect1>
+
+
+
+    <sect1>
+      <title>Modules</title>
+
+      <para>
+        If procfs is being used from within a module, be sure to set
+        the <structfield>owner</structfield> field in the
+        <structname>struct proc_dir_entry</structname> to
+        <constant>THIS_MODULE</constant>.
+      <para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+
+entry->owner = THIS_MODULE;
+      </programlisting>
+    </sect1>
+
+
+
+
+    <sect1>
+      <title>Mode and ownership</title>
+
+      <para>
+        Sometimes it is useful to change the mode and/or ownership of
+        a procfs entry. Here is an example that shows how to achieve
+        that:
+      </para>
+
+      <programlisting>
+struct proc_dir_entry* entry;
+
+entry->mode =  S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH;
+entry->uid = 0;
+entry->gid = 100;
+      </programlisting>
+
+    </sect1>
+  </chapter>
+
+
+
+
+  <chapter id="example">
+    <title>Example</title>
+
+    <!-- be careful with the example code: it shouldn't be wider than
+    approx. 60 columns, or otherwise it won't fit properly on a page
+    -->
+
+&procfsexample;
+
+  </chapter>
+</book>
diff -u --recursive --new-file v2.4.5/linux/Documentation/DocBook/procfs_example.c linux/Documentation/DocBook/procfs_example.c
--- v2.4.5/linux/Documentation/DocBook/procfs_example.c	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/DocBook/procfs_example.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,249 @@
+/*
+ * procfs_example.c: an example proc interface
+ *
+ * Copyright (C) 2001, Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * This file accompanies the procfs-guide in the Linux kernel
+ * source. Its main use is to demonstrate the concepts and
+ * functions described in the guide.
+ *
+ * This software has been developed while working on the LART
+ * computing board (http://www.lart.tudelft.nl/), which is
+ * sponsored by the Mobile Multi-media Communications
+ * (http://www.mmc.tudelft.nl/) and Ubiquitous Communications 
+ * (http://www.ubicom.tudelft.nl/) projects.
+ *
+ * The author can be reached at:
+ *
+ *  Erik Mouw
+ *  Information and Communication Theory Group
+ *  Faculty of Information Technology and Systems
+ *  Delft University of Technology
+ *  P.O. Box 5031
+ *  2600 GA Delft
+ *  The Netherlands
+ *
+ *
+ * This program is free software; you can redistribute
+ * it and/or modify it under the terms of the GNU General
+ * Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be
+ * useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more
+ * details.
+ * 
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+
+
+#define MODULE_VERSION "1.0"
+#define MODULE_NAME "procfs_example"
+
+#define FOOBAR_LEN 8
+
+struct fb_data_t {
+	char name[FOOBAR_LEN + 1];
+	char value[FOOBAR_LEN + 1];
+};
+
+
+static struct proc_dir_entry *example_dir, *foo_file,
+	*bar_file, *jiffies_file, *tty_device, *symlink;
+
+
+struct fb_data_t foo_data, bar_data;
+
+
+static int proc_read_jiffies(char *page, char **start,
+			     off_t off, int count,
+			     int *eof, void *data)
+{
+	int len;
+
+	MOD_INC_USE_COUNT;
+	
+	len = sprintf(page, "jiffies = %ld\n",
+                      jiffies);
+
+	MOD_DEC_USE_COUNT;
+
+	return len;
+}
+
+
+static int proc_read_foobar(char *page, char **start,
+			    off_t off, int count, 
+			    int *eof, void *data)
+{
+	int len;
+	struct fb_data_t *fb_data = (struct fb_data_t *)data;
+
+	MOD_INC_USE_COUNT;
+	
+	len = sprintf(page, "%s = '%s'\n", 
+		      fb_data->name, fb_data->value);
+
+	MOD_DEC_USE_COUNT;
+
+	return len;
+}
+
+
+static int proc_write_foobar(struct file *file,
+			     const char *buffer,
+			     unsigned long count, 
+			     void *data)
+{
+	int len;
+	struct fb_data_t *fb_data = (struct fb_data_t *)data;
+
+	MOD_INC_USE_COUNT;
+
+	if(count > FOOBAR_LEN)
+		len = FOOBAR_LEN;
+	else
+		len = count;
+
+	if(copy_from_user(fb_data->value, buffer, len)) {
+		MOD_DEC_USE_COUNT;
+		return -EFAULT;
+	}
+
+	fb_data->value[len] = '\0';
+
+	MOD_DEC_USE_COUNT;
+
+	return len;
+}
+
+
+static int __init init_procfs_example(void)
+{
+	int rv = 0;
+
+	/* create directory */
+	example_dir = proc_mkdir(MODULE_NAME, NULL);
+	if(example_dir == NULL) {
+		rv = -ENOMEM;
+		goto out;
+	}
+	
+	example_dir->owner = THIS_MODULE;
+	
+	/* create jiffies using convenience function */
+	jiffies_file = create_proc_read_entry("jiffies", 
+					      0444, example_dir, 
+					      proc_read_jiffies,
+					      NULL);
+	if(jiffies_file == NULL) {
+		rv  = -ENOMEM;
+		goto no_jiffies;
+	}
+
+	jiffies_file->owner = THIS_MODULE;
+
+	/* create foo and bar files using same callback
+	 * functions 
+	 */
+	foo_file = create_proc_entry("foo", 0644, example_dir);
+	if(foo_file == NULL) {
+		rv = -ENOMEM;
+		goto no_foo;
+	}
+
+	strcpy(foo_data.name, "foo");
+	strcpy(foo_data.value, "foo");
+	foo_file->data = &foo_data;
+	foo_file->read_proc = proc_read_foobar;
+	foo_file->write_proc = proc_write_foobar;
+	foo_file->owner = THIS_MODULE;
+		
+	bar_file = create_proc_entry("bar", 0644, example_dir);
+	if(bar_file == NULL) {
+		rv = -ENOMEM;
+		goto no_bar;
+	}
+
+	strcpy(bar_data.name, "bar");
+	strcpy(bar_data.value, "bar");
+	bar_file->data = &bar_data;
+	bar_file->read_proc = proc_read_foobar;
+	bar_file->write_proc = proc_write_foobar;
+	bar_file->owner = THIS_MODULE;
+		
+	/* create tty device */
+	tty_device = proc_mknod("tty", S_IFCHR | 0666,
+				example_dir, MKDEV(5, 0));
+	if(tty_device == NULL) {
+		rv = -ENOMEM;
+		goto no_tty;
+	}
+	
+	tty_device->owner = THIS_MODULE;
+
+	/* create symlink */
+	symlink = proc_symlink("jiffies_too", example_dir, 
+			       "jiffies");
+	if(symlink == NULL) {
+		rv = -ENOMEM;
+		goto no_symlink;
+	}
+
+	symlink->owner = THIS_MODULE;
+
+	/* everything OK */
+	printk(KERN_INFO "%s %s initialised\n",
+	       MODULE_NAME, MODULE_VERSION);
+	return 0;
+
+no_symlink:
+	remove_proc_entry("tty", example_dir);
+no_tty:
+	remove_proc_entry("bar", example_dir);
+no_bar:
+	remove_proc_entry("foo", example_dir);
+no_foo:
+	remove_proc_entry("jiffies", example_dir);
+no_jiffies:			      
+	remove_proc_entry(MODULE_NAME, NULL);
+out:
+	return rv;
+}
+
+
+static void __exit cleanup_procfs_example(void)
+{
+	remove_proc_entry("jiffies_too", example_dir);
+	remove_proc_entry("tty", example_dir);
+	remove_proc_entry("bar", example_dir);
+	remove_proc_entry("foo", example_dir);
+	remove_proc_entry("jiffies", example_dir);
+	remove_proc_entry(MODULE_NAME, NULL);
+
+	printk(KERN_INFO "%s %s removed\n",
+	       MODULE_NAME, MODULE_VERSION);
+}
+
+
+module_init(init_procfs_example);
+module_exit(cleanup_procfs_example);
+
+MODULE_AUTHOR("Erik Mouw");
+MODULE_DESCRIPTION("procfs examples");
+
+EXPORT_NO_SYMBOLS;
diff -u --recursive --new-file v2.4.5/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt
--- v2.4.5/linux/Documentation/fb/matroxfb.txt	Sat Nov 11 18:47:40 2000
+++ linux/Documentation/fb/matroxfb.txt	Mon Jul  2 13:56:40 2001
@@ -173,9 +173,9 @@
 mtrr     - enables write combining on frame buffer. It speeds up video accesses
            much. It is default. You must have MTRR support enabled in kernel
 	   and your CPU must have MTRR (f.e. Pentium II have them).
-sgram    - tells to driver that you have G200 with SGRAM memory. It has no
+sgram    - tells to driver that you have Gxx0 with SGRAM memory. It has no
            effect without `init'.
-sdram    - tells to driver that you have G200 with SDRAM memory.
+sdram    - tells to driver that you have Gxx0 with SDRAM memory.
            It is a default.
 inv24    - change timings parameters for 24bpp modes on Millenium and
            Millenium II. Specify this if you see strange color shadows around
@@ -279,7 +279,7 @@
  + 24bpp does not support correctly XF-FBDev on big-endian architectures.
  + interlaced text mode is not supported; it looks like hardware limitation,
    but I'm not sure.
- + G200 SGRAM/SDRAM is not autodetected.
+ + Gxx0 SGRAM/SDRAM is not autodetected.
  + maybe more...
 And following misfeatures:
  + SVGALib does not restore screen on exit.
@@ -336,7 +336,7 @@
 
 ACCEL, nofastfont
         8x16                 12x22                6x11
-	Millennium I  G200   Millennium I  G200    Millennium I G200
+	Millennium I  G200   Millennium I  G200   Millennium I  G200
 8bpp     7.79         7.24   13.55         7.78   30.00        21.01
 16bpp    9.13         7.78   16.16         7.78   30.00        21.01
 24bpp   14.17        10.72   18.69        10.24   34.99        21.01
@@ -344,7 +344,7 @@
 
 ACCEL, fastfont
         8x16                 12x22                6x11
-	Millennium I  G200    Millennium I G200   Millennium I  G200
+	Millennium I  G200   Millennium I  G200   Millennium I  G200
 8bpp     8.41         6.01    6.54         4.37   16.00        10.51
 16bpp    9.54         9.12    8.76         6.17   17.52        14.01
 24bpp   15.00        12.36   11.67        10.00   22.01        18.32
@@ -355,6 +355,8 @@
 	Millennium I  G200
 TEXT     3.29         1.50
 
+* Yes, it is slower than Millennium I.
+
 
 Dualhead G400
 =============
@@ -376,7 +378,22 @@
  + if you compiled it as module, you must insert i2c-matroxfb, matroxfb_maven
    and matroxfb_crtc2 into kernel.
 
+
+Dualhead G450
+=============
+Driver supports dualhead G450 with some limitations:
+ + secondary head shares videomemory with primary head. It is not problem
+   if you have 32MB of videoram, but if you have only 16MB, you may have
+   to think twice before choosing videomode.
+ + due to hardware limitation, secondary head can use only 16 and 32bpp
+   videomodes.
+ + secondary head is not accelerated.
+ + secondary head always powerups in 640x480@60-32 videomode. You have to use
+   fbset to change this mode.
+ + TV output is not supported
+ + kernel is not fully multihead ready, so some things are impossible to do.
+ + if you compiled it as module, you must insert matroxfb_g450 and matroxfb_crtc2
+   into kernel.
 	
-* Yes, it is slower than Millennium I.
 --
 Petr Vandrovec <vandrove@vc.cvut.cz>
diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX
--- v2.4.5/linux/Documentation/filesystems/00-INDEX	Thu Feb  8 16:32:44 2001
+++ linux/Documentation/filesystems/00-INDEX	Wed Jun 20 11:10:27 2001
@@ -33,7 +33,7 @@
 smbfs.txt
 	- info on using filesystems with the SMB protocol (Windows 3.11 and NT)
 sysv-fs.txt
-	- info on the SystemV/Coherent filesystem.
+	- info on the SystemV/V7/Xenix/Coherent filesystem.
 udf.txt
 	- info and mount options for the UDF filesystem.
 ufs.txt
diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/devfs/ChangeLog linux/Documentation/filesystems/devfs/ChangeLog
--- v2.4.5/linux/Documentation/filesystems/devfs/ChangeLog	Fri Apr  6 10:42:48 2001
+++ linux/Documentation/filesystems/devfs/ChangeLog	Wed Jun 20 10:54:31 2001
@@ -1613,3 +1613,51 @@
 - Updated README from master HTML file
 
 - Ported to kernel 2.4.0-test3-pre4 (which had devfs-patch-v174)
+===============================================================================
+Changes for patch v177
+
+- Updated README from master HTML file
+
+- Documentation cleanups
+
+- Ensure <devfs_generate_path> terminates string for root entry
+  Thanks to Tim Jansen <tim@tjansen.de>
+
+- Exported <devfs_get_name> to modules
+
+- Make <devfs_mk_symlink> send events to devfsd
+
+- Cleaned up option processing in <devfs_setup>
+
+- Fixed bugs in handling symlinks: could leak or cause Oops
+
+- Cleaned up directory handling by separating fops
+  Thanks to Alexander Viro <viro@math.psu.edu>
+===============================================================================
+Changes for patch v178
+
+- Fixed handling of inverted options in <devfs_setup>
+===============================================================================
+Changes for patch v179
+
+- Adjusted <try_modload> to account for <devfs_generate_path> fix
+===============================================================================
+Changes for patch v180
+
+- Fixed !CONFIG_DEVFS_FS stub declaration of <devfs_get_info>
+===============================================================================
+Changes for patch v181
+
+- Answered question posed by Al Viro and removed his comments from <devfs_open>
+
+- Moved setting of registered flag after other fields are changed
+
+- Fixed race between <devfsd_close> and <devfsd_notify_one>
+
+- Global VFS changes added bogus BKL to devfsd_close(): removed
+
+- Widened locking in <devfs_readlink> and <devfs_follow_link>
+
+- Replaced <devfsd_read> stack usage with <devfsd_ioctl> kmalloc
+
+- Simplified locking in <devfsd_ioctl> and fixed memory leak
diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/devfs/README linux/Documentation/filesystems/devfs/README
--- v2.4.5/linux/Documentation/filesystems/devfs/README	Wed Nov 29 10:11:38 2000
+++ linux/Documentation/filesystems/devfs/README	Tue Jun 12 10:57:46 2001
@@ -3,7 +3,7 @@
 
 Linux Devfs (Device File System) FAQ
 Richard Gooch
-3-JUL-2000
+26-APR-2001
 
 -----------------------------------------------------------------------------
 
@@ -18,7 +18,7 @@
 
 http://www.atnf.csiro.au/~rgooch/linux/
 
-NEWFLASH: The official 2.3.46 kernel has
+NEWSFLASH: The official 2.3.46 kernel has
 included the devfs patch. Future patches will be released which
 build on this. These patches are rolled into Linus' tree from time to
 time.
@@ -54,6 +54,7 @@
 Other Issues
 Kernel Naming Scheme
 Devfsd Naming Scheme
+Old Compatibility Names
 SCSI Host Probing Issues
 
 
@@ -99,6 +100,7 @@
 can easily mount the root filesystem by referring to an entry in the
 devfs namespace.
 
+
 The cost of devfs is a small increase in kernel code size and memory
 usage. About 7 pages of code (some of that in __init sections) and 72
 bytes for each entry in the namespace. A modest system has only a
@@ -157,6 +159,7 @@
 of nodes. This means that changes in the kernel must be reflected by
 changes in the MAKEDEV programme, or else the system administrator
 creates device nodes by hand.
+
 The basic problem is that there are two separate databases of
 major and minor numbers. One is in the kernel and one is in /dev (or
 in a MAKEDEV programme, if you want to look at it that way). This is
@@ -192,6 +195,7 @@
 256 kBytes of /dev inodes, but you could argue that embedded systems
 would have hand-tuned /dev directories. I've had to do just that on my
 embedded systems, but I would rather just leave it to devfs.
+
 Another issue is the time taken to lookup an inode when first
 referenced. Not only does this take time in scanning through a list in
 memory, but also the seek times to read the inodes off disc.
@@ -212,7 +216,7 @@
 likely be implemented in an ad-hoc fashion, as different drivers will
 provide their information in different ways.
 
-Devfs is much cleaner, because it (natually) has a uniform mechanism
+Devfs is much cleaner, because it (naturally) has a uniform mechanism
 to provide this information: the device nodes themselves!
 
 
@@ -253,7 +257,7 @@
 But why do that search at all if you don't have to? Once again, it
 seems pointless.
 
-Note thate devfs doesn't use the major&minor system. For devfs
+Note that devfs doesn't use the major&minor system. For devfs
 entries, the connection is done when you lookup the /dev entry. When
 devfs_register() is called, an internal table is appended which has
 the entry name and the file_operations. If the dentry cache doesn't
@@ -274,9 +278,9 @@
 /dev as a system administration tool
 
 Right now /dev contains a list of conceivable devices, most of which I
-don't have. A devfs would only show those devices available on my
-system. This means that listing /dev would be a handy way of checking
-what devices were available.
+don't have. Devfs only shows those devices available on my
+system. This means that listing /dev is a handy way of checking what
+devices are available.
 
 Major&minor size
 
@@ -289,9 +293,9 @@
 each device entry, which can be used to give an effective 32 bit
 device identifier (i.e. that's like having a 32 bit minor
 number). Since this is private to the kernel, there are no C library
-compatibility which you would have with increasing major and minor
-number sizes. See the section on "Allocation of Device Numbers" for
-details on maintaining compatibility with userspace.
+compatibility issues which you would have with increasing major and
+minor number sizes. See the section on "Allocation of Device Numbers"
+for details on maintaining compatibility with userspace.
 
 Solving this requires a kernel change.
 
@@ -375,9 +379,9 @@
 devfsd on any event, such as registration/unregistration of device
 entries, opening and closing devices, looking up inodes, scanning
 directories and more. This has many possibilities. Some of these are
-already implemented.
+already implemented. See:
+
 
-See: 
 http://www.atnf.csiro.au/~rgooch/linux/
 
 Device entry registration events can be used by devfsd to change
@@ -414,6 +418,7 @@
 requests. Instead of using kmod directly, the event is sent to
 devfsd which can implement an arbitrary authentication before loading
 the module itself.
+
 Inode lookup events can also be used to construct arbitrary
 namespaces, without having to resort to populating devfs with symlinks
 to devices that don't exist.
@@ -447,10 +452,10 @@
 
 Who else does it?
 
-FreeBSD has a devfs implementation. Solaris 2 has a pseudo-devfs
-(something akin to scsidev but for all devices, with some unspecified
-kernel support). BeOS, Plan9 and QNX also have it. SGI's IRIX 6.4 and
-above also have a device filesystem.
+FreeBSD has a devfs implementation. Solaris and AIX each have a
+pseudo-devfs (something akin to scsidev but for all devices, with some
+unspecified kernel support). BeOS, Plan9 and QNX also have it. SGI's
+IRIX 6.4 and above also have a device filesystem.
 
 While we shouldn't just automatically do something because others do
 it, we should not ignore the work of others either. FreeBSD has a lot
@@ -613,6 +618,21 @@
 are problems with dealing with symlinks, I'm suspicious of the level
 of security offered in any case.
 
+A better solution is to install util-linux-2.10.h or later, which
+fixes a bug with ttyname handling in the login programme. Then append
+the following lines to your /etc/securetty file:
+
+vc/1
+vc/2
+vc/3
+vc/4
+vc/5
+vc/6
+vc/7
+vc/8
+
+This will not weaken security.
+
 XFree86
 While not essential, it's probably a good idea to upgrade to XFree86
 4.0, as patches went in to make it more devfs-friendly. If you don't,
@@ -627,17 +647,25 @@
 
  # file classes -- these are regular expressions 
 -<console>=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9] 
-+<console>=tty[0-9][0-9]* [0-9][0-9]* :[0-9]\.[0-9] :[0-9] 
++<console>=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9] 
 
  # device classes -- these are shell-style globs 
  <floppy>=/dev/fd[0-1]* 
 
+If the patch does not apply, then change the line:
+
+<console>=tty[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
+
+with:
+
+<console>=tty[0-9][0-9]* vc/[0-9][0-9]* :[0-9]\.[0-9] :[0-9]
+
 
 Disable devpts
 I've had a report of devpts mounted on /dev/pts not working
 correctly. Since devfs will also manage /dev/pts, there is no
 need to mount devpts as well. You should either edit your
-/etc/fstab so devpts is not mounted, or disable devfs from
+/etc/fstab so devpts is not mounted, or disable devpts from
 your kernel configuration.
 
 Unsupported drivers
@@ -664,15 +692,23 @@
 
 The Kernel
 Finally, you need to make sure devfs is compiled into your
-kernel. Set CONFIG_DEVFS_FS=y and recompile your kernel. Next, you
-need to make sure devfs is mounted. The best solution is to pass
-devfs=mount at the kernel boot command line. You can edit
-/etc/lilo.conf and add the line:
-
-append = "devfs=mount"
+kernel. Set CONFIG_DEVFS_FS=y and CONFIG_DEVFS_MOUNT=y and recompile
+your kernel. At boot, devfs will be mounted onto /dev.
 
-
-This will make the kernel mount devfs at boot time onto /dev.
+If you encounter problems booting (for example if you forgot a
+configuration step), you can pass devfs=nomount at the kernel
+boot command line. This will prevent the kernel from mounting devfs at
+boot time onto /dev.
+
+In general, a kernel built with CONFIG_DEVFS_FS=y but without mounting
+devfs onto /dev is completely safe, and requires no
+configuration changes. One exception to take note of is when
+LABEL= directives are used in /etc/fstab. In this
+case you will be unable to boot properly. This is because the
+mount(8) programme uses /proc/partitions as part of
+the volume label search process, and the device names it finds are not
+available, because setting CONFIG_DEVFS_FS=y changes the names in
+/proc/partitions, irrespective of whether devfs is mounted.
 
 Now you've finished all the steps required. You're now ready to boot
 your shiny new kernel. Enjoy.
@@ -701,7 +737,7 @@
 permissions. It may be configured to record changes in permissions and
 will save them in a database (in fact a directory tree), and restore
 these upon boot. This is an efficient method and results in immediate
-saving of current permissions (unlike the tar approach, which save
+saving of current permissions (unlike the tar approach, which saves
 permissions at some unspecified future time).
 
 The default configuration file supplied with devfsd has config entries
@@ -745,8 +781,11 @@
 
 
 
+
 add the following lines to your /etc/devfsd.conf file:
 
+REGISTER	^pt[sy]/.*	IGNORE
+CHANGE		^pt[sy]/.*	IGNORE
 REGISTER	.*		COPY	/dev-state/$devname $devpath
 CHANGE		.*		COPY	$devpath /dev-state/$devname
 CREATE		.*		COPY	$devpath /dev-state/$devname
@@ -758,6 +797,17 @@
 
 
 
+Permissions database stored in normal directory
+
+If you are using an older kernel which doesn't support VFS binding,
+then you won't be able to have the permissions database in a
+mounted-over /dev. However, you can still use a regular
+directory to store the database. The sample /etc/devfsd.conf
+file above may still be used. You will need to create the
+/dev-state directory prior to installing devfsd. If you have
+old permissions in /dev, then just copy the device nodes over
+to the new directory.
+
 
 Dealing with drivers without devfs support
 
@@ -910,13 +960,48 @@
 configuration file is installed, which is used by the MODLOAD
 action. This should be sufficient for most configurations. If you
 require further configuration, edit your /etc/modules.conf
-file.
+file. The way module autoloading work with devfs is:
+
+
+a process attempts to lookup a device node (e.g. /dev/fred)
+
+
+if that device node does not exist, the full pathname is passed to
+devfsd as a string
+
+
+devfsd will pass the string to the modprobe programme (provided the
+configuration line shown above is present), and specifies that
+/etc/modules.devfs is the configuration file
+
+
+/etc/modules.devfs includes /etc/modules.conf to
+access local configurations
+
+modprobe will search it's configuration files, looking for an alias
+that translates the pathname into a module name
+
+
+the translated pathname is then used to load the module.
+
+
+If you wanted a lookup of /dev/fred to load the
+mymod module, you would require the following configuration
+line in /etc/modules.conf:
+
+alias    /dev/fred    mymod
+
+The /etc/modules.devfs configuration file provides many such
+aliases for standard device names. If you look closely at this file,
+you will note that some modules require multiple alias configuration
+lines. This is required to support module autoloading for old and new
+device names.
 
 Mounting root off a devfs device
 If you wish to mount root off a devfs device when you pass the
-"devfs=only" boot option, then you need to pass in the "root="
-option to the kernel when booting. If you use LILO, then you must have
-this in lilo.conf:
+"devfs=only" boot option, then you need to pass in the
+"root=<device>" option to the kernel when booting. If you use
+LILO, then you must have this in lilo.conf:
 
 append = "root=<device>"
 
@@ -926,12 +1011,12 @@
 root = <device>
 
 
-then LILO will determine the device number of  and will write
-that device number into a special place in the kernel image before
-starting the kernel, and the kernel will use that device number to
-mount the root filesystem. So, using the "append" variety ensures that
-LILO passes the root filesystem device as a string, which devfs can
-then use.
+then LILO will determine the device number of <device> and will
+write that device number into a special place in the kernel image
+before starting the kernel, and the kernel will use that device number
+to mount the root filesystem. So, using the "append" variety ensures
+that LILO passes the root filesystem device as a string, which devfs
+can then use.
 
 Note that this isn't an issue if you don't pass "devfs=only".
 
@@ -1067,7 +1152,8 @@
   --------                   --------                   -----------
   /dev/tts/{0,1,...}         /dev/ttyS{0,1,...}         Serial ports
   /dev/cua/{0,1,...}         /dev/cua{0,1,...}          Call out devices
-  /dev/vc/{0,1,...}          /dev/tty{1...63}           Virtual consoles
+  /dev/vc/0                  /dev/tty                   Current virtual console
+  /dev/vc/{1,2,...}          /dev/tty{1...63}           Virtual consoles
   /dev/vcc/{0,1,...}         /dev/vcs{1...63}           Virtual consoles
   /dev/pty/m{0,1,...}        /dev/ptyp??                PTY masters
   /dev/pty/s{0,1,...}        /dev/ttyp??                PTY slaves
@@ -1109,7 +1195,8 @@
 cases, the kernel-supplied naming scheme is quite convenient, so
 devfsd does not provide another naming scheme. The convenience names
 that devfsd creates are in fact the same names as the original devfs
-kernel patch created (before Linus mandated the Big Name Change).
+kernel patch created (before Linus mandated the Big Name
+Change). These are referred to as "new compatibility entries".
 
 In order to configure devfsd to create these convenience names, the
 following lines should be placed in your /etc/devfsd.conf:
@@ -1198,6 +1285,24 @@
 would appear as /dev/xd/c0t0.
 
 
+Old Compatibility Names
+
+The old compatibility names are the legacy device names, such as
+/dev/hda, /dev/sda, /dev/rtc and so on.
+Devfsd can be configured to create compatibility symlinks so that you
+may continue to use the old names in your configuration files and so
+that old applications will continue to function correctly.
+
+In order to configure devfsd to create these legacy names, the
+following lines should be placed in your /etc/devfsd.conf:
+
+REGISTER	.*		MKOLDCOMPAT
+UNREGISTER	.*		RMOLDCOMPAT
+
+This will cause devfsd to create (and destroy) symbolic links which
+point to the kernel-supplied names.
+
+
 SCSI Host Probing Issues
 
 Devfs allows you to identify SCSI discs based in part on SCSI host
@@ -1220,14 +1325,15 @@
 
 means that devices connected to
 
-- first aha1542 controller   - will be c0b#t#u#
-- first parallel port ZIP    - will be c1b#t#u#
-- second aha1542 controller  - will be c2b#t#u#
-- first NCR53C7xx controller - will be c4b#t#u#
-- any extra controller       - will be c5b#t#u#, c6b#t#u#, etc
+- first aha1542 controller   - will be /dev/scsi/host0/bus#/target#/lun#
+- first parallel port ZIP    - will be /dev/scsi/host1/bus#/target#/lun#
+- second aha1542 controller  - will be /dev/scsi/host2/bus#/target#/lun#
+- first NCR53C7xx controller - will be /dev/scsi/host4/bus#/target#/lun#
+- any extra controller       - will be /dev/scsi/host5/bus#/target#/lun#,
+                                       /dev/scsi/host6/bus#/target#/lun#, etc
 - if any of above controllers will not be found - the reserved names will
   not be used by any other device.
-- c3b#t#u# names will never be used
+- /dev/scsi/host3/bus#/target#/lun# names will never be used
 
 
 You can use ',' instead of ':' as the separator character if you
@@ -1343,6 +1449,7 @@
 
 Making things work
 Alternatives to devfs
+What I don't like about devfs
 
 
 
@@ -1518,6 +1625,54 @@
 
 
 
+
+What I don't like about devfs
+
+Here are some common complaints about devfs, and some suggestions and
+solutions that may make it more palatable for you. I can't please
+everybody, but I do try :-)
+
+I hate the naming scheme
+
+First, remember that no naming scheme will please everybody. You hate
+the scheme, others love it. Who's to say who's right and who's wrong?
+Ultimately, the person who writes the code gets to choose, and what
+exists now is a combination of the the choices made by the
+devfs author and the
+kernel maintainer (Linus).
+
+However, not all is lost. If you want to create your own naming
+scheme, it is a simple matter to write a standalone script, hack
+devfsd, or write a script called by devfsd. You can create whatever
+naming scheme you like.
+
+Further, if you want to remove all traces of the devfs naming scheme
+from /dev, you can mount devfs elsewhere (say
+/devfs) and populate /dev with links into
+/devfs. This population can be automated using devfsd if you
+wish.
+
+You can even use the VFS binding facility to make the links, rather
+than using symbolic links. This way, you don't even have to see the
+"destination" of these symbolic links.
+
+Devfs puts policy into the kernel
+
+There's already policy in the kernel. Device numbers are in fact
+policy (why should the kernel dictate what device numbers I use?).
+Face it, some policy has to be in the kernel. The real difference
+between device names as policy and device numbers as policy is that
+no one will use device numbers directly, because device
+numbers are devoid of meaning to humans and are ugly. At least with
+the devfs device names, (even though you can add your own naming
+scheme) some people will use the devfs-supplied names directly. This
+offends some people :-)
+
+Devfs is bloatware
+
+This is not even remotely true. As shown above,
+both code and data size are quite modest.
+
 -----------------------------------------------------------------------------
 
 
@@ -1550,6 +1705,14 @@
 
 http://johannes.erdfelt.com/hotswap.txt.
 Johannes has promised a HTML version will follow.
+
+
+I presented an invited 
+paper
+at the
+
+2nd Annual Storage Management Workshop held in Miamia, Florida,
+U.S.A. in October 2000.
 
 
 
diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/hpfs.txt linux/Documentation/filesystems/hpfs.txt
--- v2.4.5/linux/Documentation/filesystems/hpfs.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/filesystems/hpfs.txt	Mon Jun 11 19:15:27 2001
@@ -1,5 +1,5 @@
-Read/Write HPFS 2.00
-1998-1999, Mikulas Patocka
+Read/Write HPFS 2.05
+1998-2001, Mikulas Patocka
 
 email: mikulas@artax.karlin.mff.cuni.cz
 homepage: http://artax.karlin.mff.cuni.cz/~mikulas/vyplody/hpfs/index-e.cgi
@@ -269,6 +269,20 @@
      Removed a lot of redundant code
 2.00 Fixed a bug in rename (it was there since 1.96)
      Better anti-fragmentation strategy
+2.01 Fixed problem with directory listing over NFS
+     Directory lseek now checks for proper parameters
+     Fixed race-condition in buffer code - it is in all filesystems in Linux;
+        when reading device (cat /dev/hda) while creating files on it, files
+        could be damaged
+2.02 Woraround for bug in breada in Linux. breada could cause accesses beyond
+        end of partition
+2.03 Char, block devices and pipes are correctly created
+     Fixed non-crashing race in unlink (Alexander Viro)
+     Now it works with Japanese version of OS/2
+2.04 Fixed error when ftruncate used to extend file
+2.05 Fixed crash when got mount parameters without =
+     Fixed crash when allocation of anode failed due to full disk
+     Fixed some crashes when block io or inode allocation failed
 
 
  vim: set textwidth=80:
diff -u --recursive --new-file v2.4.5/linux/Documentation/filesystems/udf.txt linux/Documentation/filesystems/udf.txt
--- v2.4.5/linux/Documentation/filesystems/udf.txt	Thu Mar  2 11:17:32 2000
+++ linux/Documentation/filesystems/udf.txt	Mon Jun 11 19:15:27 2001
@@ -1,10 +1,10 @@
 *
 * ./Documentation/filesystems/udf.txt
 *
-UDF Filesystem version 0.9.1
+UDF Filesystem version 0.9.4
 
 If you encounter problems with reading UDF discs using this driver,
-please report them to linux_udf@hootie.lvld.hp.com, which is the
+please report them to linux_udf@hpesjro.fc.hp.com, which is the
 developer's list.
 
 Write support requires a block driver which supports writing. The current
@@ -23,7 +23,8 @@
 	noadinicb	Don't embed data in the inode
 	shortad		Use short ad's
 	longad		Use long ad's (default)
-	strict		Set strict conformance (unused)
+	strict		Set strict conformance
+	iocharset=	Set the NLS character set
 
 The remaining are for debugging and disaster recovery:
 
diff -u --recursive --new-file v2.4.5/linux/Documentation/java.txt linux/Documentation/java.txt
--- v2.4.5/linux/Documentation/java.txt	Thu Jul  1 10:47:08 1999
+++ linux/Documentation/java.txt	Wed Jun 27 13:52:16 2001
@@ -1,4 +1,4 @@
-               Java(tm) Binary Kernel Support for Linux v1.02
+               Java(tm) Binary Kernel Support for Linux v1.03
                ----------------------------------------------
 
 Linux beats them ALL! While all other OS's are TALKING about direct
@@ -30,6 +30,8 @@
    (you should really have read binfmt_misc.txt now):
    support for Java applications:
      ':Java:M::\xca\xfe\xba\xbe::/usr/local/bin/javawrapper:'
+   support for executable Jar files:
+     ':ExecutableJAR:E::jar::/usr/local/bin/jarwrapper:'
    support for Java Applets:
      ':Applet:E::html::/usr/bin/appletviewer:'
    or the following, if you want to be more selective:
@@ -343,7 +345,15 @@
 ====================== Cut here ===================
 
 
-Now simply chmod +x the .class and/or .html files you want to execute.
+====================== Cut here ===================
+#!/bin/bash
+# /usr/local/java/bin/jarwrapper - the wrapper for binfmt_misc/jar
+
+java -jar $1
+====================== Cut here ===================
+
+
+Now simply chmod +x the .class, .jar and/or .html files you want to execute.
 To add a Java program to your path best put a symbolic link to the main
 .class file into /usr/bin (or another place you like) omitting the .class
 extension. The directory containing the original .class file will be
@@ -369,6 +379,11 @@
 	./HelloWorld.class
 
 
+To execute Java Jar files, simple chmod the *.jar files to include
+the execution bit, then just do
+       ./Application.jar
+
+
 To execute Java Applets, simple chmod the *.html files to include
 the execution bit, then just do
 	./Applet.html
@@ -376,5 +391,6 @@
 
 originally by Brian A. Lantz, brian@lantz.com
 heavily edited for binfmt_misc by Richard Günther
-new scripts by Colin J. Watson <cjw44@cam.ac.uk>.
+new scripts by Colin J. Watson <cjw44@cam.ac.uk>
+added executable Jar file support by Kurt Huwig <kurt@iku-netz.de>
 
diff -u --recursive --new-file v2.4.5/linux/Documentation/kernel-docs.txt linux/Documentation/kernel-docs.txt
--- v2.4.5/linux/Documentation/kernel-docs.txt	Fri Apr  6 10:42:48 2001
+++ linux/Documentation/kernel-docs.txt	Thu Jun 28 14:45:07 2001
@@ -3,7 +3,7 @@
                                       
                       Understanding the Linux Kernel.
                                       
-              Juan-Mariano de Goyeneche < jmseyas@dit.upm.es>
+               Juan-Mariano de Goyeneche <jmseyas@dit.upm.es>
                                       
 /*
  * The latest version of this document may be found at:
@@ -41,7 +41,7 @@
        
      * Title: "The Linux Kernel"
        Author: David A. Rusling.
-       URL: http://sunsite.unc.edu/linux/LDP/tlk/tlk.html
+       URL: http://www.linuxdoc.org/LDP/tlk/tlk.html
        Keywords: everything!, book.
        Description: On line, 200 pages book describing most aspects of
        the Linux Kernel. Probably, the first reference for beginners.
@@ -57,7 +57,7 @@
        
      * Title: "The Linux Kernel Hackers' Guide"
        Author: Michael K.Johnson and others.
-       URL: http://khg.redhat.com/HyperNews/get/khg.html
+       URL: http://www.linuxdoc.org/LDP/khg/HyperNews/get/khg.html
        Keywords: everything!
        Description: No more Postscript book-like version. Only HTML now.
        Many people have contributed. The interface is similar to web
@@ -99,15 +99,15 @@
        Author: Richard Gooch.
        URL: http://www.atnf.csiro.au/~rgooch/linux/vfs.txt
        Keywords: VFS, File System, mounting filesystems, opening files,
-       dentries,
-       dcache. Description: Brief introduction to the Linux Virtual File
-       System. What is it, how it works, operations taken when opening a
-       file or mounting a file system and description of important data
+       dentries, dcache.
+       Description: Brief introduction to the Linux Virtual File System.
+       What is it, how it works, operations taken when opening a file or
+       mounting a file system and description of important data
        structures explaining the purpose of each of their entries.
        
      * Title: "The Linux RAID-1, 4, 5 Code"
        Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
-       URL: http://www.ssc.com/lj/issue44/2391.html
+       URL: http://www2.linuxjournal.com/lj-issues/issue44/2391.html
        Keywords: RAID, MD driver.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "A description of the implementation of the RAID-1,
@@ -117,7 +117,7 @@
        
      * Title: "Dynamic Kernels: Modularized Device Drivers"
        Author: Alessandro Rubini.
-       URL: http://www.ssc.com/lj/issue23/1219.html
+       URL: http://www2.linuxjournal.com/lj-issues/issue23/1219.html
        Keywords: device driver, module, loading/unloading modules,
        allocating resources.
        Description: Linux Journal Kernel Korner article. Here is it's
@@ -132,8 +132,8 @@
        Author: Alessandro Rubini.
        URL: http://www2.linuxjournal.com/lj-issues/issue24/1220.html
        Keywords: character driver, init_module, clean_up module,
-       autodetection,
-       mayor number, minor number, file operations, open(), close().
+       autodetection, mayor number, minor number, file operations,
+       open(), close().
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "This article, the second of four, introduces part of
        the actual code to create custom module implementing a character
@@ -152,7 +152,7 @@
        
      * Title: "Dissecting Interrupts and Browsing DMA"
        Author: Alessandro Rubini and Georg v. Zezschwitz.
-       URL: http://www.ssc.com/lj/issue26/interrupt.html
+       URL: http://www2.linuxjournal.com/lj-issues/issue26/1222.html
        Keywords: interrupts, irqs, DMA, bottom halves, task queues.
        Description: Linux Journal Kernel Korner article. Here is it's
        abstract: "This is the fourth in a series of articles about
@@ -187,26 +187,9 @@
        simple---most of the complexity (other than talking to the
        hardware) involves managing network packets in memory".
        
-     * Title: "An Introduction to the Linux 1.3.x Networking Code"
-       Author: Vipul Gupta.
-       URL: http://anchor.cs.binghamton.edu/courses/cs628/linux-net.html
-       Keywords: files, sk_buffs.
-       Description: A short description of files under the net/
-       directory. Each file has a one or two lines paragraph description.
-       sk_buffs explained, too, with some beautiful pictures. A little
-       bit outdated.
-       
-     * Title: "Linux ioctl() Primer"
-       Author: Vipul Gupta.
-       URL: http://anchor.cs.binghamton.edu/courses/cs628/ioctl.html
-       Keywords: ioctl, socket.
-       Description: Little description and examples on the use and
-       implementation of the ioctl() system call. A little bit biased
-       towards sockets.
-       
      * Title: "Writing Linux Device Drivers"
        Author: Michael K. Johnson.
-       URL: http://www.redhat.com/~johnsonm/devices.html
+       URL: http://people.redhat.com/johnsonm/devices.html
        Keywords: files, VFS, file operations, kernel interface, character
        vs block devices, I/O access, hardware interrupts, DMA, access to
        user memory, memory allocation, timers.
@@ -241,7 +224,7 @@
        URL:
        ftp://ftp.llp.fu-berlin.de/pub/linux/LINUX-LAB/whitepapers/drivers
        .ps.gz
-       Keywords: character device drivers, I/O, signals, DMA, accesing
+       Keywords: character device drivers, I/O, signals, DMA, accessing
        ports in user space, kernel environment.
        Description: 68 pages paper on writing character drivers. A little
        bit old (1.993, 1.994) although still useful.
@@ -260,24 +243,17 @@
        Notes: This paper was first published in the Proceedings of the
        First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
        
-     * Title: "The Second Extended Filesystem"
-       Author: Matthew Wilcox.
-       URL: http://pocket.fluff.org/~mrw/linux/ext2.txt
-       Keywords: ext2, filesystem.
-       Description: Description of ext2's blocks, directories, inodes...
-       Notes: Seems to be DOWN. Anyone knows another link for it?
-       
      * Title: "Analysis of the Ext2fs structure"
        Author: Louis-Dominique Dubeau.
        URL: http://step.polymtl.ca/~ldd/ext2fs/ext2fs_toc.html
        Keywords: ext2, filesystem, ext2fs.
        Description: Description of ext2's blocks, directories, inodes,
-       bitmaps, invariants ...
+       bitmaps, invariants...
        
      * Title: "Journaling the Linux ext2fs Filesystem"
        Author: Stephen C. Tweedie.
        URL:
-       ftp://ftp.uk.linux.org:/pub/linux/sct/fs/jfs/journal-design.ps.gz
+       ftp://ftp.uk.linux.org/pub/linux/sct/fs/jfs/journal-design.ps.gz
        Keywords: ext3, journaling.
        Description: Excellent 8-pages paper explaining the journaling
        capabilities added to ext2 by the author, showing different
@@ -291,13 +267,13 @@
        Description: Kernel functions/structures/variables which changed
        from 2.0.x to 2.2.x.
        
-     * Title: "Kernel API changes from 2.2 to 2.3"
+     * Title: "Kernel API changes from 2.2 to 2.4"
        Author: Richard Gooch.
        URL:
-       http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.3.html
-       Keywords: 2.3, changes.
+       http://www.atnf.csiro.au/~rgooch/linux/docs/porting-to-2.4.html
+       Keywords: 2.4, changes.
        Description: Kernel functions/structures/variables which changed
-       from 2.2.x to 2.3.x.
+       from 2.2.x to 2.4.x.
        
      * Title: "Linux Kernel Module Programming Guide"
        Author: Ori Pomerantz.
@@ -333,7 +309,9 @@
        
      * Title: "The Kernel Hacking HOWTO"
        Author: Various Talented People, and Rusty.
-       URL: http://www.samba.org/~netfilter/kernel-hacking-HOWTO.html
+       URL:
+       http://www.lisoleg.net/doc/Kernel-Hacking-HOWTO/kernel-hacking-HOW
+       TO.html
        Keywords: HOWTO, kernel contexts, deadlock, locking, modules,
        symbols, return conventions.
        Description: From the Introduction: "Please understand that I
@@ -345,7 +323,7 @@
        routines. This document assumes familiarity with C, and an
        understanding of what the kernel is, and how it is used. It was
        originally written for the 2.3 kernels, but nearly all of it
-       applies to 2.2 too; 2.0 is slightly different. ".
+       applies to 2.2 too; 2.0 is slightly different".
        
      * Title: "ALSA 0.5.0 Developer documentation"
        Author: Stephan 'Jumpy' Bartels .
@@ -476,23 +454,103 @@
        URL: http://www.linux-mag.com/2000-03/gear_01.html
        Keywords: PCI, bus, bus-mastering.
        Description: The title says it all.
-
+       
      * Title: "Linux 2.4 Kernel Internals"
-       Author: Tigran Aivazian.
+       Author: Tigran Aivazian and Christoph Hellwig.
        URL: http://www.moses.uklinux.net/patches/lki.html
-       Keywords: Linux, kernel, VFS, SMP boot
-       Description: A little book used for a short training course
-       I gave on this subject at VERITAS. Covers building the kernel
-       image, booting (including SMP), process management, VFS and more.
+       Keywords: Linux, kernel, booting, SMB boot, VFS, page cache.
+       Description: A little book used for a short training course.
+       Covers building the kernel image, booting (including SMP bootup),
+       process management, VFS and more.
+       
+     * Title: "Linux IP Networking. A Guide to the Implementation and
+       Modification of the Linux Protocol Stack."
+       Author: Glenn Herrin.
+       URL:
+       http://kernelnewbies.org/documents/ipnetworking/linuxipnetworking.
+       html
+       Keywords: network, networking, protocol, IP, UDP, TCP, connection,
+       socket, receiving, transmitting, forwarding, routing, packets,
+       modules, /proc, sk_buff, FIB, tags.
+       Description: Excellent paper devoted to the Linux IP Networking,
+       explaining anything from the kernel's to the user space
+       configuration tools' code. Very good to get a general overview of
+       the kernel networking implementation and understand all steps
+       packets follow from the time they are received at the network
+       device till they are delivered to applications. The studied kernel
+       code is from 2.2.14 version. Provides code for a working packet
+       dropper example.
+       
+     * Title: "Get those boards talking under Linux."
+       Author: Alex Ivchenko.
+       URL: http://www.ednmag.com/ednmag/reg/2000/06222000/13df2.htm
+       Keywords: data-acquisition boards, drivers, modules, interrupts,
+       memory allocation.
+       Description: Article written for people wishing to make their data
+       acquisition boards work on their GNU/Linux machines. Gives a basic
+       overview on writting drivers, from the naming of functions to
+       interrupt handling.
+       Notes: Two-parts article. Part II is at
+       http://www.ednmag.com/ednmag/reg/2000/07062000/14df.htm
+       
+     * Title: "Linux PCMCIA Programmer's Guide"
+       Author: David Hinds.
+       URL: http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
+       Keywords: PCMCIA.
+       Description: "This document describes how to write kernel device
+       drivers for the Linux PCMCIA Card Services interface. It also
+       describes how to write user-mode utilities for communicating with
+       Card Services.
+       
+     * Title: "The Linux Kernel NFSD Implementation"
+       Author: Neil Brown.
+       URL:
+       http://www.cse.unsw.edu.au/~neilb/oss/linux-commentary/nfsd.html
+       Keywords: knfsd, nfsd, NFS, RPC, lockd, mountd, statd.
+       Description: The title says it all.
+       Notes: Covers knfsd's version 1.4.7 (patch against 2.2.7 kernel).
+       
+     * Title: "A Linux vm README"
+       Author: Kanoj Sarcar.
+       URL: http://reality.sgi.com/kanoj_engr/vm229.html
+       Keywords: virtual memory, mm, pgd, vma, page, page flags, page
+       cache, swap cache, kswapd.
+       Description: Telegraphic, short descriptions and definitions
+       relating the Linux virtual memory implementation.
+       
+     * Title: "(nearly) Complete Linux Loadable Kernel Modules. The
+       definitive guide for hackers, virus coders and system
+       administrators."
+       Author: pragmatic/THC.
+       URL: http://packetstorm.securify.com/groups/thc/LKM_HACKING.html
+       Keywords: syscalls, intercept, hide, abuse, symbol table.
+       Description: Interesting paper on how to abuse the Linux kernel in
+       order to intercept and modify syscalls, make
+       files/directories/processes invisible, become root, hijack ttys,
+       write kernel modules based virus... and solutions for admins to
+       avoid all those abuses.
+       Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x
+       kernels. Also available in txt format at
+       http://www.blacknemesis.org/hacking/txt/cllkm.txt
        
      BOOKS: (Not on-line)
    
      * Title: "Linux Device Drivers"
        Author: Alessandro Rubini.
-       Publisher: O'Reilly &Associates.
+       Publisher: O'Reilly & Associates.
        Date: 1998.
+       Pages: 439.
        ISBN: 1-56592-292-1
        
+     * Title: "Linux Device Drivers, 2nd Edition"
+       Author: Alessandro Rubini and Jonathan Corbet.
+       Publisher: O'Reilly & Associates.
+       Date: 2001.
+       Pages: 586.
+       ISBN: 0-59600-008-1
+       Notes: Further information in
+       http://www.oreilly.com/catalog/linuxdrive2/
+       
      * Title: "Linux Kernel Internals"
        Author: Michael Beck.
        Publisher: Addison-Wesley.
@@ -580,8 +638,26 @@
        Notes: Though not being directly about Linux, Linux aims to be
        POSIX. Good reference.
        
+     * Title: "Understanding the Linux Kernel"
+       Author: Daniel P. Bovet and Marco Cesati.
+       Publisher: O'Reilly & Associates, Inc..
+       Date: 2000.
+       Pages: 702.
+       ISBN: 0-596-00002-2
+       Notes: Further information in
+       http://www.oreilly.com/catalog/linuxkernel/
+       
      MISCELLANEOUS:
    
+     * Name: linux/Documentation
+       Author: Many.
+       URL: Just look inside your kernel sources.
+       Keywords: anything, DocBook.
+       Description: Documentation that comes with the kernel sources,
+       inside the Documentation directory. Some pages from this document
+       (including this document itself) have been moved there, and might
+       be more up to date than the web version.
+       
      * Name: "Linux Source Driver"
        URL: http://lsd.linux.cz
        Keywords: Browsing source code.
@@ -593,6 +669,16 @@
        and variables) and LSD can generate patches for you on the fly
        (files, directories or kernel)".
        
+     * Name: "Linux Kernel Source Reference"
+       Author: Thomas Graichen.
+       URL: http://innominate.org/~graichen/projects/lksr/
+       Keywords: CVS, web, cvsweb, browsing source code.
+       Description: Web interface to a CVS server with the kernel
+       sources. "Here you can have a look at any file of the Linux kernel
+       sources of any version starting from 1.0 up to the (daily updated)
+       current version available. Also you can check the differences
+       between two versions of a file".
+       
      * Name: "Cross-Referencing Linux"
        URL: http://lxr.linux.no/source/
        Keywords: Browsing source code.
@@ -608,7 +694,7 @@
        produced during the week. Published every Thursday.
        
      * Name: "Kernel Traffic"
-       URL: http://kt.zork.net
+       URL: http://kt.zork.net/kernel-traffic/
        Keywords: linux-kernel mailing list, weekly kernel news.
        Description: Weekly newsletter covering the most relevant
        discussions of the linux-kernel mailing list.
@@ -622,10 +708,7 @@
        too.
        
      * Name: "New linux-kernel Mailing List FAQ"
-       URL: Original site:
-       http://www.altern.org/andrebalsa/doc/lkml-faq.html
-       URL: U.S. mirror site:
-       http://www.ececs.uc.edu/~rreilova/linux/lkml-faq.html
+       URL: http://www.tux.org/lkml/
        Keywords: linux-kernel mailing list FAQ.
        Description: linux-kernel is a mailing list for developers to
        communicate. This FAQ builds on the previous linux-kernel mailing
@@ -636,34 +719,34 @@
        
      * Name: "Linux Virtual File System"
        Author: Peter J. Braam.
-       URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs
+       URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
        Keywords: slides, VFS, inode, superblock, dentry, dcache.
        Description: Set of slides, presumably from a presentation on the
        Linux VFS layer. Covers version 2.1.x, with dentries and the
        dcache.
        
-     * Name: "Gary's Enciclopedia - The Linux Kernel"
+     * Name: "Gary's Encyclopedia - The Linux Kernel"
        Author: Gary (I suppose...).
        URL: http://members.aa.net/~swear/pedia/kernel.html
        Keywords: links, not found here?.
-       Description: Gary's Enciclopedia exists to allow the rapid finding
+       Description: Gary's Encyclopedia exists to allow the rapid finding
        of documentation and other information of interest to GNU/Linux
        users. It has about 4000 links to external pages in 150 major
        categories. This link is for kernel-specific links, documents,
-       sites... Look there if you could not find here whar you were
+       sites... Look there if you could not find here what you were
        looking for.
        
      * Name: "The home page of Linux-MM"
        Author: The Linux-MM team.
-       URL: http://www.linux.eu.org/Linux-MM/
+       URL: http://linux-mm.org/
        Keywords: memory management, Linux-MM, mm patches, TODO, docs,
        mailing list.
-       Description: Site devoted to Linux Memory Mangement development.
+       Description: Site devoted to Linux Memory Management development.
        Memory related patches, HOWTOs, links, mm developers... Don't miss
        it if you are interested in memory management development!
        
      * Name: "Kernel Newbies IRC Channel"
-       URL: http://www.surriel.com/kernelnewbies.shtml
+       URL: http://www.kernelnewbies.org
        Keywords: IRC, newbies, channel, asking doubts.
        Description: #kernelnewbies on irc.openprojects.net. From the web
        page: "#kernelnewbies is an IRC network dedicated to the 'newbie'
@@ -672,7 +755,8 @@
        professional kernel hackers that want to help less seasoned kernel
        people. [...] #kernelnewbies is on the Open Projects IRC Network,
        try irc.openprojects.net or irc.<country>.openprojects.net as your
-       server and then /join #kernelnewbies".
+       server and then /join #kernelnewbies". It also hosts articles,
+       documents, FAQs...
        
      * Name: "linux-kernel mailing list archives and search engines"
        URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
@@ -683,4 +767,4 @@
        you have a better/another one, please let me know.
      _________________________________________________________________
    
-   Document last updated on Thu Jun 1 21:58:18 CEST 2000DATE$
+   Document last updated on Thu Jun 28 15:09:39 CEST 2001
diff -u --recursive --new-file v2.4.5/linux/Documentation/kernel-parameters.txt linux/Documentation/kernel-parameters.txt
--- v2.4.5/linux/Documentation/kernel-parameters.txt	Wed Apr 18 11:49:11 2001
+++ linux/Documentation/kernel-parameters.txt	Wed Jun 20 11:21:33 2001
@@ -455,6 +455,10 @@
 		lastbus=N		[IA-32] Scan all buses till bus #N. Can be useful
 					if the kernel is unable to find your secondary buses
 					and you want to tell it explicitly which ones they are.
+		assign-busses		[IA-32] Always assign all PCI bus
+					numbers ourselves, overriding
+					whatever the firmware may have
+					done.
 
 	pd.		[PARIDE]
 
diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/TODO linux/Documentation/networking/TODO
--- v2.4.5/linux/Documentation/networking/TODO	Thu Apr 19 13:43:40 2001
+++ linux/Documentation/networking/TODO	Mon Jul  2 14:03:04 2001
@@ -14,12 +14,5 @@
 
 * Add ETHTOOL_GDRVINFO ioctl support to all ethernet drivers.
 
-
-
-To-do items to consider for network drivers
--------------------------------------------
-* Make a single function which handles the ethtool ioctl for
-  most MII-compatible devices?  Ideally the driver would pass function
-  pointers to its existing mdio_{read,write} functions when calling the
-  generic ioctl handler.
+* dmfe PCI DMA is totally wrong and only works on x86
 
diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/alias.txt linux/Documentation/networking/alias.txt
--- v2.4.5/linux/Documentation/networking/alias.txt	Tue Apr 28 14:22:04 1998
+++ linux/Documentation/networking/alias.txt	Fri Jun 29 19:38:26 2001
@@ -2,40 +2,43 @@
 IP-Aliasing:
 ============
 
+IP-aliases are additional IP-adresses/masks hooked up to a base 
+interface by adding a colon and a string when running ifconfig. 
+This string is usually numeric, but this is not a must.
+
+IP-Aliases are avail if CONFIG_INET (`standard' IPv4 networking) 
+is configured in the kernel.
 
-o For IP aliasing you must have IP_ALIAS support included by static
-  linking.
 
 o Alias creation.
-  Alias creation is done by 'magic' iface naming: eg. to create a
+  Alias creation is done by 'magic' interface naming: eg. to create a
   200.1.1.1 alias for eth0 ...
   
     # ifconfig eth0:0 200.1.1.1  etc,etc....
                    ~~ -> request alias #0 creation (if not yet exists) for eth0
-    and routing stuff also ...
-    # route add -host 200.1.1.1 dev eth0:0  (if same IP network as
-					    main device)
-   
-    # route add -net 200.1.1.0 dev eth0:0   (if completely new network wanted
-					    for eth0:0)
+
+    The corresponding route is also set up by this command. 
+    Please note: The route always points to the base interface.
+	
 
 o Alias deletion.
-  Also done by shutting the interface down:
+  The alias is removed by shutting the alias down:
 
     # ifconfig eth0:0 down
                  ~~~~~~~~~~ -> will delete alias
 
   		   		   
-Alias (re-)configuring
+o Alias (re-)configuring
 
-  Aliases are not real devices, but programs` should be able to configure and
+  Aliases are not real devices, but programs should be able to configure and
   refer to them as usual (ifconfig, route, etc).
 
-Relationship with main device
------------------------------
 
-  - the main device is an alias itself like additional aliases and can
-    be shut down without deleting other aliases.
+o Relationship with main device
+
+  If the base device is shut down the added aliases will be deleted 
+  too.
+
 
 Contact
 -------
diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/sk98lin.txt linux/Documentation/networking/sk98lin.txt
--- v2.4.5/linux/Documentation/networking/sk98lin.txt	Fri Sep 15 14:34:19 2000
+++ linux/Documentation/networking/sk98lin.txt	Mon Jul  2 13:56:40 2001
@@ -1,16 +1,17 @@
-(C)Copyright 1999-2000 SysKonnect.
+(C)Copyright 1999-2001 SysKonnect GmbH.
+All rights reserved
 ===========================================================================
 
-sk98lin.txt created 12-Sept-2000
+sk98lin.txt created 28-May-2001
 
-Readme File for sk98lin.o v3.05
-SK-NET Gigabit Ethernet Adapter SK-98xx Driver for Linux
+Readme File for sk98lin v4.06
+SK-NET Gigabit Ethernet PCI driver for LINUX
 
 This file contains
 (1) OVERVIEW
 (2) REQUIRED FILES
 (3) INSTALLATION
-(4) INCLUSION OF THE ADAPTER AT SYSTEM START
+(4) INCLUSION OF ADAPTER AT SYSTEM START
 (5) DRIVER PARAMETERS
 (6) LARGE FRAME SUPPORT
 (7) TROUBLESHOOTING
@@ -19,13 +20,12 @@
 ===========================================================================
 
 
-
 (1) OVERVIEW
 ============
 
 The sk98lin driver supports the SysKonnect SK-NET Gigabit Ethernet
 Adapter SK-98xx family on Linux 2.2.x and above.
-It has been tested with Linux on Intel/x86, ALPHA and UltraSPARC machines.
+It has been tested with Linux on Intel/x86 machines.
 From v3.02 on, the driver is integrated in the linux kernel source.
 ***
 
@@ -64,8 +64,8 @@
    "make modules_install".
    Reboot your system.
 
-4) Load the module manually by entering:
-       insmod sk98lin.o
+2) Load the module manually by entering:
+       modprobe sk98lin
    If the SysKonnect SK-98xx adapter is installed in your
    computer and you have a /proc filesystem, running the command
    'more /proc/net/dev' should produce an output containing a
@@ -75,7 +75,7 @@
    
    NOTE 1: If you have more than one SysKonnect SK-98xx adapter, the
            adapters will be listed as 'eth0', 'eth1', 'eth2', etc.
-           For each adapter, repeat the steps 5) and 6).
+           For each adapter, repeat the steps 3) and 4).
    NOTE 2: If you have other Ethernet adapters installed,
            your SysKonnect SK-98xx adapter can be mapped to 'eth1' or
 	   'eth2' ...
@@ -84,7 +84,7 @@
 	   for each adapter that is found, containing the
 	   corresponding 'ethX'.
 
-5) Select an IP address and assign it to the respective adapter by
+3) Select an IP address and assign it to the respective adapter by
    entering:
        ifconfig eth0 <ip-address>
    This causes the adapter to connect to the ethernet. The solitary
@@ -99,22 +99,22 @@
    NOTE: If you are in doubt about IP addresses, ask your network
          administrator for assistance.
 
-6) Your adapter should now be fully operational.
+4) Your adapter should now be fully operational.
    Use 'ping <otherstation>' to verify the connection to other
    computers on your network.
-   By entering 'ifconfig', you can check the number of packets sent
-   and received by your adapter and additional some other information
-   regarding the adapter configuration.
+   By viewing /proc/net/sk98lin/[devicename], you can check some 
+   information regarding to the adapter configuration.
+
 
-7) The driver module can be stopped and unloaded using the following
+5) The driver module can be stopped and unloaded using the following
    commands:
        ifconfig eth0 down
        rmmod sk98lin
 ***
 
 
-(4) INCLUSION OF THE ADAPTER AT SYSTEM START
-============================================
+(4) INCLUSION OF ADAPTER AT SYSTEM START
+========================================
 
 Since a large number of different Linux distributions are 
 available, we are unable to describe a general installation procedure
@@ -129,7 +129,7 @@
 =====================
 
 Parameters can be set at the command line while loading the
-module with 'insmod'. The configuration tools of some distributions
+module with 'modprobe'. The configuration tools of some distributions
 can also give parameters to the driver module.
 If you use the kernel module loader, you can set driver parameters
 in the file /etc/modules.conf (or old name: /etc/conf.modules).
@@ -138,12 +138,12 @@
 options sk98lin ...
 
 For "...", use the same syntax as described below for the command
-line parameters of insmod.
+line paramaters of modprobe.
 You either have to reboot your computer or unload and reload
 the driver to activate the new parameters.
 The syntax of the driver parameters is:
 
-insmod sk98lin parameter=value1[,value2[,value3...]]
+modprobe sk98lin parameter=value1[,value2[,value3...]]
 
 value1 is for the first adapter, value2 for the second one etc.
 All Parameters are case sensitive, so write them exactly as
@@ -156,7 +156,7 @@
 	adapter to FULL and on Port A of the second adapter to HALF.
 	You must enter:
 
-	insmod sk98lin.o AutoNeg_A=On,Off DupCap_A=Full,Half
+	modprobe sk98lin AutoNeg_A=On,Off DupCap_A=Full,Half
 
 NOTE: The number of adapters that can be configured this way is
       limited in the driver (file skge.c, constant SK_MAX_CARD_PARAM).
@@ -187,7 +187,7 @@
   this port is not "Sense". If autonegotiation is "On", all
   three values are possible. If it is "Off", only "Full" and
   "Half" are allowed.
-  It is useful if your link partner does not support all
+  It is usefull if your link partner does not support all
   possible combinations.
 
 - Flow Control
@@ -234,7 +234,7 @@
 
 - RLMT (Redundant Link Management Technology) Mode
   Parameter:	RlmtMode
-  Values:	CheckLinkState,CheckLocalPort, CheckSeg
+  Values:	CheckLinkState,CheckLocalPort, CheckSeg, DualNet
   Default:	CheckLinkState
 
   RLMT (the driver part that decides which port to use) knows three
@@ -257,6 +257,13 @@
    Ethernet switches installed in your network that have been configured
    to use the Spanning Tree protocol.
 
+-- DualNet - Both ports A and B are used as separate devices at the same
+   time. So if you have a dual port adapter, port A will show up as eth0
+   and port B as eth1. Both ports can be used independend with distinct
+   IP addresses.
+   The preferred port setting is not used. Rlmt is turned off.
+   
+
   NOTE: The modes CheckLocalPort and CheckSeg are meant to operate in
         configurations where a network path between the ports on one
         adapter exists. Especially, they are not designed to work where
@@ -269,7 +276,7 @@
 
 Large frames (also called jumbo frames) are now supported by the
 driver. This can result in a greatly improved throughput if
-transferring large amounts of data.
+transfering large amounts of data.
 To enable large frames, set the MTU (maximum transfer unit)
 of the interface to the value you wish (up to 9000). The command
 for this is:
@@ -285,7 +292,7 @@
 You can switch back to the standard ethernet frame size with:
   ifconfig eth0 mtu 1500
 
-To make this setting persistent, add a script with the 'ifconfig'
+To make this setting persitent, add a script with the 'ifconfig'
 line to the system startup sequence (named something like "S99sk98lin"
 in /etc/rc.d/rc2.d).
 ***
@@ -373,11 +380,27 @@
 (8) HISTORY
 ===========
 
-VERSION 3.05 (In-Kernel version)
+VERSION 4.02 (In-Kernel version)
+New Features:
+- Add Kernel 2.4 changes
+Known limitations:
+- None
+
+VERSION 4.01 (In-Kernel version)
+Problems fixed:
+- Full statistics support for DualNet mode
+Known limitations:
+- None
+
+VERSION 4.00 (In-Kernel version)
 Problems fixed:
-- Failed for multiple adapters in kernel 2.4.0
-New features:
-- New versions of several common modules
+- Memory leak found 
+New Features:
+- Proc filesystem integration
+- DualNet functionality integrated
+- Rlmt networks added
+Known limitations:
+- statistics partially incorrect in DualNet mode
 
 VERSION 3.04 (In-Kernel version)
 Problems fixed:
diff -u --recursive --new-file v2.4.5/linux/Documentation/networking/vortex.txt linux/Documentation/networking/vortex.txt
--- v2.4.5/linux/Documentation/networking/vortex.txt	Tue Mar  6 19:13:51 2001
+++ linux/Documentation/networking/vortex.txt	Wed Jun 20 11:15:44 2001
@@ -230,6 +230,23 @@
 other media types does not occur.
 
 
+Transmit error, Tx status register 82
+-------------------------------------
+
+This is a common error which is almost always caused by another host on
+the same network being in full-duplex mode, while this host is in
+half-duplex mode.  You need to find that other host and make it run in
+half-duplex mode or fix this host to run in full-duplex mode.
+
+As a last resort, you can force the 3c59x driver into full-duplex mode
+with
+
+	options 3c59x full_duplex=1
+
+but this has to be viewed as a workaround for broken network gear and
+should only really be used for equipment which cannot autonegotiate.
+
+
 Additional resources
 --------------------
 
diff -u --recursive --new-file v2.4.5/linux/Documentation/pci.txt linux/Documentation/pci.txt
--- v2.4.5/linux/Documentation/pci.txt	Sat May 19 17:43:05 2001
+++ linux/Documentation/pci.txt	Thu Jun 28 14:58:05 2001
@@ -62,8 +62,13 @@
 			deregistration of the driver or when it's manually pulled
 			out of a hot-pluggable slot). This function always gets
 			called from process context, so it can sleep.
-	suspend,	Power management hooks -- called when the device goes to
-	resume		sleep or is resumed.
+	save_state	Save a device's state before it's suspend.
+	suspend		Put device into low power state.
+	resume		Wake device from low power state.
+	enable_wake	Enable device to generate wake events from a low power state.
+
+			(Please see Documentation/power/pci.txt for descriptions
+			of PCI Power Management and the related functions)
 
 The ID table is an array of struct pci_device_id ending with a all-zero entry.
 Each entry consists of:
diff -u --recursive --new-file v2.4.5/linux/Documentation/power/pci.txt linux/Documentation/power/pci.txt
--- v2.4.5/linux/Documentation/power/pci.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/power/pci.txt	Thu Jun 28 14:58:05 2001
@@ -0,0 +1,306 @@
+
+PCI Power Management
+~~~~~~~~~~~~~~~~~~~~
+
+An overview of the concepts and the related functions in the Linux kernel
+
+Patrick Mochel <mochel@transmeta.com>
+
+---------------------------------------------------------------------------
+
+1. Overview
+2. How the PCI Subsystem Does Power Management
+3. PCI Utility Functions
+4. PCI Device Drivers
+5. Resources
+
+1. Overview
+~~~~~~~~~~~
+
+The PCI Power Management Specification was introduced between the PCI 2.1 and
+PCI 2.2 Specifications. It a standard interface for controlling various 
+power management operations.
+
+Implementation of the PCI PM Spec is optional, as are several sub-components of
+it. If a device supports the PCI PM Spec, the device will have an 8 byte 
+capability field in its PCI configuration space. This field is used to describe
+and control the standard PCI power management features.
+
+The PCI PM spec defines 4 operating states for devices (D0 - D3) and for buses
+(B0 - B3). The higher the number, the less power the device consumes. However,
+the higher the number, the longer the latency is for the device to return to 
+an operational state (D0).
+
+Bus power management is not covered in this version of this document.
+
+Note that all PCI devices support D0 and D3 by default, regardless of whether or
+not they implement any of the PCI PM spec.
+
+The possible state transitions that a device can undergo are:
+
++---------------------------+
+| Current State | New State |
++---------------------------+
+| D0            | D1, D2, D3|
++---------------------------+
+| D1            | D2, D3    |
++---------------------------+
+| D2            | D3        |
++---------------------------+
+| D1, D2, D3    | D0        |
++---------------------------+
+
+Note that when the system is entering a global suspend state, all devices will be 
+placed into D3 and when resuming, all devices will be placed into D0. However, 
+when the system is running, other state transitions are possible.
+
+2. How The PCI Subsystem Handles Power Management
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The PCI suspend/resume functionality is accessed indirectly via the Power Management 
+subsystem. At boot, the PCI driver registers a power management callback with that layer.
+Upon entering a suspend state, the PM layer iterates through all of its registered 
+callbacks. This currently takes place only during APM state transitions.
+
+Upon going to sleep, the PCI subsystem walks its device tree twice. Both times, it does
+a depth first walk of the device tree. The first walk saves  each of the device's state 
+and checks for devices that will prevent the system from entering a global power state. 
+The next walk then places the devices in a low power state.
+
+The first walk allows a graceful recovery in the event of a failure, since none of the 
+devices have actually been powered down.
+
+In both walks, in particular the second, all children of a bridge are touched before the
+actual bridge itself. This allows the bridge to retain power while its children are being
+accessed.
+
+Upon resuming from sleep, just the opposite must be true: all bridges must be powered on
+and restored before their children are powered on. This is easily accomplished with a
+breadth-first walk of the PCI device tree.
+
+
+3. PCI Utility Functions
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+These are helper functions designed to be called by individual device drivers.
+Assuming that a device behaves as advertised, these should be applicable in most
+cases. However, results may vary.
+
+Note that these functions are never implicitly called for the driver. The driver is always
+responsible for deciding when and if to call these.
+
+
+pci_save_state
+--------------
+
+Usage:
+	pci_save_state(dev, buffer);
+
+Description:
+	Save first 64 bytes of PCI config space. Buffer must be allocated by caller.
+
+
+pci_restore_state
+-----------------
+
+Usage:
+	pci_restore_state(dev,buffer);
+
+Description:
+	Restore previously saved config space. (First 64 bytes only);
+
+	If buffer is NULL, then restore what information we know about the device
+	from bootup: BARs and interrupt line.
+
+
+pci_set_power_state
+-------------------
+
+Usage:
+	pci_set_power_state(dev,state);
+
+Description:
+	Transition device to low power state using PCI PM Capabilities registers.
+
+	Will fail under one of the following conditions:
+	- If state is less than current state, but not D0 (illegal transition)
+	- Device doesn't support PM Capabilities
+	- Device does not support requested state
+
+
+pci_enable_wake
+---------------
+
+Usage:
+	pci_enable_wake(dev,state,enable);
+
+Description:
+	Enable device to generate PME# during low power state using PCI PM 
+	Capabilities.
+
+	Checks whether if device supports generating PME# from requested state and fail
+	if it does not, unless enable == 0 (request is to disable wake events, which
+	is implicit if it doesn't even support it in the first place).
+
+	Note that the PMC Register in the device's PM Capabilties has a bitmask of
+	the states it supports generating PME# from. D3hot is bit 3 and D3cold is bit
+	4. So, while a value of 4 as the state may not seem semantically correct, it
+	is. 
+
+
+4. PCI Device Drivers
+~~~~~~~~~~~~~~~~~~~~~
+
+These functions are intended for use by individual drivers, and are defined in 
+struct pci_driver:
+
+        int  (*save_state) (struct pci_dev *dev, u32 state);
+        int  (*suspend)(struct pci_dev *dev, u32 state);
+        int  (*resume) (struct pci_dev *dev);
+        int  (*enable_wake) (struct pci_dev *dev, u32 state, int enable);
+
+
+save_state
+----------
+
+Usage:
+
+if (dev->driver && dev->driver->save_state)
+	dev->driver->save_state(dev,state);
+
+The driver should use this callback to save device state. It should take into 
+account the current state of the device and the requested state in order to avoid
+any unnecessary operations.
+
+For example, a video card that supports all 4 states (D0-D3), all controller context
+is preserved when entering D1, but the screen is placed into a low power state
+(blanked). 
+
+The driver can also interpret this function as a notification that it may be entering
+a sleep state in the near future. If it knows that the device cannot enter the 
+requested state, either because of lack of support for it, or because the devices is 
+middle of some critical operation, then it should fail.
+
+This function should not be used to set any state in the device or the driver because
+the device may not actually enter the sleep state (e.g. another driver later causes
+causes a global state transition to fail).
+
+Note that in intermediate low power states, a device's I/O and memory spaces may be
+disabled and may not be available in subsequent transitions to lower power states.
+
+
+suspend
+-------
+
+Usage:
+
+if (dev->driver && dev->driver->suspend)
+	dev->driver->suspend(dev,state);
+
+A driver uses this function to actually transition the device into a low power 
+state. This may include disabling I/O, memory and bus-mastering, as well as physically
+transitioning the device to a lower power state.
+
+Bus mastering may be disabled by doing:
+
+pci_disable_device(dev);
+
+For devices that support the PCI PM Spec, this may be used to set the device's power 
+state:
+
+pci_set_power_state(dev,state);
+
+The driver is also responsible for disabling any other device-specific features
+(e.g blanking screen, turning off on-card memory, etc).
+
+The driver should be sure to track the current state of the device, as it may obviate
+the need for some operations.
+
+The driver should update the current_state field in its pci_dev structure in this 
+function.
+
+resume
+------
+
+Usage:
+
+if (dev->driver && dev->driver->suspend)
+	dev->driver->resume(dev)
+
+The resume callback may be called from any power state, and is always meant to 
+transition the device to the D0 state. 
+
+The driver is responsible for reenabling any features of the device that had 
+been disabled during previous suspend calls and restoring all state that was saved
+in previous save_state calls.
+
+If the device is currently in D3, it must be completely reinitialized, as it must be
+assumed that the device has lost all of its context (even that of its PCI config 
+space). For almost all current drivers, this means that the initialization code that
+the driver does at boot must be separated out and called again from the resume
+callback. Note that some values for the device may not have to be probed for this
+time around if they are saved before entering the low power state.
+
+If the device supports the PCI PM Spec, it can use this to physically transition the
+device to D0:
+
+pci_set_power_state(dev,0);
+
+Note that if the entire system is transitioning out of a global sleep state, all 
+devices will be placed in the D0 state, so this is not necessary. However, in the
+event that the device is placed in the D3 state during normal operation, this call
+is necessary. It is impossible to determine which of the two events is taking place
+in the driver, so it is always a good idea to make that call.
+
+The driver should take note of the state that it is resuming from in order to ensure
+correct (and speedy) operation.
+
+The driver should update the current_state field in its pci_dev structure in this 
+function.
+
+
+enable_wake
+-----------
+
+Usage:
+
+if (dev->driver && dev->driver->enable_wake)
+	dev->driver->enable_wake(dev,state,enable);
+
+This callback is generally only relevant for devices that support the PCI PM
+spec and have the ability to generate a PME# (Power Management Event Signal)
+to wake the system up. (However, it is possible that a device may support 
+some non-standard way of generating a wake event on sleep.)
+
+Bits 15:11 of the PMC (Power Mgmt Capabilities) Register in a device's
+PM Capabilties describe what power states the device supports generating a 
+wake event from:
+
++------------------+
+|  Bit  |  State   |
++------------------+
+|  15   |   D0     |
+|  14   |   D1     |
+|  13   |   D2     |
+|  12   |   D3hot  |
+|  11   |   D3cold |
++------------------+
+
+A device can use this to enable wake events:
+
+	 pci_enable_wake(dev,state,enable);
+
+Note that to enable PME# from D3cold, a value of 4 should be passed to 
+pci_enable_wake (since it uses an index into a bitmask). If a driver gets
+a request to enable wake events from D3, two calls should be made to 
+pci_enable_wake (one for both D3hot and D3cold).
+
+
+5. Resources
+~~~~~~~~~~~~
+
+PCI Local Bus Specification 
+PCI Bus Power Management Interface Specification
+
+  http://pcisig.org
+
diff -u --recursive --new-file v2.4.5/linux/Documentation/sound/README.OSS linux/Documentation/sound/README.OSS
--- v2.4.5/linux/Documentation/sound/README.OSS	Wed Apr 11 19:02:27 2001
+++ linux/Documentation/sound/README.OSS	Tue Jun 12 10:56:11 2001
@@ -17,7 +17,7 @@
 document can be still interesting and very helpful.
 
 [ File edited 17.01.1999 - Riccardo Facchetti ]
-[ Edited miroSOUND section 17.09.2000 - Robert Siemer ]
+[ Edited miroSOUND section 19.04.2001 - Robert Siemer ]
 
 OSS/Free version 3.8 release notes
 ----------------------------------
@@ -1327,7 +1327,7 @@
 ---------
 
 The miroSOUND PCM1-pro, PCM12 and PCM20 radio has been used
-successfully. This card is based on the MAD16, OPL4, and CS4231A chips
+successfully. These cards are based on the MAD16, OPL4, and CS4231A chips
 and everything said in the section about MAD16 cards applies here,
 too. The only major difference between the PCMxx and other MAD16 cards
 is that instead of the mixer in the CS4231 codec a separate mixer
@@ -1337,8 +1337,8 @@
 you compile this ACI driver together with the normal MAD16 support
 when you use a miroSOUND PCMxx card. The ACI mixer is controlled by
 /dev/mixer and the CS4231 mixer by /dev/mixer1 (depends on load
-time). Only in special cases you want to change something on the CS4231
-mixer.
+time). Only in special cases you want to change something regularly on
+the CS4231 mixer.
 
 The miroSOUND PCM12 and PCM20 radio is capable of full duplex
 operation (simultaneous PCM replay and recording), which allows you to
@@ -1354,10 +1354,9 @@
 miropcm20.o module. Also the 7-band equalizer is integrated
 (limited by the OSS-design). Developement has started and maybe
 finished for the RDS decoder on this card, too. You will be able to
-read radio text, the program service name, program type and
+read RadioText, the Programme Service name, Programme TYpe and
 others. Even the v4l radio module benefits from it with a refined
-strength value. See aci.c, radio-miropcm20.c and rds-miropcm20.c for
-more details.
+strength value. See aci.[ch] and miropcm20*.[ch] for more details.
 
 The following configuration parameters have worked fine for the PCM12
 in Markus Kuhn's system, many other configurations might work, too:
diff -u --recursive --new-file v2.4.5/linux/Documentation/usb/se401.txt linux/Documentation/usb/se401.txt
--- v2.4.5/linux/Documentation/usb/se401.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/usb/se401.txt	Wed Jun 27 13:59:32 2001
@@ -0,0 +1,54 @@
+Linux driver for SE401 based USB cameras
+
+Copyright, 2001, Jeroen Vreeken
+
+
+INTRODUCTION:
+
+The SE401 chip is the used in low-cost usb webcams.
+It is produced by Endpoints Inc. (www.endpoints.com).
+It interfaces directly to a cmos image sensor and USB. The only other major
+part in a se401 based camera is a dram chip.
+
+The following cameras are known to work with this driver:
+
+Aox se401 (non-branded) cameras
+Philips PVCV665 USB VGA webcam 'Vesta Fun'
+Kensington VideoCAM PC Camera Model 67014
+Kensington VideoCAM PC Camera Model 67015
+Kensington VideoCAM PC Camera Model 67016
+Kensington VideoCAM PC Camera Model 67017
+
+
+WHAT YOU NEED:
+
+-	USB support
+-	VIDEO4LINUX support
+
+More information about USB support for linux can be found at:
+http://www.linux-usb.org
+
+
+MODULE OPTIONS:
+
+When the driver is compiled as a module you can also use the 'flickerless'
+option. With it exposure is limited to values that do not interfere with the
+net frequency. Valid options for this option are 0, 50 and 60. (0=disable,
+50=50hz, 60=60hz)
+
+
+KNOWN PROBLEMS:
+
+The driver works fine with the usb-ohci and uhci host controller drivers,
+the default settings also work with usb-uhci. But sending more then one bulk
+transfer at a time with usb-uhci doesn't work yet.
+Users of usb-ohci and uhci can safely enlarge SE401_NUMSBUF in se401.h in
+order to increase the throughput (and thus framerate).
+
+
+HELP:
+
+The latest info on this driver can be found at:
+http://www.chello.nl/~j.vreeken/se401/
+And questions to me can be send to:
+pe1rxq@amsat.org
diff -u --recursive --new-file v2.4.5/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- v2.4.5/linux/Documentation/usb/usb-serial.txt	Mon Mar 19 17:21:54 2001
+++ linux/Documentation/usb/usb-serial.txt	Wed Jun 27 13:59:32 2001
@@ -245,6 +245,17 @@
        Edgeport/16 Dual
 
 
+REINER SCT cyberJack pinpad/e-com USB chipcard reader
+   
+  Interface to ISO 7816 compatible contactbased chipcards, e.g. GSM SIMs.
+  
+Current status:
+  This is the kernel part of the driver for this USB card reader.
+  There is also a user part for a CT-API driver available. A site
+  for downloading is TBA. For now, you can request it from the
+  maintainer (linux-usb@sii.li).
+
+
 Generic Serial driver
 
   If your device is not one of the above listed devices, compatible with
diff -u --recursive --new-file v2.4.5/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.5/linux/MAINTAINERS	Sun May 20 12:11:38 2001
+++ linux/MAINTAINERS	Wed Jun 27 13:59:32 2001
@@ -231,7 +231,7 @@
 CIRRUS LOGIC GENERIC FBDEV DRIVER
 P:	Jeff Garzik
 M:	jgarzik@mandrakesoft.com
-L:	linux-fbdev@vuser.vu.union.edu
+L:	linux-fbdev-devel@lists.sourceforge.net
 S:	Odd Fixes
 
 CIRRUS LOGIC CS4280/CS461x SOUNDDRIVER
@@ -712,16 +712,11 @@
 M:	perex@suse.cz
 S:	Maintained
 
-ISDN SUBSYSTEM (general)
-P:	Fritz Elfert
-M:	fritz@isdn4linux.de
-L:	isdn4linux@listserv.isdn4linux.de
-W:	http://www.isdn4linux.de
-S:	Maintained
-
-ISDN SUBSYSTEM (card drivers)
+ISDN SUBSYSTEM
 P:	Karsten Keil
 M:	kkeil@suse.de
+P:	Kai Germaschewski
+M:	kai.germaschewski@gmx.de
 L:	isdn4linux@listserv.isdn4linux.de
 W:	http://www.isdn4linux.de
 S:	Maintained
@@ -764,8 +759,8 @@
 M:	kaos@ocs.com.au
 P:	Michael Elizabeth Chastain
 M:	mec@shout.net
-L:	linux-kbuild@torque.net
-W:	http://www.kernel.org/pub/linux/kernel/projects/kbuild/
+L:	kbuild-devel@lists.sourceforge.net
+W:	http://kbuild.sourceforge.net
 S:	Maintained 
 
 KERNEL NFSD
@@ -789,24 +784,30 @@
 L:	linux-x25@vger.kernel.org
 S:	Maintained
 
+LINUX FOR IBM pSERIES (RS/6000)
+P:	Paul Mackerras
+M:	paulus@au.ibm.com
+W:	http://www.ibm.com/linux/ltc/projects/ppc
+S:	Supported
+
 LINUX FOR POWERPC
-P:	Cort Dougan
-M:	cort@fsmlabs.com
+P:	Paul Mackerras
+M:	paulus@samba.org
 W:	http://www.fsmlabs.com/linuxppcbk.html
-S:	Maintained
+S:	Supported
 
 LINUX FOR POWER MACINTOSH
-P:	Paul Mackerras
-M:	paulus@samba.org
+P:	Benjamin Herrenschmidt
+M:	benh@kernel.crashing.org
 W:	http://www.linuxppc.org/
 L:	linuxppc-dev@lists.linuxppc.org
 S:	Maintained
 
 LOGICAL VOLUME MANAGER
 P:     Heinz Mauelshagen
-M:     linux-LVM@EZ-Darmstadt.Telekom.de
-L:     linux-LVM@msede.com
-W:     http://linux.msede.com/lvm
+M:     mge@sistina.de
+L:     linux-LVM@sistina.com
+W:     http://www.sistina.com/lvm
 S:     Maintained 
 
 M68K
@@ -1087,9 +1088,9 @@
 S:	Maintained
 
 RAGE128 FRAMEBUFFER DISPLAY DRIVER
-P:	Brad Douglas
-M:	brad@neruo.com
-L:	linux-fbdev@vuser.vu.union.edu
+P:	Ani Joshi
+M:	ajoshi@shell.unixbox.com
+L:	linux-fbdev-devel@lists.sourceforge.net
 S:	Maintained
 
 RAYLINK/WEBGEAR 802.11 WIRELESS LAN DRIVER
@@ -1169,7 +1170,7 @@
 S:	Unmaintained
 
 SCSI TAPE DRIVER
-P:	Kai Mdkisara
+P:	Kai Mäkisara
 M:	Kai.Makisara@metla.fi
 L:	linux-scsi@vger.kernel.org
 S:	Maintained
@@ -1194,12 +1195,6 @@
 L:	samba@samba.org
 S:	Maintained
 
-SMP: (except SPARC)
-P:	Linus Torvalds
-M:	torvalds@transmeta.com
-L:	linux-smp@vger.kernel.org
-S:	Maintained
-
 SOFTWARE RAID (Multiple Disks) SUPPORT
 P:	Ingo Molnar
 M:	mingo@redhat.com
@@ -1347,8 +1342,8 @@
 M:	bfennema@falcon.csc.calpoly.edu
 P:	Dave Boynton
 M:	dave@trylinux.com
-L:	linux_udf@hootie.lvld.hp.com
-W:	http://www.trylinux.com/projects/udf/index.html
+L:	linux_udf@hpesjro.fc.hp.com
+W:	http://linux-udf.sourceforge.net
 S:	Maintained
 
 UMSDOS FILESYSTEM
@@ -1473,6 +1468,12 @@
 L:	linux-usb-devel@lists.sourceforge.net
 S:	Maintained
 
+USB SERIAL CYBERJACK PINPAD/E-COM DRIVER
+M:  linux-usb@sii.li
+L:  linux-usb-users@lists.sourceforge.net
+L:  linux-usb-devel@lists.sourceforge.net
+S:  Supported
+
 USB MASS STORAGE DRIVER
 P:	Matthew Dharm
 M:	mdharm-usb@one-eyed-alien.net
@@ -1571,6 +1572,12 @@
 M:	middelin@polyware.nl
 W:	http://www.polyware.nl/~middelin/En/hobbies.html
 W:	http://www.polyware.nl/~middelin/hobbies.html
+S:	Maintained
+
+Bluetooth Subsystem (BlueZ)
+P:	Maxim Krasnyansky
+M:	maxk@qualcomm.com
+W:	http://bluez.sf.net
 S:	Maintained
 
 THE REST
diff -u --recursive --new-file v2.4.5/linux/Makefile linux/Makefile
--- v2.4.5/linux/Makefile	Fri May 25 09:51:33 2001
+++ linux/Makefile	Fri Jun 29 19:42:38 2001
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 5
-EXTRAVERSION =
+SUBLEVEL = 6
+EXTRAVERSION =-pre9
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
@@ -87,7 +87,8 @@
 
 CPPFLAGS := -D__KERNEL__ -I$(HPATH)
 
-CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strict-aliasing
+CFLAGS := $(CPPFLAGS) -Wall -Wstrict-prototypes -Wno-trigraphs -O2 \
+          -fomit-frame-pointer -fno-strict-aliasing
 AFLAGS := -D__ASSEMBLY__ $(CPPFLAGS)
 
 #
@@ -127,6 +128,7 @@
 DRIVERS-m :=
 DRIVERS-  :=
 
+DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o
 DRIVERS-$(CONFIG_PARPORT) += drivers/parport/driver.o
 DRIVERS-y += drivers/char/char.o \
 	drivers/block/block.o \
@@ -155,7 +157,8 @@
 DRIVERS-$(CONFIG_PCI) += drivers/pci/driver.o
 DRIVERS-$(CONFIG_MTD) += drivers/mtd/mtdlink.o
 DRIVERS-$(CONFIG_PCMCIA) += drivers/pcmcia/pcmcia.o
-DRIVERS-$(CONFIG_PCMCIA_NETCARD) += drivers/net/pcmcia/pcmcia_net.o
+DRIVERS-$(CONFIG_NET_PCMCIA) += drivers/net/pcmcia/pcmcia_net.o
+DRIVERS-$(CONFIG_NET_WIRELESS) += drivers/net/wireless/wireless_net.o
 DRIVERS-$(CONFIG_PCMCIA_CHRDEV) += drivers/char/pcmcia/pcmcia_char.o
 DRIVERS-$(CONFIG_DIO) += drivers/dio/dio.a
 DRIVERS-$(CONFIG_SBUS) += drivers/sbus/sbus_all.o
@@ -175,8 +178,8 @@
 DRIVERS-$(CONFIG_IRDA) += drivers/net/irda/irda.o
 DRIVERS-$(CONFIG_I2C) += drivers/i2c/i2c.o
 DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o
-DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o
 DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o
+DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o
 
 DRIVERS := $(DRIVERS-y)
 
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/boot/bootloader.lds linux/arch/alpha/boot/bootloader.lds
--- v2.4.5/linux/arch/alpha/boot/bootloader.lds	Sun Sep  6 10:34:33 1998
+++ linux/arch/alpha/boot/bootloader.lds	Mon Jul  2 14:40:14 2001
@@ -6,7 +6,7 @@
   .text : { *(.text) }
   _etext = .;
   PROVIDE (etext = .);
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .data : { *(.data) CONSTRUCTORS }
   .got : { *(.got) }
   .sdata : { *(.sdata) }
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.4.5/linux/arch/alpha/config.in	Fri May 25 09:55:36 2001
+++ linux/arch/alpha/config.in	Mon Jun 11 19:15:27 2001
@@ -348,6 +348,10 @@
 source drivers/usb/Config.in
 source drivers/input/Config.in
 
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   source net/bluetooth/Config.in
+fi
+
 mainmenu_option next_comment
 comment 'Kernel hacking'
 
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.4.5/linux/arch/alpha/kernel/alpha_ksyms.c	Fri May 25 09:54:50 2001
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Wed Jun 20 11:10:27 2001
@@ -16,6 +16,7 @@
 #include <linux/pci.h>
 #include <linux/tty.h>
 #include <linux/mm.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/hwrpb.h>
@@ -100,6 +101,10 @@
 EXPORT_SYMBOL(__constant_c_memset);
 EXPORT_SYMBOL(copy_page);
 EXPORT_SYMBOL(clear_page);
+
+EXPORT_SYMBOL(__delay);
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(udelay);
 
 EXPORT_SYMBOL(__direct_map_base);
 EXPORT_SYMBOL(__direct_map_size);
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/core_tsunami.c linux/arch/alpha/kernel/core_tsunami.c
--- v2.4.5/linux/arch/alpha/kernel/core_tsunami.c	Thu May 24 15:24:37 2001
+++ linux/arch/alpha/kernel/core_tsunami.c	Mon Jun 11 19:15:27 2001
@@ -11,7 +11,6 @@
 #include <linux/pci.h>
 #include <linux/sched.h>
 #include <linux/init.h>
-#include <linux/bootmem.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -21,6 +20,8 @@
 #include <asm/io.h>
 #include <asm/core_tsunami.h>
 #undef __EXTERN_INLINE
+
+#include <linux/bootmem.h>
 
 #include "proto.h"
 #include "pci_impl.h"
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S
--- v2.4.5/linux/arch/alpha/kernel/entry.S	Thu May 24 15:20:18 2001
+++ linux/arch/alpha/kernel/entry.S	Mon Jun 11 19:15:27 2001
@@ -31,7 +31,7 @@
 #define TASK_STATE		0
 #define TASK_FLAGS		8
 #define TASK_SIGPENDING		16
-#define TASK_ADDR_LIMIT		24	
+#define TASK_ADDR_LIMIT		24
 #define TASK_EXEC_DOMAIN	32
 #define TASK_NEED_RESCHED	40
 #define TASK_PTRACE		48
@@ -576,13 +576,15 @@
 .align 3
 ret_from_sys_call:
 	cmovne	$26,0,$19		/* $19 = 0 => non-restartable */
+#ifdef CONFIG_SMP
 	ldl	$3,TASK_PROCESSOR($8)
-	lda	$4,irq_stat		/* softirq_active */
 	sll	$3,L1_CACHE_SHIFT,$3
+#endif
+	lda	$4,irq_stat
+#ifdef CONFIG_SMP
 	addq	$3,$4,$4
-	ldq	$4,0($4)		/* softirq_active[32] + softirq_mask[32] */
-	sll	$4,32,$3
-	and	$4,$3,$4
+#endif
+	ldq	$4,0($4)		/* __softirq_pending */
 	bne	$4,handle_softirq
 ret_from_softirq:
 	ldq	$0,SP_OFF($30)
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.4.5/linux/arch/alpha/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/alpha/kernel/irq.c	Wed Jun 20 11:10:27 2001
@@ -359,7 +359,9 @@
 static void
 register_irq_proc (unsigned int irq)
 {
+#ifdef CONFIG_SMP
 	struct proc_dir_entry *entry;
+#endif
 	char name [MAX_NAMELEN];
 
 	if (!root_irq_dir || (irq_desc[irq].handler == &no_irq_type))
@@ -389,7 +391,9 @@
 void
 init_irq_proc (void)
 {
+#ifdef CONFIG_SMP
 	struct proc_dir_entry *entry;
+#endif
 	int i;
 
 	/* create /proc/irq */
@@ -512,7 +516,10 @@
 int
 get_irq_list(char *buf)
 {
-	int i, j;
+#ifdef CONFIG_SMP
+	int j;
+#endif
+	int i;
 	struct irqaction * action;
 	char *p = buf;
 
@@ -569,7 +576,7 @@
 
 
 /*
- * do_IRQ handles all normal device IRQ's (the special
+ * handle_irq handles all normal device IRQ's (the special
  * SMP cross-CPU interrupts have their own specific
  * handlers).
  */
@@ -632,7 +639,7 @@
 	/*
 	 * Edge triggered interrupts need to remember pending events.
 	 * This applies to any hw interrupts that allow a second
-	 * instance of the same irq to arrive while we are in do_IRQ
+	 * instance of the same irq to arrive while we are in handle_irq
 	 * or in the handler. But the code here only handles the _second_
 	 * instance of the irq, not the third or fourth. So it is mostly
 	 * useful for irq hardware that does not mask cleanly in an
@@ -656,6 +663,9 @@
 	 */
 	desc->handler->end(irq);
 	spin_unlock(&desc->lock);
+
+	if (softirq_pending(cpu))
+		do_softirq();
 }
 
 /*
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c
--- v2.4.5/linux/arch/alpha/kernel/irq_alpha.c	Tue Feb 13 14:13:43 2001
+++ linux/arch/alpha/kernel/irq_alpha.c	Mon Jul  2 14:03:04 2001
@@ -18,6 +18,8 @@
 unsigned long __irq_attempt[NR_IRQS];
 #endif
 
+extern unsigned long irq_err_count;
+
 /* Hack minimum IPL during interrupt processing for broken hardware.  */
 #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
 int __min_ipl;
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.4.5/linux/arch/alpha/kernel/osf_sys.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/alpha/kernel/osf_sys.c	Tue Jun 12 10:26:14 2001
@@ -44,7 +44,6 @@
 
 extern int do_pipe(int *);
 
-extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
 extern asmlinkage unsigned long sys_brk(unsigned long);
 
 /*
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.4.5/linux/arch/alpha/kernel/process.c	Thu May 24 15:20:18 2001
+++ linux/arch/alpha/kernel/process.c	Wed Jun 20 11:10:27 2001
@@ -28,6 +28,7 @@
 #include <linux/mman.h>
 #include <linux/elfcore.h>
 #include <linux/reboot.h>
+#include <linux/tty.h>
 #include <linux/console.h>
 
 #include <asm/reg.h>
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.4.5/linux/arch/alpha/kernel/smp.c	Thu May 24 15:24:37 2001
+++ linux/arch/alpha/kernel/smp.c	Mon Jun 11 19:15:27 2001
@@ -682,6 +682,9 @@
 
 		data->prof_counter = data->prof_multiplier;
 		irq_exit(cpu, RTC_IRQ);
+
+		if (softirq_pending(cpu))
+			do_softirq();
 	}
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_alcor.c linux/arch/alpha/kernel/sys_alcor.c
--- v2.4.5/linux/arch/alpha/kernel/sys_alcor.c	Fri Oct 27 10:55:01 2000
+++ linux/arch/alpha/kernel/sys_alcor.c	Wed Jun 27 16:18:13 2001
@@ -15,6 +15,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/reboot.h>
 
 #include <asm/ptrace.h>
 #include <asm/system.h>
@@ -219,11 +220,21 @@
 static void
 alcor_kill_arch(int mode)
 {
-	/* Who said DEC engineer's have no sense of humor? ;-)  */
-	if (alpha_using_srm) {
-		*(vuip) GRU_RESET = 0x0000dead;
-		mb();
+	switch(mode) {
+	case LINUX_REBOOT_CMD_RESTART:
+		/* Who said DEC engineer's have no sense of humor? ;-)  */
+		if (alpha_using_srm) {
+			*(vuip) GRU_RESET = 0x0000dead;
+			mb();
+		}
+		break;
+	case LINUX_REBOOT_CMD_HALT:
+		break;
+	case LINUX_REBOOT_CMD_POWER_OFF:
+		break;
 	}
+
+	halt();
 }
 
 
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_dp264.c linux/arch/alpha/kernel/sys_dp264.c
--- v2.4.5/linux/arch/alpha/kernel/sys_dp264.c	Fri May 25 09:54:50 2001
+++ linux/arch/alpha/kernel/sys_dp264.c	Mon Jun 11 19:15:27 2001
@@ -16,18 +16,15 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 
-#define __EXTERN_INLINE inline
-#include <asm/io.h>
-#include <asm/core_tsunami.h>
-#undef  __EXTERN_INLINE
-
 #include <asm/ptrace.h>
 #include <asm/system.h>
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/bitops.h>
 #include <asm/mmu_context.h>
+#include <asm/io.h>
 #include <asm/pgtable.h>
+#include <asm/core_tsunami.h>
 #include <asm/hwrpb.h>
 
 #include "proto.h"
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_rawhide.c linux/arch/alpha/kernel/sys_rawhide.c
--- v2.4.5/linux/arch/alpha/kernel/sys_rawhide.c	Fri Mar  2 11:12:07 2001
+++ linux/arch/alpha/kernel/sys_rawhide.c	Mon Jun 11 19:15:27 2001
@@ -59,10 +59,11 @@
 	irq -= 16;
 	hose = irq / 24;
 	irq -= hose * 24;
+	mask = 1 << irq;
 
 	spin_lock(&rawhide_irq_lock);
-	mask = cached_irq_masks[hose] |= 1 << irq;
-	mask |= hose_irq_masks[hose];
+	mask |= cached_irq_masks[hose];
+	cached_irq_masks[hose] = mask;
 	rawhide_update_irq_hw(hose, mask);
 	spin_unlock(&rawhide_irq_lock);
 }
@@ -75,14 +76,37 @@
 	irq -= 16;
 	hose = irq / 24;
 	irq -= hose * 24;
+	mask = ~(1 << irq) | hose_irq_masks[hose];
 
 	spin_lock(&rawhide_irq_lock);
-	mask = cached_irq_masks[hose] &= ~(1 << irq);
-	mask |= hose_irq_masks[hose];
+	mask &= cached_irq_masks[hose];
+	cached_irq_masks[hose] = mask;
 	rawhide_update_irq_hw(hose, mask);
 	spin_unlock(&rawhide_irq_lock);
 }
 
+static void
+rawhide_mask_and_ack_irq(unsigned int irq)
+{
+	unsigned int mask, mask1, hose;
+
+	irq -= 16;
+	hose = irq / 24;
+	irq -= hose * 24;
+	mask1 = 1 << irq;
+	mask = ~mask1 | hose_irq_masks[hose];
+
+	spin_lock(&rawhide_irq_lock);
+
+	mask &= cached_irq_masks[hose];
+	cached_irq_masks[hose] = mask;
+	rawhide_update_irq_hw(hose, mask);
+
+	/* Clear the interrupt.  */
+	*(vuip)MCPCIA_INT_REQ(MCPCIA_HOSE2MID(hose)) = mask1;
+
+	spin_unlock(&rawhide_irq_lock);
+}
 
 static unsigned int
 rawhide_startup_irq(unsigned int irq)
@@ -104,7 +128,7 @@
 	shutdown:	rawhide_disable_irq,
 	enable:		rawhide_enable_irq,
 	disable:	rawhide_disable_irq,
-	ack:		rawhide_disable_irq,
+	ack:		rawhide_mask_and_ack_irq,
 	end:		rawhide_end_irq,
 };
 
@@ -145,8 +169,12 @@
 	mcpcia_init_hoses();
 
 	for (hose = hose_head; hose; hose = hose->next) {
-		int h = hose->index;
-		rawhide_update_irq_hw(h, hose_irq_masks[h]);
+		unsigned int h = hose->index;
+		unsigned int mask = hose_irq_masks[h];
+
+		cached_irq_masks[h] = mask;
+		*(vuip)MCPCIA_INT_MASK0(MCPCIA_HOSE2MID(h)) = mask;
+		*(vuip)MCPCIA_INT_MASK1(MCPCIA_HOSE2MID(h)) = 0;
 	}
 
 	for (i = 16; i < 128; ++i) {
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_sable.c linux/arch/alpha/kernel/sys_sable.c
--- v2.4.5/linux/arch/alpha/kernel/sys_sable.c	Fri Oct 27 10:55:01 2000
+++ linux/arch/alpha/kernel/sys_sable.c	Tue Jun 12 11:44:59 2001
@@ -96,7 +96,7 @@
 static inline void
 sable_update_irq_hw(unsigned long bit, unsigned long mask)
 {
-	int port = 0x536;
+	int port = 0x537;
 
 	if (bit >= 16) {
 		port = 0x53d;
@@ -121,7 +121,7 @@
 	} else if (bit >= 8) {
 		port = 0x53a;
 		val1 = 0xE0 | (bit - 8);
-		val2 = 0xE0 | 2;
+		val2 = 0xE0 | 3;
 	} else {
 		port = 0x536;
 		val1 = 0xE0 | (bit - 0);
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c
--- v2.4.5/linux/arch/alpha/kernel/sys_sio.c	Fri Oct 27 10:55:01 2000
+++ linux/arch/alpha/kernel/sys_sio.c	Wed Jun 20 11:10:27 2001
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/tty.h>
 
 #include <asm/compiler.h>
 #include <asm/ptrace.h>
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile
--- v2.4.5/linux/arch/alpha/lib/Makefile	Thu Feb  8 12:56:29 2001
+++ linux/arch/alpha/lib/Makefile	Wed Jun 20 11:10:27 2001
@@ -21,6 +21,7 @@
 endif
 
 OBJS =	__divqu.o __remqu.o __divlu.o __remlu.o \
+	udelay.o \
 	$(ev6)memset.o \
 	$(ev6)memcpy.o \
 	memmove.o \
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/lib/udelay.c linux/arch/alpha/lib/udelay.c
--- v2.4.5/linux/arch/alpha/lib/udelay.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/lib/udelay.c	Wed Jun 20 11:10:27 2001
@@ -0,0 +1,47 @@
+#include <linux/config.h>
+#include <linux/sched.h> /* for udelay's use of smp_processor_id */
+#include <asm/param.h>
+#include <asm/smp.h>
+#include <linux/delay.h>
+
+/*
+ * Copyright (C) 1993, 2000 Linus Torvalds
+ *
+ * Delay routines, using a pre-computed "loops_per_jiffy" value.
+ */
+
+/*
+ * Use only for very small delays (< 1 msec). 
+ *
+ * The active part of our cycle counter is only 32-bits wide, and
+ * we're treating the difference between two marks as signed.  On
+ * a 1GHz box, that's about 2 seconds.
+ */
+
+void __delay(int loops)
+{
+	int tmp;
+	__asm__ __volatile__(
+		"	rpcc %0\n"
+		"	addl %1,%0,%1\n"
+		"1:	rpcc %0\n"
+		"	subl %1,%0,%0\n"
+		"	bgt %0,1b"
+		: "=&r" (tmp), "=r" (loops) : "1"(loops));
+}
+
+void __udelay(unsigned long usecs, unsigned long lpj)
+{
+	usecs *= (((unsigned long)HZ << 32) / 1000000) * lpj;
+	__delay((long)usecs >> 32);
+}
+
+void udelay(unsigned long usecs)
+{
+#ifdef CONFIG_SMP
+	__udelay(usecs, cpu_data[smp_processor_id()].loops_per_jiffy);
+#else
+	__udelay(usecs, loops_per_jiffy);
+#endif
+}
+
diff -u --recursive --new-file v2.4.5/linux/arch/alpha/vmlinux.lds.in linux/arch/alpha/vmlinux.lds.in
--- v2.4.5/linux/arch/alpha/vmlinux.lds.in	Mon Jun 26 11:26:56 2000
+++ linux/arch/alpha/vmlinux.lds.in	Mon Jul  2 14:40:14 2001
@@ -53,7 +53,7 @@
   /* Global data */
   _data = .;
   .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .data : { *(.data) CONSTRUCTORS }
   .got : { *(.got) }
   .sdata : { *(.sdata) }
diff -u --recursive --new-file v2.4.5/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.4.5/linux/arch/arm/Makefile	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/Makefile	Wed Jun 27 14:12:04 2001
@@ -26,7 +26,7 @@
 apcs-$(CONFIG_CPU_26)		:=-mcpu=arm3 -Os
 
 arch-y				:=
-arch-$(CONFIG_CPU_32v3)		:=-march=armv3m
+arch-$(CONFIG_CPU_32v3)		:=-march=armv3
 arch-$(CONFIG_CPU_32v4)		:=-march=armv4
 arch-$(CONFIG_CPU_32v5)		:=-march=armv5
 
@@ -123,6 +123,10 @@
 MACHINE		 = clps711x
 endif
 
+ifeq ($(CONFIG_ARCH_ANAKIN),y)
+MACHINE		 = anakin
+endif
+
 export	LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS
 
 # Only set INCDIR if its not already defined above
@@ -156,7 +160,7 @@
 LIBS		:= arch/arm/fastfpe/fast-math-emu.o $(LIBS)
 endif
 
-ifeq ($(CONFIG_ARCH_CLPS7500),y)
+ifeq ($(findstring y,$(CONFIG_ARCH_CLPS7500) $(CONFIG_ARCH_L7200)),y)
 SUBDIRS		+= drivers/acorn/char
 DRIVERS		+= drivers/acorn/char/acorn-char.o
 endif
@@ -237,8 +241,8 @@
 	@( \
 	CFG=$(@:_config=); \
 	if [ -f arch/arm/def-configs/$$CFG ]; then \
-	  $(RM) arch/arm/defconfig; \
-	  cp arch/arm/def-configs/$$CFG arch/arm/defconfig; \
+	  [ -f .config ] && $(MV) .config .config.old; \
+	  cp arch/arm/def-configs/$$CFG .config; \
 	  echo "*** Default configuration for $$CFG installed"; \
 	  echo "*** Next, you may run 'make oldconfig'"; \
 	else \
diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile
--- v2.4.5/linux/arch/arm/boot/Makefile	Thu Apr 12 12:03:50 2001
+++ linux/arch/arm/boot/Makefile	Wed Jun 27 14:12:04 2001
@@ -90,9 +90,17 @@
 ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
   ZTEXTADDR	 = 0xC0200000
 endif
+ifeq ($(CONFIG_SA1100_YOPY),y)
+  ZTEXTADDR      = 0x00080000
+  ZBSSADDR       = 0xc0200000
+endif
 ifeq ($(CONFIG_SA1111),y)
   ZRELADDR	 = 0xc0208000
 endif
+endif
+
+ifeq ($(CONFIG_ARCH_ANAKIN),y)
+ZTEXTADDR	 = 0x20008000
 endif
 
 #
diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- v2.4.5/linux/arch/arm/boot/compressed/Makefile	Thu Apr 12 12:03:50 2001
+++ linux/arch/arm/boot/compressed/Makefile	Wed Jun 27 14:12:04 2001
@@ -30,7 +30,7 @@
 endif
 
 ifeq ($(CONFIG_ARCH_INTEGRATOR),y)
-OBJS		+= head-netwinder.o
+OBJS		+= head-integrator.o
 endif
 
 ifeq ($(CONFIG_ARCH_FTVPCI),y)
diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/head-integrator.S linux/arch/arm/boot/compressed/head-integrator.S
--- v2.4.5/linux/arch/arm/boot/compressed/head-integrator.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/boot/compressed/head-integrator.S	Wed Jun 27 14:12:04 2001
@@ -0,0 +1,4 @@
+#include <asm/mach-types.h>
+
+		.section	".start", #alloc, #execinstr
+		mov	r7, #MACH_TYPE_INTEGRATOR
diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S
--- v2.4.5/linux/arch/arm/boot/compressed/head.S	Thu Apr 12 12:03:50 2001
+++ linux/arch/arm/boot/compressed/head.S	Wed Jun 27 14:12:04 2001
@@ -12,7 +12,39 @@
 
 /*
  * Debugging stuff
+ *
+ * Note that these macros must not contain any code which is not
+ * 100% relocatable.  Any attempt to do so will result in a crash.
+ * Please select one of the following when turning on debugging.
  */
+#ifdef DEBUG
+#if 0 /* DC21285-type */
+		.macro	loadsp,	rb
+		mov	\rb, #0x7c000000
+		.endm
+		.macro	writeb,	rb
+		strb	\rb, [r3, #0x3f8]
+		.endm
+#elif 0 /* RiscPC-type */
+		.macro	loadsp,	rb
+		mov	\rb, #0x03000000
+		orr	\rb, \rb, #0x00010000
+		.endm
+		.macro	writeb,	rb
+		strb	\rb, [r3, #0x3f8 << 2]
+		.endm
+#elif 0 /* integrator-type */
+		.macro	loadsp, rb
+		mov	\rb, #0x16000000
+		.endm
+		.macro	writeb, rb
+		strb	\rb, [r3, #0]
+		.endm
+#else
+#error no serial architecture defined
+#endif
+#endif
+
 		.macro	kputc,val
 		mov	r0, \val
 		bl	putc
@@ -27,53 +59,31 @@
 		.macro	debug_reloc_start
 #ifdef DEBUG
 		kputc	#'\n'
-		kphex	r6, 8
+		kphex	r6, 8		/* processor id */
 		kputc	#':'
-		kphex	r5, 8
+		kphex	r7, 8		/* architecture id */
+		kputc	#':'
+		mrc	p15, 0, r0, c1, c0
+		kphex	r0, 8		/* control reg
+		kputc	#'\n'
+		kphex	r5, 8		/* decompressed kernel start */
 		kputc	#'-'
-		kphex	r8, 8
+		kphex	r8, 8		/* decompressed kernel end  */
 		kputc	#'>'
-		kphex	r4, 8
+		kphex	r4, 8		/* kernel execution address */
 		kputc	#'\n'
 #endif
 		.endm
 
 		.macro	debug_reloc_end
 #ifdef DEBUG
-		mov	r8, r0
-		kphex	r5, 8
-		kputc	#'-'
-		kphex	r8, 8
+		kphex	r5, 8		/* end of kernel */
 		kputc	#'\n'
 		mov	r0, r4
-		bl	memdump
+		bl	memdump		/* dump 256 bytes at start of kernel */
 #endif
 		.endm
 
-/*
- * Note that these macros must not contain any code which is not
- * 100% relocatable.  Any attempt to do so will result in a crash.
- */
-#if 0
-		.macro	loadsp,	rb
-		mov	\rb, #0x7c000000
-		.endm
-
-		.macro	writeb,	rb
-		strb	\rb, [r3, #0x3f8]
-		.endm
-#else
-		.macro	loadsp,	rb
-		mov	\rb, #0x03000000
-		orr	\rb, \rb, #0x00010000
-		.endm
-
-		.macro	writeb,	rb
-		strb	\rb, [r3, #0x3f8 << 2]
-		.endm
-#endif
-
-
 		.section ".start", #alloc, #execinstr
 /*
  * sort out different calling conventions
@@ -91,14 +101,18 @@
 		.word	_edata			@ zImage end address
 1:		mov	r7, r1			@ save architecture ID
 		mov	r8, #0			@ save r0
-#ifdef CONFIG_ANGELBOOT
+
 		/*
 		 * Booting from Angel - need to enter SVC mode and disable
-		 * FIQs/IRQs (numeric definitions from angel arm.h source)
+		 * FIQs/IRQs (numeric definitions from angel arm.h source).
+		 * We only do this if we were in user mode on entry.
 		 */
+		mrs	r0, cpsr		@ get current mode
+		tst	r0, #3			@ not user?
+		bne	not_angel
 		mov	r0, #0x17		@ angel_SWIreason_EnterSVC
 		swi	0x123456		@ angel_SWI_ARM
-		mrs	r0, cpsr		@ turn off interrupts to
+not_angel:	mrs	r0, cpsr		@ turn off interrupts to
 		orr	r0, r0, #0xc0		@ prevent angel from running
 		msr	cpsr_c, r0
 
@@ -106,7 +120,7 @@
 		 * Note that some cache flushing and other stuff may
 		 * be needed here - is there an Angel SWI call for this?
 		 */
-#endif
+
 		/*
 		 * some architecture specific code can be inserted
 		 * by the linker here, but it should preserve r7 and r8.
@@ -300,30 +314,46 @@
 		.size	proc_sa1110_type, . - proc_sa1110_type
 
 /*
- * Turn off StrongARM cache and MMU.  It is safe to
- * leave the I-cache on.
+ * Turn off the Cache and MMU.  ARMv3 does not support
+ * reading the control register, but ARMv4 does.
  *
- * On entry,
- *  r6 = processor ID
- * On exit,
- *  r0, r1 corrupted
- * This routine must preserve:
- *  r4, r6, r7
+ * On entry,  r6 = processor ID
+ * On exit,   r0, r1 corrupted
+ * This routine must preserve: r4, r6, r7
  */
 		.align	5
-cache_off:	ldr	r1, proc_sa110_type
-		eor	r1, r1, r6
-		movs	r1, r1, lsr #5		@ catch SA110 and SA1100
-		beq	1f
-		ldr	r1, proc_sa1110_type
-		eor	r1, r1, r6
-		movs	r1, r1, lsr #4
-		movne	pc, lr
-1:
+cache_off:
+#ifdef CONFIG_CPU_ARM610
+		eor	r1, r6, #0x41000000
+		eor	r1, r1, #0x00560000
+		bic	r1, r1, #0x0000001f
+		teq	r1, #0x00000600
+		mov	r0, #0x00000060		@ ARM6 control reg.
+		beq	__armv3_cache_off
+#endif
+#ifdef CONFIG_CPU_ARM710
+		eor	r1, r6, #0x41000000
+		bic	r1, r1, #0x00070000
+		bic	r1, r1, #0x000000ff
+		teq	r1, #0x00007000		@ ARM7
+		teqne	r1, #0x00007100		@ ARM710
+		mov	r0, #0x00000070		@ ARM7 control reg.
+		beq	__armv3_cache_off
+#endif
 		mrc	p15, 0, r0, c1, c0
 		bic	r0, r0, #0x000d
-		mcr	p15, 0, r0, c1, c0
-		mov	pc, lr		
+		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c7	@ invalidate whole cache v4
+		mcr	p15, 0, r0, c8, c7	@ invalidate whole TLB v4
+		mov	pc, lr
+
+__armv3_cache_off:
+		mcr	p15, 0, r0, c1, c0	@ turn MMU and cache off
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c0	@ invalidate whole cache v3
+		mcr	p15, 0, r0, c5, c0	@ invalidate whole TLB v3
+		mov	pc, lr
 
 /*
  * Clean and flush the cache to maintain consistency.
@@ -401,13 +431,10 @@
 
 memdump:	mov	r12, r0
 		mov	r10, lr
-		mov	r1, #8
-		bl	phex
-		mov	r0, #'\n'
-		bl	putc
 		mov	r11, #0
 2:		mov	r0, r11, lsl #2
-		mov	r1, #4
+		add	r0, r0, r12
+		mov	r1, #8
 		bl	phex
 		mov	r0, #':'
 		bl	putc
diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/setup-sa1100.S linux/arch/arm/boot/compressed/setup-sa1100.S
--- v2.4.5/linux/arch/arm/boot/compressed/setup-sa1100.S	Thu Apr 12 12:03:50 2001
+++ linux/arch/arm/boot/compressed/setup-sa1100.S	Wed Jun 27 14:12:04 2001
@@ -16,16 +16,16 @@
 		.text
 
 GPIO_BASE:	.long	0x90040000
-#define GPLR	0x00
-#define GPDR	0x04
-#define GPSR	0x08
-#define GAFR	0x1c
+#define GPLR		0x00
+#define GPDR		0x04
+#define GPSR		0x08
+#define GAFR		0x1c
 
 PPC_BASE:	.long	0x90060000
-#define PPAR	0x08
+#define PPAR		0x08
 
 IC_BASE:	.long	0x90050000
-#define ICMR	0x04
+#define ICMR		0x04
 
 UART1_BASE:	.long	0x80010000
 UART3_BASE:	.long	0x80050000
@@ -95,7 +95,11 @@
 		@ Initialize UART (if bootloader has not done it yet)...
 		teq	r3, #MACH_TYPE_BRUTUS
 		teqne	r3, #MACH_TYPE_ASSABET
+		teqne   r3, #MACH_TYPE_ITSY
+		teqne   r3, #MACH_TYPE_OMNIMETER
+		teqne   r3, #MACH_TYPE_JORNADA720
 		teqne	r3, #MACH_TYPE_GRAPHICSCLIENT
+		teqne	r3, #MACH_TYPE_FLEXANET
 		bne	skip_uart
 
 		@ UART3 if Assabet is used with Neponset
diff -u --recursive --new-file v2.4.5/linux/arch/arm/boot/compressed/vmlinux.lds.in linux/arch/arm/boot/compressed/vmlinux.lds.in
--- v2.4.5/linux/arch/arm/boot/compressed/vmlinux.lds.in	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/boot/compressed/vmlinux.lds.in	Mon Jul  2 14:40:14 2001
@@ -24,6 +24,7 @@
     *(.fixup)
     *(.gnu.warning)
     *(.rodata)
+    *(.rodata.*)
     *(.glue_7)
     *(.glue_7t)
     input_data = .;
diff -u --recursive --new-file v2.4.5/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.4.5/linux/arch/arm/config.in	Tue Apr 17 17:19:24 2001
+++ linux/arch/arm/config.in	Mon Jun 11 19:15:27 2001
@@ -482,6 +482,9 @@
 
 source drivers/usb/Config.in
 
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   source net/bluetooth/Config.in
+fi
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S
--- v2.4.5/linux/arch/arm/kernel/calls.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/calls.S	Wed Jun 27 14:12:04 2001
@@ -13,6 +13,7 @@
 #define NR_syscalls 256
 #else
 
+__syscall_start:
 /* 0 */		.long	SYMBOL_NAME(sys_ni_syscall)
 		.long	SYMBOL_NAME(sys_exit)
 		.long	SYMBOL_NAME(sys_fork_wrapper)
@@ -176,7 +177,7 @@
 /* 160 */	.long	SYMBOL_NAME(sys_sched_get_priority_min)
 		.long	SYMBOL_NAME(sys_sched_rr_get_interval)
 		.long	SYMBOL_NAME(sys_nanosleep)
-		.long	SYMBOL_NAME(sys_mremap)
+		.long	SYMBOL_NAME(sys_arm_mremap)
 		.long	SYMBOL_NAME(sys_setresuid16)
 /* 165 */	.long	SYMBOL_NAME(sys_getresuid16)
 		.long	SYMBOL_NAME(sys_ni_syscall)
@@ -231,8 +232,13 @@
 /* 215 */	.long	SYMBOL_NAME(sys_setfsuid)
 		.long	SYMBOL_NAME(sys_setfsgid)
 		.long	SYMBOL_NAME(sys_getdents64)
+		.long	SYMBOL_NAME(sys_pivot_root)
+		.long	SYMBOL_NAME(sys_mincore)
+/* 220 */	.long	SYMBOL_NAME(sys_madvise)
+		.long	SYMBOL_NAME(sys_fcntl64)
+__syscall_end:
 
-		.rept	NR_syscalls-217
+		.rept	NR_syscalls - (__syscall_end - __syscall_start) / 4
 			.long	SYMBOL_NAME(sys_ni_syscall)
 		.endr
 #endif
diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- v2.4.5/linux/arch/arm/kernel/ecard.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/kernel/ecard.c	Wed Jun 27 14:12:04 2001
@@ -1,7 +1,7 @@
 /*
  *  linux/arch/arm/kernel/ecard.c
  *
- *  Copyright 1995-1998 Russell King
+ *  Copyright 1995-2001 Russell King
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -26,7 +26,6 @@
  *  17-Apr-1999	RMK	Support for EASI Type C cycles.
  */
 #define ECARD_C
-#define __KERNEL_SYSCALLS__
 
 #include <linux/config.h>
 #include <linux/module.h>
@@ -34,6 +33,7 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
+#include <linux/reboot.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/proc_fs.h>
@@ -382,12 +382,12 @@
  * We ignore all calls, unless it is a SYS_RESTART call - power down/halts
  * will be followed by a SYS_RESTART if ctrl-alt-del is pressed again.
  */
-static void ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
+static int ecard_reboot(struct notifier_block *me, unsigned long val, void *v)
 {
 	struct ecard_request req;
 
 	if (val != SYS_RESTART)
-		return;
+		return 0;
 
 	/*
 	 * Disable the expansion card interrupt
@@ -414,6 +414,7 @@
 	have_expmask = ~0;
 	__raw_writeb(have_expmask, EXPMASK_ENABLE);
 #endif
+	return 0;
 }
 
 static struct notifier_block ecard_reboot_notifier = {
diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.4.5/linux/arch/arm/kernel/entry-armv.S	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/kernel/entry-armv.S	Wed Jun 27 14:12:04 2001
@@ -1179,7 +1179,6 @@
 		stmfd	sp!, {r4 - r6, lr}
 
 		adr	r1, .LCvectors			@ set up the vectors
-		mov	r0, #0
 		ldmia	r1, {r1, r2, r3, r4, r5, r6, ip, lr}
 		stmia	r0, {r1, r2, r3, r4, r5, r6, ip, lr}
 
diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c
--- v2.4.5/linux/arch/arm/kernel/fiq.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/kernel/fiq.c	Wed Jun 27 14:12:04 2001
@@ -48,7 +48,7 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 
-#define FIQ_VECTOR 0x1c
+#define FIQ_VECTOR (vectors_base() + 0x1c)
 
 static unsigned long no_fiq_insn;
 
diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.4.5/linux/arch/arm/kernel/sys_arm.c	Mon Mar 19 12:35:10 2001
+++ linux/arch/arm/kernel/sys_arm.c	Wed Jun 27 14:12:04 2001
@@ -55,10 +55,19 @@
 	unsigned long prot, unsigned long flags,
 	unsigned long fd, unsigned long pgoff)
 {
-	int error = -EBADF;
+	int error = -EINVAL;
 	struct file * file = NULL;
 
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+	/*
+	 * If we are doing a fixed mapping, and address < PAGE_SIZE,
+	 * then deny it.
+	 */
+	if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0)
+		goto out;
+
+	error = -EBADF;
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
@@ -99,6 +108,29 @@
 	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
 out:
 	return error;
+}
+
+asmlinkage unsigned long
+sys_arm_mremap(unsigned long addr, unsigned long old_len,
+	       unsigned long new_len, unsigned long flags,
+	       unsigned long new_addr)
+{
+	unsigned long ret = -EINVAL;
+
+	/*
+	 * If we are doing a fixed mapping, and address < PAGE_SIZE,
+	 * then deny it.
+	 */
+	if (flags & MREMAP_FIXED && new_addr < PAGE_SIZE &&
+	    vectors_base() == 0)
+		goto out;
+
+	down_write(&current->mm->mmap_sem);
+	ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+	up_write(&current->mm->mmap_sem);
+
+out:
+	return ret;
 }
 
 /*
diff -u --recursive --new-file v2.4.5/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.4.5/linux/arch/arm/kernel/traps.c	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/kernel/traps.c	Wed Jun 27 14:12:04 2001
@@ -20,6 +20,7 @@
 #include <linux/mm.h>
 #include <linux/spinlock.h>
 #include <linux/ptrace.h>
+#include <linux/elf.h>
 #include <linux/init.h>
 
 #include <asm/atomic.h>
@@ -27,6 +28,7 @@
 #include <asm/pgtable.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 #include "ptrace.h"
 
@@ -143,12 +145,24 @@
 		c_backtrace(fp, processor_mode(regs));
 }
 
+/*
+ * This is called from SysRq-T (show_task) to display the current
+ * call trace for each process.  Very useful.
+ */
+void show_trace_task(struct task_struct *tsk)
+{
+	if (tsk != current) {
+		unsigned int fp = tsk->thread.save->fp;
+		c_backtrace(fp, 0x10);
+	}
+}
+
 spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * This function is protected against re-entrancy.
  */
-void die(const char *str, struct pt_regs *regs, int err)
+NORET_TYPE void die(const char *str, struct pt_regs *regs, int err)
 {
 	struct task_struct *tsk = current;
 
@@ -173,9 +187,9 @@
 		fs = get_fs();
 		set_fs(KERNEL_DS);
 
-		dump_instr(regs);
 		dump_stack(tsk, (unsigned long)(regs + 1));
 		dump_backtrace(regs, tsk);
+		dump_instr(regs);
 
 		set_fs(fs);
 	}
@@ -448,9 +462,12 @@
 
 void __init trap_init(void)
 {
-	extern void __trap_init(void);
+	extern void __trap_init(void *);
 
-	__trap_init();
+	__trap_init((void *)vectors_base());
+	if (vectors_base() != 0)
+		printk("Relocating machine vectors to 0x%08x\n",
+			vectors_base());
 #ifdef CONFIG_CPU_32
 	modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
 #endif
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mach-ebsa110/arch.c linux/arch/arm/mach-ebsa110/arch.c
--- v2.4.5/linux/arch/arm/mach-ebsa110/arch.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mach-ebsa110/arch.c	Wed Jun 27 14:12:04 2001
@@ -1,10 +1,7 @@
 /*
  *  linux/arch/arm/mach-ebsa110/arch.c
  *
- *  Architecture specific fixups.  This is where any
- *  parameters in the params struct are fixed up, or
- *  any additional architecture specific information
- *  is pulled from the params struct.
+ *  Architecture specific fixups.
  */
 #include <linux/tty.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mach-ebsa110/hardware.h linux/arch/arm/mach-ebsa110/hardware.h
--- v2.4.5/linux/arch/arm/mach-ebsa110/hardware.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/mach-ebsa110/hardware.h	Wed Jun 27 14:12:04 2001
@@ -0,0 +1,16 @@
+/*
+ *  linux/arch/arm/mach-ebsa110/hardware.h
+ *
+ *  Copyright (C) 2001 Russell King
+ *
+ *  Local hardware definitions.
+ */
+#ifndef HARDWARE_H
+#define HARDWARE_H
+
+#define IRQ_MASK		0xfe000000	/* read */
+#define IRQ_MSET		0xfe000000	/* write */
+#define IRQ_STAT		0xff000000	/* read */
+#define IRQ_MCLR		0xff000000	/* write */
+
+#endif
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mach-ebsa110/io.c linux/arch/arm/mach-ebsa110/io.c
--- v2.4.5/linux/arch/arm/mach-ebsa110/io.c	Sun May 20 12:11:38 2001
+++ linux/arch/arm/mach-ebsa110/io.c	Wed Jun 27 14:12:04 2001
@@ -188,6 +188,7 @@
 u32 __inl(int port)
 {
 	BUG();
+	return 0;
 }
 
 EXPORT_SYMBOL(__inb);
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/consistent.c linux/arch/arm/mm/consistent.c
--- v2.4.5/linux/arch/arm/mm/consistent.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mm/consistent.c	Wed Jun 27 14:12:04 2001
@@ -67,18 +67,21 @@
 #endif
 
 	/*
-	 * free wasted pages.  We skip the first page since
-	 * we know that it will have count = 1 and won't
-	 * require freeing.
+	 * free wasted pages.  We skip the first page since we know
+	 * that it will have count = 1 and won't require freeing.
+	 * We also mark the pages in use as reserved so that
+	 * remap_page_range works.
 	 */
 	page = virt_to_page(virt);
 	free = page + (size >> PAGE_SHIFT);
 	end  = page + (1 << order);
 
-	while (++page < end) {
+	for (; page < end; page++) {
 		set_page_count(page, 1);
 		if (page >= free)
 			__free_page(page);
+		else
+			SetPageReserved(page);
 	}
 	return ret;
 
@@ -108,10 +111,26 @@
  * free a page as defined by the above mapping.  We expressly forbid
  * calling this from interrupt context.
  */
-void consistent_free(void *vaddr)
+void consistent_free(void *vaddr, size_t size, dma_addr_t handle)
 {
+	struct page *page, *end;
+	void *virt;
+
 	if (in_interrupt())
 		BUG();
+
+	virt = bus_to_virt(handle);
+
+	/*
+	 * More messing around with the MM internals.  This is
+	 * sick, but then so is remap_page_range().
+	 */
+	size = PAGE_ALIGN(size);
+	page = virt_to_page(virt);
+	end = page + (size >> PAGE_SHIFT);
+
+	for (; page < end; page++)
+		ClearPageReserved(page);
 
 	__iounmap(vaddr);
 }
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.4.5/linux/arch/arm/mm/fault-armv.c	Wed May 16 15:25:16 2001
+++ linux/arch/arm/mm/fault-armv.c	Wed Jun 27 14:12:04 2001
@@ -24,6 +24,7 @@
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/unaligned.h>
 
@@ -45,9 +46,8 @@
  *
  * Speed optimisations and better fault handling by Russell King.
  *
- * NOTE!!! This is not portable onto the ARM6/ARM7 processors yet.  Also,
- * it seems to give a severe performance impact (1 abort/ms - NW runs at
- * ARM6 speeds) with GCC 2.7.2.2 - needs checking with a later GCC/EGCS.
+ * *** NOTE ***
+ * This code is not portable to processors with late data abort handling.
  */
 #define CODING_BITS(i)	(i & 0x0e000000)
 
@@ -57,6 +57,8 @@
 #define LDST_W_BIT(i)	(i & (1 << 21))		/* Writeback		*/
 #define LDST_L_BIT(i)	(i & (1 << 20))		/* Load			*/
 
+#define LDST_P_EQ_U(i)	((((i) ^ ((i) >> 1)) & (1 << 23)) == 0)
+
 #define LDSTH_I_BIT(i)	(i & (1 << 22))		/* half-word immed	*/
 #define LDM_S_BIT(i)	(i & (1 << 22))		/* write CPSR from SPSR	*/
 
@@ -336,29 +338,48 @@
 	return TYPE_FAULT;
 }
 
+/*
+ * LDM/STM alignment handler.
+ *
+ * There are 4 variants of this instruction:
+ *
+ * B = rn pointer before instruction, A = rn pointer after instruction
+ *              ------ increasing address ----->
+ *	        |    | r0 | r1 | ... | rx |    |
+ * PU = 01             B                    A
+ * PU = 11        B                    A
+ * PU = 00        A                    B
+ * PU = 10             A                    B
+ */
 static int
 do_alignment_ldmstm(unsigned long addr, unsigned long instr, struct pt_regs *regs)
 {
 	unsigned int rd, rn, correction, nr_regs, regbits;
-	unsigned long eaddr;
-
-	correction = 4; /* sometimes 8 on ARMv3 */
-	regs->ARM_pc += correction;
-
-	rd = RD_BITS(instr);
-	rn = RN_BITS(instr);
-	eaddr = regs->uregs[rn];
+	unsigned long eaddr, newaddr;
 
 	if (LDM_S_BIT(instr))
 		goto bad;
 
+	correction = 4; /* processor implementation defined */
+	regs->ARM_pc += correction;
+
 	ai_multi += 1;
 
+	/* count the number of registers in the mask to be transferred */
 	for (regbits = REGMASK_BITS(instr), nr_regs = 0; regbits; regbits >>= 1)
 		nr_regs += 4;
 
+	rn = RN_BITS(instr);
+	newaddr = eaddr = regs->uregs[rn];
+
 	if (!LDST_U_BIT(instr))
-		eaddr -= nr_regs;
+		nr_regs = -nr_regs;
+	newaddr += nr_regs;
+	if (!LDST_U_BIT(instr))
+		eaddr = newaddr;
+
+	if (LDST_P_EQ_U(instr))	/* U = P */
+		eaddr += 4;
 
 	/*
 	 * This is a "hint" - we already have eaddr worked out by the
@@ -369,34 +390,23 @@
 			"addr = %08lx, eaddr = %08lx\n",
 			 instruction_pointer(regs), instr, addr, eaddr);
 
-	if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) ||
-	    (LDST_U_BIT(instr)      && LDST_P_BIT(instr)))
-		eaddr += 4;
-
 	for (regbits = REGMASK_BITS(instr), rd = 0; regbits; regbits >>= 1, rd += 1)
 		if (regbits & 1) {
-			if (LDST_L_BIT(instr)) {
+			if (LDST_L_BIT(instr))
 				get32_unaligned_check(regs->uregs[rd], eaddr);
-				if (rd == 15)
-					correction = 0;
-			} else
+			else
 				put32_unaligned_check(regs->uregs[rd], eaddr);
 			eaddr += 4;
 		}
 
-	if (LDST_W_BIT(instr)) {
-		if (LDST_P_BIT(instr) && !LDST_U_BIT(instr))
-			eaddr -= nr_regs;
-		else if (LDST_P_BIT(instr))
-			eaddr -= 4;
-		else if (!LDST_U_BIT(instr))
-			eaddr -= 4 + nr_regs;
-		regs->uregs[rn] = eaddr;
-	}
-	regs->ARM_pc -= correction;
+	if (LDST_W_BIT(instr))
+		regs->uregs[rn] = newaddr;
+	if (!LDST_L_BIT(instr) || !(REGMASK_BITS(instr) & (1 << 15)))
+		regs->ARM_pc -= correction;
 	return TYPE_DONE;
 
 fault:
+	regs->ARM_pc -= correction;
 	return TYPE_FAULT;
 
 bad:
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.4.5/linux/arch/arm/mm/mm-armv.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mm/mm-armv.c	Wed Jun 27 14:12:04 2001
@@ -79,37 +79,40 @@
 
 	memzero(new_pgd, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
 
-	/*
-	 * This lock is here just to satisfy pmd_alloc and pte_lock
-	 */
-	spin_lock(&mm->page_table_lock);
+	init_pgd = pgd_offset_k(0);
 
-	/*
-	 * On ARM, first page must always be allocated since it contains
-	 * the machine vectors.
-	 */
-	new_pmd = pmd_alloc(mm, new_pgd, 0);
-	if (!new_pmd)
-		goto no_pmd;
-
-	new_pte = pte_alloc(mm, new_pmd, 0);
-	if (!new_pte)
-		goto no_pte;
+	if (vectors_base() == 0) {
+		init_pmd = pmd_offset(init_pgd, 0);
+		init_pte = pte_offset(init_pmd, 0);
+
+		/*
+		 * This lock is here just to satisfy pmd_alloc and pte_lock
+		 */
+		spin_lock(&mm->page_table_lock);
+
+		/*
+		 * On ARM, first page must always be allocated since it
+		 * contains the machine vectors.
+		 */
+		new_pmd = pmd_alloc(mm, new_pgd, 0);
+		if (!new_pmd)
+			goto no_pmd;
+
+		new_pte = pte_alloc(mm, new_pmd, 0);
+		if (!new_pte)
+			goto no_pte;
 
-	init_pgd = pgd_offset_k(0);
-	init_pmd = pmd_offset(init_pgd, 0);
-	init_pte = pte_offset(init_pmd, 0);
+		set_pte(new_pte, *init_pte);
 
-	set_pte(new_pte, *init_pte);
+		spin_unlock(&mm->page_table_lock);
+	}
 
 	/*
 	 * Copy over the kernel and IO PGD entries
 	 */
-	memcpy(new_pgd  + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
 		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
 
-	spin_unlock(&mm->page_table_lock);
-
 	/*
 	 * FIXME: this should not be necessary
 	 */
@@ -134,25 +137,26 @@
 
 void free_pgd_slow(pgd_t *pgd)
 {
-	if (pgd) { /* can pgd be NULL? */
-		pmd_t *pmd;
-		pte_t *pte;
-
-		/* pgd is always present and good */
-		pmd = (pmd_t *)pgd;
-		if (pmd_none(*pmd))
-			goto free;
-		if (pmd_bad(*pmd)) {
-			pmd_ERROR(*pmd);
-			pmd_clear(pmd);
-			goto free;
-		}
+	pmd_t *pmd;
+	pte_t *pte;
 
-		pte = pte_offset(pmd, 0);
+	if (!pgd)
+		return;
+
+	/* pgd is always present and good */
+	pmd = (pmd_t *)pgd;
+	if (pmd_none(*pmd))
+		goto free;
+	if (pmd_bad(*pmd)) {
+		pmd_ERROR(*pmd);
 		pmd_clear(pmd);
-		pte_free(pte);
-		pmd_free(pmd);
+		goto free;
 	}
+
+	pte = pte_offset(pmd, 0);
+	pmd_clear(pmd);
+	pte_free(pte);
+	pmd_free(pmd);
 free:
 	free_pages((unsigned long) pgd, 2);
 }
@@ -296,17 +300,6 @@
 
 	init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE);
 
-	p->physical   = virt_to_phys(init_maps);
-	p->virtual    = 0;
-	p->length     = PAGE_SIZE;
-	p->domain     = DOMAIN_USER;
-	p->prot_read  = 0;
-	p->prot_write = 0;
-	p->cacheable  = 1;
-	p->bufferable = 0;
-
-	p ++;
-
 	for (i = 0; i < mi->nr_banks; i++) {
 		if (mi->bank[i].size == 0)
 			continue;
@@ -350,16 +343,9 @@
 #endif
 
 	/*
-	 * We may have a mapping in virtual address 0.
-	 * Clear it out.
-	 */
-	clear_mapping(0);
-
-	/*
 	 * Go through the initial mappings, but clear out any
 	 * pgdir entries that are not in the description.
 	 */
-	i = 0;
 	q = init_maps;
 	do {
 		if (address < q->virtual || q == p) {
@@ -374,6 +360,21 @@
 			q ++;
 		}
 	} while (address != 0);
+
+	/*
+	 * Create a mapping for the machine vectors at virtual address 0
+	 * or 0xffff0000.  We should always try the high mapping.
+	 */
+	init_maps->physical   = virt_to_phys(init_maps);
+	init_maps->virtual    = vectors_base();
+	init_maps->length     = PAGE_SIZE;
+	init_maps->domain     = DOMAIN_USER;
+	init_maps->prot_read  = 0;
+	init_maps->prot_write = 0;
+	init_maps->cacheable  = 1;
+	init_maps->bufferable = 0;
+
+	create_mapping(init_maps);
 
 	flush_cache_all();
 }
diff -u --recursive --new-file v2.4.5/linux/arch/arm/mm/mm-l7200.c linux/arch/arm/mm/mm-l7200.c
--- v2.4.5/linux/arch/arm/mm/mm-l7200.c	Thu Apr 12 12:20:31 2001
+++ linux/arch/arm/mm/mm-l7200.c	Wed Jun 27 14:12:04 2001
@@ -10,7 +10,6 @@
 #include <asm/hardware.h>
 #include <asm/page.h>
 #include <asm/proc/domain.h>
-#include <asm/setup.h>
 
 #include <asm/mach/map.h>
 
diff -u --recursive --new-file v2.4.5/linux/arch/arm/tools/Makefile linux/arch/arm/tools/Makefile
--- v2.4.5/linux/arch/arm/tools/Makefile	Tue Mar  6 19:44:35 2001
+++ linux/arch/arm/tools/Makefile	Wed Jun 27 14:12:04 2001
@@ -16,7 +16,7 @@
 
 $(TOPDIR)/include/asm-arm/constants.h: constants-hdr getconstants.c
 	$(CC) $(CFLAGS) -S -o - getconstants.c | \
-	 sed 's/^\(#define .* \)#\(.*\)/\1\2/;/^#define/!d' | \
+	 sed 's/^\(#define .* \)[#$$]\(.*\)/\1\2/;/^#define/!d' | \
 	 cat constants-hdr - > $@.tmp
 	cmp $@.tmp $@ >/dev/null 2>&1 || mv $@.tmp $@; $(RM) $@.tmp
 
diff -u --recursive --new-file v2.4.5/linux/arch/arm/tools/getconstants.c linux/arch/arm/tools/getconstants.c
--- v2.4.5/linux/arch/arm/tools/getconstants.c	Wed Apr 11 19:02:27 2001
+++ linux/arch/arm/tools/getconstants.c	Wed Jun 27 14:12:04 2001
@@ -60,7 +60,5 @@
 
 DEFN("PAGE_SZ",			PAGE_SIZE);
 
-DEFN("KSWI_BASE",		0x900000);
-DEFN("KSWI_SYS_BASE",		0x9f0000);
 DEFN("SYS_ERROR0",		0x9f0000);
 }
diff -u --recursive --new-file v2.4.5/linux/arch/arm/tools/mach-types linux/arch/arm/tools/mach-types
--- v2.4.5/linux/arch/arm/tools/mach-types	Wed Apr 11 19:02:27 2001
+++ linux/arch/arm/tools/mach-types	Wed Jun 27 14:12:04 2001
@@ -6,7 +6,7 @@
 # To add an entry into this database, please see Documentation/arm/README,
 # or contact rmk@arm.linux.org.uk
 #
-# Last update: Sat Apr 7 09:45:09 2001
+# Last update: Sun Jun 17 00:53:17 2001
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -63,7 +63,7 @@
 citygo			SA1100_CITYGO		CITYGO			51
 pfs168			SA1100_PFS168		PFS168			52
 spot			SA1100_SPOT		SPOT			53
-flexanet		ARCH_FLEXANET		FLEXANET		54
+flexanet		SA1100_FLEXANET		FLEXANET		54
 webpal			ARCH_WEBPAL		WEBPAL			55
 linpda			SA1100_LINPDA		LINPDA			56
 anakin			ARCH_ANAKIN		ANAKIN			57
@@ -77,6 +77,26 @@
 xfile			SA1100_XFILE		XFILE			65
 accelent_ep9312		ARCH_ACCELENT_EP9312	ACCELENT_EP9312		66
 ic200			ARCH_IC200		IC200			67
+creditlart		SA1100_CREDITLART	CREDITLART		68
+htm			SA1100_HTM		HTM			69
+iq80310			ARCH_IQ80310		IQ80310			70
+freebot			SA1100_FREEBOT		FREEBOT			71
+entel			ARCH_ENTEL		ENTEL			72
+enp3510			ARCH_ENP3510		ENP3510			73
+trizeps			SA1100_TRIZEPS		TRIZEPS			74
+nesa			SA1100_NESA		NESA			75
+venus			ARCH_VENUS		VENUS			76
+tardis			ARCH_TARDIS		TARDIS			77
+mercury			ARCH_MERCURY		MERCURY			78
+empeg			SA1100_EMPEG		EMPEG			79
+adi_eb			ARCH_I80200FCC		I80200FCC		80
+itt_cpb			SA1100_ITT_CPB		ITT_CPB			81
+sa1110_svc		ARCH_SA1110_SVC		SA1110_SVC		82
+alpha2			SA1100_ALPHA2		ALPHA2			84
+alpha1			SA1100_ALPHA1		ALPHA1			85
+netarm			ARCH_NETARM		NETARM			86
+simpad			SA1100_SIMPAD		SIMPAD			87
+pda1			ARCH_PDA1		PDA1			88
+lubbock			ARCH_LUBBOCK		LUBBOCK			89
 
 # The following are unallocated
-empeg			SA1100_EMPEG		EMPEG
diff -u --recursive --new-file v2.4.5/linux/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in
--- v2.4.5/linux/arch/arm/vmlinux-armo.lds.in	Thu Feb  8 16:32:44 2001
+++ linux/arch/arm/vmlinux-armo.lds.in	Mon Jul  2 14:40:14 2001
@@ -47,6 +47,7 @@
 			*(.gnu.warning)
 			*(.text.lock)	/* out-of-line lock text */
 			*(.rodata)
+			*(.rodata.*)
 			*(.glue_7)
 			*(.glue_7t)
 			*(.kstrtab)
diff -u --recursive --new-file v2.4.5/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- v2.4.5/linux/arch/arm/vmlinux-armv.lds.in	Wed May 16 15:25:16 2001
+++ linux/arch/arm/vmlinux-armv.lds.in	Mon Jul  2 14:40:14 2001
@@ -42,6 +42,7 @@
 			*(.gnu.warning)
 			*(.text.lock)	/* out-of-line lock text */
 			*(.rodata)
+			*(.rodata.*)
 			*(.glue_7)
 			*(.glue_7t)
 		*(.got)			/* Global offset table		*/
diff -u --recursive --new-file v2.4.5/linux/arch/cris/boot/compressed/decompress.ld linux/arch/cris/boot/compressed/decompress.ld
--- v2.4.5/linux/arch/cris/boot/compressed/decompress.ld	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/boot/compressed/decompress.ld	Mon Jul  2 14:40:14 2001
@@ -13,6 +13,7 @@
 		_stext = . ;
 		*(.text)
 		*(.rodata)
+		*(.rodata.*)
 		_etext = . ;
 	} > dram
 	.data :
diff -u --recursive --new-file v2.4.5/linux/arch/cris/cris.ld linux/arch/cris/cris.ld
--- v2.4.5/linux/arch/cris/cris.ld	Tue May  1 16:04:56 2001
+++ linux/arch/cris/cris.ld	Mon Jul  2 14:40:14 2001
@@ -24,7 +24,7 @@
 		*(.fixup)
 		*(.text.__*)
 		*(.rodata)
-		*(.rodata.__*)
+		*(.rodata.*)
 	}
 
 	. = ALIGN(4);                /* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/cris/drivers/ide.c linux/arch/cris/drivers/ide.c
--- v2.4.5/linux/arch/cris/drivers/ide.c	Fri Apr  6 10:42:55 2001
+++ linux/arch/cris/drivers/ide.c	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-/* $Id: ide.c,v 1.9 2001/03/01 13:11:18 bjornw Exp $
+/* $Id: ide.c,v 1.16 2001/04/05 08:30:07 matsfg Exp $
  *
  * Etrax specific IDE functions, like init and PIO-mode setting etc.
  * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
@@ -8,6 +8,28 @@
  *             Mikael Starvik     (pio setup stuff)
  *
  * $Log: ide.c,v $
+ * Revision 1.16  2001/04/05 08:30:07  matsfg
+ * Corrected cse1 and csp0 reset.
+ *
+ * Revision 1.15  2001/04/04 14:34:06  bjornw
+ * Re-instated code that mysteriously disappeared during review updates.
+ *
+ * Revision 1.14  2001/04/04 13:45:12  matsfg
+ * Calls REG_SHADOW_SET for cse1 reset so only the resetbit is affected
+ *
+ * Revision 1.13  2001/04/04 13:26:40  matsfg
+ * memmapping is done in init.c
+ *
+ * Revision 1.12  2001/04/04 11:37:56  markusl
+ * Updated according to review remarks
+ *
+ * Revision 1.11  2001/03/29 12:49:14  matsfg
+ * Changed check for ata_tot_size from >= to >.
+ * Sets sw_len to 0 if size is exactly 65536.
+ *
+ * Revision 1.10  2001/03/16 09:39:30  matsfg
+ * Support for reset on port CSP0
+ *
  * Revision 1.9  2001/03/01 13:11:18  bjornw
  * 100 -> HZ
  *
@@ -158,6 +180,10 @@
 #define ATA_PIO0_STROBE 19
 #define ATA_PIO0_HOLD    4
 
+static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
+static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive,
+			  void *buffer, unsigned int length);
+
 /*
  * good_dma_drives() lists the model names (from "hdparm -i")
  * of drives which do not support mword2 DMA but which are
@@ -174,7 +200,7 @@
 	unsigned long flags;
 	
 	pio = 4;
-	//pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	/* pio = ide_get_best_pio_mode(drive, pio, 4, NULL); */
 	
 	save_flags(flags);
 	cli();
@@ -226,10 +252,6 @@
 	restore_flags(flags);
 }
 
-static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive); /* defined below */
-static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive,
-			  void *buffer, unsigned int length);        /* defined below */
-
 void __init 
 init_e100_ide (void)
 {
@@ -277,26 +299,23 @@
 	*R_GEN_CONFIG = genconfig_shadow;
 
 #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
-#ifndef CONFIG_CRIS_LOW_MAP
-	/* remap the I/O-mapped reset-bit from CSE1 to something inside our kernel space */
-	reset_addr = (unsigned long *)ioremap((unsigned long)(MEM_CSE1_START |
-							      MEM_NON_CACHEABLE), 16);
-	*reset_addr = 0;
-#else
-	/* LOW_MAP, can't do the ioremap, but it's already mapped straight over */
-	reset_addr = (unsigned long *)(MEM_CSE1_START | MEM_NON_CACHEABLE);
-	*reset_addr = 0;
+        init_ioremap();
+        REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 0);
 #endif
+
+#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET
+        init_ioremap();
+        REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 0);
 #endif
 
 	/* wait some */
-
-	dummy = 1;
-	dummy = 2;
-	dummy = 3;
+	udelay(25);
 
 #ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
-	*reset_addr = 1 << 16;
+	REG_SHADOW_SET(port_cse1_addr, port_cse1_shadow, 16, 1);
+#endif
+#ifdef CONFIG_ETRAX_IDE_CSP0_8_RESET
+	REG_SHADOW_SET(port_csp0_addr, port_csp0_shadow, 8, 1);
 #endif
 #ifdef CONFIG_ETRAX_IDE_G27_RESET
 	*R_PORT_G_DATA = 0; /* de-assert bus-reset */
@@ -349,7 +368,6 @@
 e100_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
 	ide_ioreg_t data_reg = IDE_DATA_REG;
-	unsigned long status;
 
 	D(printk("atapi_input_bytes, dreg 0x%x, buffer 0x%x, count %d\n",
 		 data_reg, buffer, bytecount));
@@ -376,7 +394,7 @@
 	
 	/* initiate a multi word dma read using PIO handshaking */
 	
-	*R_ATA_TRANSFER_CNT = bytecount >> 1;
+	*R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1);
 	
 	*R_ATA_CTRL_DATA = data_reg |
 		IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
@@ -390,35 +408,38 @@
 	LED_DISK_READ(1);
 	WAIT_DMA(3);
 	LED_DISK_READ(0);
-	
+
 #if 0
-	/* old polled transfer code */
-	
-	/* initiate a multi word read */
-	
-	*R_ATA_TRANSFER_CNT = wcount << 1;
-	
-	*R_ATA_CTRL_DATA = data_reg |
-		IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
-		IO_STATE(R_ATA_CTRL_DATA, src_dst,  register) |
-		IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
-		IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
-		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-	
-	/* svinto has a latency until the busy bit actually is set */
-	
-	nop(); nop();
-	nop(); nop();
-	nop(); nop();
-	nop(); nop();
-	nop(); nop();
-	
-	/* unit should be busy during multi transfer */
-	while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) {
-		while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav)))
-			status = *R_ATA_STATUS_DATA;
-		*ptr++ = (unsigned short)(status & 0xffff);
-	}
+        /* old polled transfer code
+	 * this should be moved into a new function that can do polled
+	 * transfers if DMA is not available
+	 */
+        
+        /* initiate a multi word read */
+        
+        *R_ATA_TRANSFER_CNT = wcount << 1;
+        
+        *R_ATA_CTRL_DATA = data_reg |
+                IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
+                IO_STATE(R_ATA_CTRL_DATA, src_dst,  register) |
+                IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
+                IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+                IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+        
+        /* svinto has a latency until the busy bit actually is set */
+        
+        nop(); nop();
+        nop(); nop();
+        nop(); nop();
+        nop(); nop();
+        nop(); nop();
+        
+        /* unit should be busy during multi transfer */
+        while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) {
+                while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav)))
+                        status = *R_ATA_STATUS_DATA;
+                *ptr++ = (unsigned short)(status & 0xffff);
+        }
 #endif
 }
 
@@ -426,8 +447,6 @@
 e100_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
 {
 	ide_ioreg_t data_reg = IDE_DATA_REG;
-	unsigned short *ptr = (unsigned short *)buffer;
-	unsigned long ctrl;
 	
 	D(printk("atapi_output_bytes, dreg 0x%x, buffer 0x%x, count %d\n",
 		 data_reg, buffer, bytecount));
@@ -454,7 +473,7 @@
 	
 	/* initiate a multi word dma write using PIO handshaking */
 	
-	*R_ATA_TRANSFER_CNT = bytecount >> 1;
+	*R_ATA_TRANSFER_CNT = IO_FIELD(R_ATA_TRANSFER_CNT, count, bytecount >> 1);
 	
 	*R_ATA_CTRL_DATA = data_reg |
 		IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
@@ -470,40 +489,42 @@
 	LED_DISK_WRITE(0);
 
 #if 0
-	/* old polled write code */
+        /* old polled write code - see comment in input_bytes */
 
-	while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */
+	/* wait for busy flag */
+        while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); 
 
-	/* initiate a multi word write */
+        /* initiate a multi word write */
 
-	*R_ATA_TRANSFER_CNT = bytecount >> 1;
+        *R_ATA_TRANSFER_CNT = bytecount >> 1;
 
-	ctrl = data_reg |
-		IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
-		IO_STATE(R_ATA_CTRL_DATA, src_dst,  register) |
-		IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
-		IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
-		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
-	
-	LED_DISK_WRITE(1);
-	
-	/* Etrax will set busy = 1 until the multi pio transfer has finished
-	 * and tr_rdy = 1 after each succesful word transfer. 
-	 * When the last byte has been transferred Etrax will first set tr_tdy = 1 
-	 * and then busy = 0 (not in the same cycle). If we read busy before it
-	 * has been set to 0 we will think that we should transfer more bytes 
-	 * and then tr_rdy would be 0 forever. This is solved by checking busy
-	 * in the inner loop.
-	 */
-	
-	do {
-		*R_ATA_CTRL_DATA = ctrl | *ptr++;
-		while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) &&
-		      (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)));
-	} while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));
+        ctrl = data_reg |
+                IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
+                IO_STATE(R_ATA_CTRL_DATA, src_dst,  register) |
+                IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
+                IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+                IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+        
+        LED_DISK_WRITE(1);
+        
+        /* Etrax will set busy = 1 until the multi pio transfer has finished
+         * and tr_rdy = 1 after each succesful word transfer. 
+         * When the last byte has been transferred Etrax will first set tr_tdy = 1 
+         * and then busy = 0 (not in the same cycle). If we read busy before it
+         * has been set to 0 we will think that we should transfer more bytes 
+         * and then tr_rdy would be 0 forever. This is solved by checking busy
+         * in the inner loop.
+         */
+        
+        do {
+                *R_ATA_CTRL_DATA = ctrl | *ptr++;
+                while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) &&
+                      (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)));
+        } while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));
+
+        LED_DISK_WRITE(0);
+#endif  
 
-	LED_DISK_WRITE(0);
-#endif	
 }
 
 /*
@@ -604,7 +625,7 @@
 		      those blocks that were actually set-up for transfer.
 		*/
 
-		if(ata_tot_size + size >= 131072) {
+		if(ata_tot_size + size > 131072) {
 			printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, size);
 			return 1;
 		}
@@ -625,7 +646,12 @@
                         addr += 65536;
                 }
 		/* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
-		ata_descrs[count].sw_len = size;
+                if(size == 65536) {
+                  ata_descrs[count].sw_len = 0;  /* 0 means 65536, this is a 16-bit field */
+                }
+                else {
+                  ata_descrs[count].sw_len = size;
+                }
 		ata_descrs[count].ctrl = 0;
 		ata_descrs[count].buf = addr;
 		ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]);
@@ -793,9 +819,11 @@
 		
 		/* initiate a multi word dma read using DMA handshaking */
 		
-		*R_ATA_TRANSFER_CNT = ata_tot_size >> 1;
+		*R_ATA_TRANSFER_CNT =
+			IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1);
 		
-		*R_ATA_CTRL_DATA = IDE_DATA_REG  |
+		*R_ATA_CTRL_DATA =
+			IO_FIELD(R_ATA_CTRL_DATA, data, IDE_DATA_REG) |
 			IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
 			IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma)  |
 			IO_STATE(R_ATA_CTRL_DATA, handsh,   dma)  |
@@ -834,9 +862,11 @@
 		
 		/* initiate a multi word dma write using DMA handshaking */
 		
-		*R_ATA_TRANSFER_CNT = ata_tot_size >> 1;
+		*R_ATA_TRANSFER_CNT =
+			IO_FIELD(R_ATA_TRANSFER_CNT, count, ata_tot_size >> 1);
 		
-		*R_ATA_CTRL_DATA = IDE_DATA_REG |
+		*R_ATA_CTRL_DATA =
+			IO_FIELD(R_ATA_CTRL_DATA, data,     IDE_DATA_REG) |
 			IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
 			IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma) |
 			IO_STATE(R_ATA_CTRL_DATA, handsh,   dma) |
diff -u --recursive --new-file v2.4.5/linux/arch/i386/boot/tools/build.c linux/arch/i386/boot/tools/build.c
--- v2.4.5/linux/arch/i386/boot/tools/build.c	Mon Mar 13 09:35:06 2000
+++ linux/arch/i386/boot/tools/build.c	Mon Jul  2 13:56:40 2001
@@ -154,7 +154,7 @@
 	if (sys_size > (is_big_kernel ? 0x28000 : DEF_SYSSIZE))
 		die("System is too big. Try using %smodules.",
 			is_big_kernel ? "" : "bzImage or ");
-	if (sys_size > 0xffff)
+	if (sys_size > 0xefff)
 		fprintf(stderr,"warning: kernel is too big for standalone boot "
 		    "from floppy\n");
 	while (sz > 0) {
diff -u --recursive --new-file v2.4.5/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.4.5/linux/arch/i386/config.in	Thu May 24 15:14:08 2001
+++ linux/arch/i386/config.in	Wed Jun 20 17:47:39 2001
@@ -245,6 +245,10 @@
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    dep_bool '  ACPI support' CONFIG_ACPI $CONFIG_PM
+   
+   if [ "$CONFIG_ACPI" != "n" ]; then
+      source drivers/acpi/Config.in
+   fi
 fi
 
 dep_tristate '  Advanced Power Management BIOS support' CONFIG_APM $CONFIG_PM
@@ -374,6 +378,10 @@
 endmenu
 
 source drivers/usb/Config.in
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   source net/bluetooth/Config.in
+fi
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
diff -u --recursive --new-file v2.4.5/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.5/linux/arch/i386/defconfig	Tue May 22 10:53:06 2001
+++ linux/arch/i386/defconfig	Mon Jul  2 16:08:28 2001
@@ -192,7 +192,7 @@
 # CONFIG_BLK_DEV_HD_IDE is not set
 # CONFIG_BLK_DEV_HD is not set
 CONFIG_BLK_DEV_IDEDISK=y
-# CONFIG_IDEDISK_MULTI_MODE is not set
+CONFIG_IDEDISK_MULTI_MODE=y
 # CONFIG_BLK_DEV_IDEDISK_VENDOR is not set
 # CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set
 # CONFIG_BLK_DEV_IDEDISK_IBM is not set
@@ -217,10 +217,10 @@
 CONFIG_BLK_DEV_RZ1000=y
 CONFIG_BLK_DEV_IDEPCI=y
 CONFIG_IDEPCI_SHARE_IRQ=y
-# CONFIG_BLK_DEV_IDEDMA_PCI is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
 # CONFIG_BLK_DEV_OFFBOARD is not set
-# CONFIG_IDEDMA_PCI_AUTO is not set
-# CONFIG_BLK_DEV_IDEDMA is not set
+CONFIG_IDEDMA_PCI_AUTO=y
+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
@@ -235,8 +235,8 @@
 # CONFIG_BLK_DEV_HPT34X is not set
 # CONFIG_HPT34X_AUTODMA is not set
 # CONFIG_BLK_DEV_HPT366 is not set
-# CONFIG_BLK_DEV_PIIX is not set
-# CONFIG_PIIX_TUNING is not set
+CONFIG_BLK_DEV_PIIX=y
+CONFIG_PIIX_TUNING=y
 # CONFIG_BLK_DEV_NS87415 is not set
 # CONFIG_BLK_DEV_OPTI621 is not set
 # CONFIG_BLK_DEV_PDC202XX is not set
@@ -247,7 +247,8 @@
 # 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_AUTO=y
+# CONFIG_IDEDMA_IVB is not set
 # CONFIG_DMA_NONPCI is not set
 CONFIG_BLK_DEV_IDE_MODES=y
 
@@ -362,10 +363,18 @@
 # Ethernet (10 or 100Mbit)
 #
 CONFIG_NET_ETHERNET=y
+# CONFIG_ARM_AM79C961A is not set
+# CONFIG_SUNLANCE is not set
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNBMAC is not set
+# CONFIG_SUNQE is not set
+# CONFIG_SUNLANCE 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
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
 # CONFIG_DEPCA is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_ISA is not set
@@ -376,11 +385,12 @@
 # CONFIG_APRICOT is not set
 # CONFIG_CS89x0 is not set
 # CONFIG_TULIP is not set
+# 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=y
-# CONFIG_EEPRO100_PM is not set
 # CONFIG_LNE390 is not set
 # CONFIG_FEALNX is not set
 # CONFIG_NATSEMI is not set
@@ -397,16 +407,19 @@
 # CONFIG_TLAN is not set
 # CONFIG_VIA_RHINE is not set
 # CONFIG_WINBOND_840 is not set
-# CONFIG_HAPPYMEAL is not set
 # CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
 # CONFIG_ACENIC is not set
+# CONFIG_ACENIC_OMIT_TIGON_I is not set
+# CONFIG_MYRI_SBUS is not set
 # CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_SK98LIN is not set
 # CONFIG_FDDI is not set
+# CONFIG_PLIP is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 
@@ -445,7 +458,6 @@
 # CONFIG_PCMCIA_NETWAVE is not set
 # CONFIG_PCMCIA_WAVELAN is not set
 # CONFIG_AIRONET4500_CS is not set
-CONFIG_PCMCIA_NETCARD=y
 
 #
 # Amateur Radio support
@@ -530,6 +542,7 @@
 CONFIG_AGP_AMD=y
 CONFIG_AGP_SIS=y
 CONFIG_AGP_ALI=y
+# CONFIG_AGP_SWORKS is not set
 CONFIG_DRM=y
 CONFIG_DRM_TDFX=y
 # CONFIG_DRM_GAMMA is not set
@@ -587,7 +600,6 @@
 # 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
@@ -648,6 +660,7 @@
 # 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
 
@@ -703,6 +716,7 @@
 # CONFIG_USB_IBMCAM is not set
 # CONFIG_USB_OV511 is not set
 # CONFIG_USB_PWC is not set
+# CONFIG_USB_SE401 is not set
 # CONFIG_USB_DSBR is not set
 # CONFIG_USB_DABUSB is not set
 
@@ -711,6 +725,7 @@
 #
 # CONFIG_USB_PLUSB is not set
 # CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_CATC is not set
 # CONFIG_USB_NET1080 is not set
 
 #
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/apic.c linux/arch/i386/kernel/apic.c
--- v2.4.5/linux/arch/i386/kernel/apic.c	Tue Dec  5 12:43:48 2000
+++ linux/arch/i386/kernel/apic.c	Wed Jun 20 11:06:38 2001
@@ -23,6 +23,7 @@
 #include <linux/mc146818rtc.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/atomic.h>
 #include <asm/smp.h>
 #include <asm/mtrr.h>
 #include <asm/mpspec.h>
@@ -270,7 +271,13 @@
 	 *   PCI Ne2000 networking cards and PII/PIII processors, dual
 	 *   BX chipset. ]
 	 */
-#if 0
+	/*
+	 * Actually disabling the focus CPU check just makes the hang less
+	 * frequent as it makes the interrupt distributon model be more
+	 * like LRU than MRU (the short-term load is more even across CPUs).
+	 * See also the comment in end_level_ioapic_irq().  --macro
+	 */
+#if 1
 	/* Enable focus processor (bit==0) */
 	value &= ~(1<<9);
 #else
@@ -728,6 +735,9 @@
 	irq_enter(cpu, 0);
 	smp_local_timer_interrupt(regs);
 	irq_exit(cpu, 0);
+
+	if (softirq_pending(cpu))
+		do_softirq();
 }
 
 /*
@@ -764,7 +774,7 @@
 	apic_write(APIC_ESR, 0);
 	v1 = apic_read(APIC_ESR);
 	ack_APIC_irq();
-	irq_err_count++;
+	atomic_inc(&irq_err_count);
 
 	/* Here is what the APIC error bits mean:
 	   0: Send CS error
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/bluesmoke.c linux/arch/i386/kernel/bluesmoke.c
--- v2.4.5/linux/arch/i386/kernel/bluesmoke.c	Mon May 21 12:34:50 2001
+++ linux/arch/i386/kernel/bluesmoke.c	Sun Jul  1 19:52:45 2001
@@ -182,7 +182,7 @@
  *	Set up machine check reporting on the Winchip C6 series
  */
  
-static void winchip_mcheck_init(struct cpuinfo_x86 *c)
+static void __init winchip_mcheck_init(struct cpuinfo_x86 *c)
 {
 	u32 lo, hi;
 	/* Not supported on C3 */
@@ -207,8 +207,14 @@
  *	This has to be run for each processor
  */
 
+
+static int mce_disabled = 0;
+
 void __init mcheck_init(struct cpuinfo_x86 *c)
 {
+	if(mce_disabled)
+		return;
+		
 	switch(c->x86_vendor)
 	{
 		case X86_VENDOR_AMD:
@@ -226,3 +232,10 @@
 			break;
 	}
 }
+
+static int __init mcheck_disable(char *str)
+{
+	mce_disabled = 1;
+	return 1;
+}
+__setup("nomce", mcheck_disable);
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.4.5/linux/arch/i386/kernel/entry.S	Wed Nov  8 17:09:50 2000
+++ linux/arch/i386/kernel/entry.S	Tue Jun 12 11:47:28 2001
@@ -203,18 +203,7 @@
 	call *SYMBOL_NAME(sys_call_table)(,%eax,4)
 	movl %eax,EAX(%esp)		# save the return value
 ENTRY(ret_from_sys_call)
-#ifdef CONFIG_SMP
-	movl processor(%ebx),%eax
-	shll $CONFIG_X86_L1_CACHE_SHIFT,%eax
-	movl SYMBOL_NAME(irq_stat)(,%eax),%ecx		# softirq_active
-	testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx	# softirq_mask
-#else
-	movl SYMBOL_NAME(irq_stat),%ecx		# softirq_active
-	testl SYMBOL_NAME(irq_stat)+4,%ecx	# softirq_mask
-#endif
-	jne   handle_softirq
-	
-ret_with_reschedule:
+	cli				# need_resched and signals atomic test
 	cmpl $0,need_resched(%ebx)
 	jne reschedule
 	cmpl $0,sigpending(%ebx)
@@ -257,33 +246,16 @@
 	jmp ret_from_sys_call
 
 	ALIGN
-ret_from_exception:
-#ifdef CONFIG_SMP
-	GET_CURRENT(%ebx)
-	movl processor(%ebx),%eax
-	shll $CONFIG_X86_L1_CACHE_SHIFT,%eax
-	movl SYMBOL_NAME(irq_stat)(,%eax),%ecx		# softirq_active
-	testl SYMBOL_NAME(irq_stat)+4(,%eax),%ecx	# softirq_mask
-#else
-	movl SYMBOL_NAME(irq_stat),%ecx		# softirq_active
-	testl SYMBOL_NAME(irq_stat)+4,%ecx	# softirq_mask
-#endif
-	jne   handle_softirq
-
 ENTRY(ret_from_intr)
 	GET_CURRENT(%ebx)
+ret_from_exception:
 	movl EFLAGS(%esp),%eax		# mix EFLAGS and CS
 	movb CS(%esp),%al
 	testl $(VM_MASK | 3),%eax	# return to VM86 mode or non-supervisor?
-	jne ret_with_reschedule
+	jne ret_from_sys_call
 	jmp restore_all
 
 	ALIGN
-handle_softirq:
-	call SYMBOL_NAME(do_softirq)
-	jmp ret_from_intr
-	
-	ALIGN
 reschedule:
 	call SYMBOL_NAME(schedule)    # test
 	jmp ret_from_sys_call
@@ -334,14 +306,16 @@
 	pushl $-1		# mark this as an int
 	SAVE_ALL
 	GET_CURRENT(%ebx)
-	pushl $ret_from_exception
 	movl %cr0,%eax
 	testl $0x4,%eax			# EM (math emulation bit)
-	je SYMBOL_NAME(math_state_restore)
+	jne device_not_available_emulate
+	call SYMBOL_NAME(math_state_restore)
+	jmp ret_from_exception
+device_not_available_emulate:
 	pushl $0		# temporary storage for ORIG_EIP
 	call  SYMBOL_NAME(math_emulate)
 	addl $4,%esp
-	ret
+	jmp ret_from_exception
 
 ENTRY(debug)
 	pushl $0
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.4.5/linux/arch/i386/kernel/head.S	Fri Apr 20 16:23:30 2001
+++ linux/arch/i386/kernel/head.S	Wed Jun 20 11:00:53 2001
@@ -41,8 +41,6 @@
  *
  * On entry, %esi points to the real-mode code as a 32-bit pointer.
  */
-ENTRY(stext)
-ENTRY(_stext)
 startup_32:
 /*
  * Set segments to known values
@@ -409,6 +407,12 @@
 ENTRY(empty_zero_page)
 
 .org 0x5000
+
+/*
+ * Real beginning of normal "text" segment
+ */
+ENTRY(stext)
+ENTRY(_stext)
 
 /*
  * This starts the data section. Note that the above is all
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.4.5/linux/arch/i386/kernel/i386_ksyms.c	Tue May 15 08:46:20 2001
+++ linux/arch/i386/kernel/i386_ksyms.c	Mon Jul  2 14:49:24 2001
@@ -90,9 +90,6 @@
 EXPORT_SYMBOL_NOVERS(__get_user_1);
 EXPORT_SYMBOL_NOVERS(__get_user_2);
 EXPORT_SYMBOL_NOVERS(__get_user_4);
-EXPORT_SYMBOL_NOVERS(__put_user_1);
-EXPORT_SYMBOL_NOVERS(__put_user_2);
-EXPORT_SYMBOL_NOVERS(__put_user_4);
 
 EXPORT_SYMBOL(strtok);
 EXPORT_SYMBOL(strpbrk);
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c
--- v2.4.5/linux/arch/i386/kernel/i8259.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/i386/kernel/i8259.c	Wed Jun 20 11:06:38 2001
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
 
+#include <asm/atomic.h>
 #include <asm/system.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -321,7 +322,7 @@
 			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
 			spurious_irq_mask |= irqmask;
 		}
-		irq_err_count++;
+		atomic_inc(&irq_err_count);
 		/*
 		 * Theoretically we do not have to handle this IRQ,
 		 * but in Linux this does not cause problems and is
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.4.5/linux/arch/i386/kernel/io_apic.c	Fri Feb  9 11:28:31 2001
+++ linux/arch/i386/kernel/io_apic.c	Wed Jun 20 11:06:38 2001
@@ -33,6 +33,8 @@
 #include <asm/smp.h>
 #include <asm/desc.h>
 
+#define APIC_LOCKUP_DEBUG
+
 static spinlock_t ioapic_lock = SPIN_LOCK_UNLOCKED;
 
 /*
@@ -122,8 +124,14 @@
 	static void name##_IO_APIC_irq (unsigned int irq)		\
 	__DO_ACTION(R, ACTION, FINAL)
 
-DO_ACTION( __mask,    0, |= 0x00010000, io_apic_sync(entry->apic))/* mask = 1 */
-DO_ACTION( __unmask,  0, &= 0xfffeffff, )				/* mask = 0 */
+DO_ACTION( __mask,             0, |= 0x00010000, io_apic_sync(entry->apic) )
+						/* mask = 1 */
+DO_ACTION( __unmask,           0, &= 0xfffeffff, )
+						/* mask = 0 */
+DO_ACTION( __mask_and_edge,    0, = (reg & 0xffff7fff) | 0x00010000, )
+						/* mask = 1, trigger = 0 */
+DO_ACTION( __unmask_and_level, 0, = (reg & 0xfffeffff) | 0x00008000, )
+						/* mask = 0, trigger = 1 */
 
 static void mask_IO_APIC_irq (unsigned int irq)
 {
@@ -255,10 +263,16 @@
  */
 static int pin_2_irq(int idx, int apic, int pin);
 
-int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
+int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pin)
 {
 	int apic, i, best_guess = -1;
 
+	Dprintk("querying PCI -> IRQ mapping bus:%d, slot:%d, pin:%d.\n",
+		bus, slot, pin);
+	if (mp_bus_id_to_pci_bus[bus] == -1) {
+		printk(KERN_WARNING "PCI BIOS passed nonexistent PCI bus %d!\n", bus);
+		return -1;
+	}
 	for (i = 0; i < mp_irq_entries; i++) {
 		int lbus = mp_irqs[i].mpc_srcbus;
 
@@ -269,14 +283,14 @@
 
 		if ((mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
 		    !mp_irqs[i].mpc_irqtype &&
-		    (bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
+		    (bus == lbus) &&
 		    (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
 			int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
 
 			if (!(apic || IO_APIC_IRQ(irq)))
 				continue;
 
-			if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3))
+			if (pin == (mp_irqs[i].mpc_srcbusirq & 3))
 				return irq;
 			/*
 			 * Use the first all-but-pin matching entry as a
@@ -728,9 +742,11 @@
 	printk(KERN_DEBUG ".... register #01: %08X\n", *(int *)&reg_01);
 	printk(KERN_DEBUG ".......     : max redirection entries: %04X\n", reg_01.entries);
 	if (	(reg_01.entries != 0x0f) && /* older (Neptune) boards */
+		(reg_01.entries != 0x11) &&
 		(reg_01.entries != 0x17) && /* typical ISA+PCI boards */
 		(reg_01.entries != 0x1b) && /* Compaq Proliant boards */
 		(reg_01.entries != 0x1f) && /* dual Xeon boards */
+		(reg_01.entries != 0x20) &&
 		(reg_01.entries != 0x22) && /* bigger Xeon boards */
 		(reg_01.entries != 0x2E) &&
 		(reg_01.entries != 0x3F)
@@ -847,6 +863,8 @@
 
 	v = apic_read(APIC_EOI);
 	printk(KERN_DEBUG "... APIC EOI: %08x\n", v);
+	v = apic_read(APIC_RRR);
+	printk(KERN_DEBUG "... APIC RRR: %08x\n", v);
 	v = apic_read(APIC_LDR);
 	printk(KERN_DEBUG "... APIC LDR: %08x\n", v);
 	v = apic_read(APIC_DFR);
@@ -1191,12 +1209,61 @@
 #define enable_level_ioapic_irq		unmask_IO_APIC_irq
 #define disable_level_ioapic_irq	mask_IO_APIC_irq
 
-static void end_level_ioapic_irq (unsigned int i)
+static void end_level_ioapic_irq (unsigned int irq)
 {
+	unsigned long v;
+
+/*
+ * It appears there is an erratum which affects at least version 0x11
+ * of I/O APIC (that's the 82093AA and cores integrated into various
+ * chipsets).  Under certain conditions a level-triggered interrupt is
+ * erroneously delivered as edge-triggered one but the respective IRR
+ * bit gets set nevertheless.  As a result the I/O unit expects an EOI
+ * message but it will never arrive and further interrupts are blocked
+ * from the source.  The exact reason is so far unknown, but the
+ * phenomenon was observed when two consecutive interrupt requests
+ * from a given source get delivered to the same CPU and the source is
+ * temporarily disabled in between.
+ *
+ * A workaround is to simulate an EOI message manually.  We achieve it
+ * by setting the trigger mode to edge and then to level when the edge
+ * trigger mode gets detected in the TMR of a local APIC for a
+ * level-triggered interrupt.  We mask the source for the time of the
+ * operation to prevent an edge-triggered interrupt escaping meanwhile.
+ * The idea is from Manfred Spraul.  --macro
+ */
+	v = apic_read(APIC_TMR + ((IO_APIC_VECTOR(irq) & ~0x1f) >> 1));
+
 	ack_APIC_irq();
+
+	if (!(v & (1 << (IO_APIC_VECTOR(irq) & 0x1f)))) {
+#ifdef APIC_MISMATCH_DEBUG
+		atomic_inc(&irq_mis_count);
+#endif
+		spin_lock(&ioapic_lock);
+		__mask_and_edge_IO_APIC_irq(irq);
+#ifdef APIC_LOCKUP_DEBUG
+		for (;;) {
+			struct irq_pin_list *entry = irq_2_pin + irq;
+			unsigned int reg;
+
+			if (entry->pin == -1)
+				break;
+			reg = io_apic_read(entry->apic, 0x10 + entry->pin * 2);
+			if (reg & 0x00004000)
+				printk(KERN_CRIT "Aieee!!!  Remote IRR"
+					" still set after unlock!\n");
+			if (!entry->next)
+				break;
+			entry = irq_2_pin + entry->next;
+		}
+#endif
+		__unmask_and_level_IO_APIC_irq(irq);
+		spin_unlock(&ioapic_lock);
+	}
 }
 
-static void mask_and_ack_level_ioapic_irq (unsigned int i) { /* nothing */ }
+static void mask_and_ack_level_ioapic_irq (unsigned int irq) { /* nothing */ }
 
 static void set_ioapic_affinity (unsigned int irq, unsigned long mask)
 {
@@ -1426,7 +1493,7 @@
 	pin1 = find_isa_irq_pin(0, mp_INT);
 	pin2 = find_isa_irq_pin(0, mp_ExtINT);
 
-	printk(KERN_INFO "..TIMER: vector=%d pin1=%d pin2=%d\n", vector, pin1, pin2);
+	printk(KERN_INFO "..TIMER: vector=%02X pin1=%d pin2=%d\n", vector, pin1, pin2);
 
 	if (pin1 != -1) {
 		/*
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.4.5/linux/arch/i386/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/i386/kernel/irq.c	Wed Jun 20 11:06:38 2001
@@ -33,6 +33,7 @@
 #include <linux/irq.h>
 #include <linux/proc_fs.h>
 
+#include <asm/atomic.h>
 #include <asm/io.h>
 #include <asm/smp.h>
 #include <asm/system.h>
@@ -119,7 +120,12 @@
 	end_none
 };
 
-volatile unsigned long irq_err_count;
+atomic_t irq_err_count;
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
+atomic_t irq_mis_count;
+#endif
+#endif
 
 /*
  * Generic, controller-independent functions:
@@ -167,7 +173,12 @@
 			apic_timer_irqs[cpu_logical_map(j)]);
 	p += sprintf(p, "\n");
 #endif
-	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
+	p += sprintf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+#ifdef CONFIG_X86_IO_APIC
+#ifdef APIC_MISMATCH_DEBUG
+	p += sprintf(p, "MIS: %10u\n", atomic_read(&irq_mis_count));
+#endif
+#endif
 	return p - buf;
 }
 
@@ -623,7 +634,7 @@
 	desc->handler->end(irq);
 	spin_unlock(&desc->lock);
 
-	if (softirq_active(cpu) & softirq_mask(cpu))
+	if (softirq_pending(cpu))
 		do_softirq();
 	return 1;
 }
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/mpparse.c linux/arch/i386/kernel/mpparse.c
--- v2.4.5/linux/arch/i386/kernel/mpparse.c	Tue Nov 14 21:25:34 2000
+++ linux/arch/i386/kernel/mpparse.c	Mon Jun 11 19:15:27 2001
@@ -36,7 +36,7 @@
  */
 int apic_version [MAX_APICS];
 int mp_bus_id_to_type [MAX_MP_BUSSES];
-int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
+int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { [0 ... MAX_MP_BUSSES-1] = -1 };
 int mp_current_pci_id;
 int pic_mode;
 unsigned long mp_lapic_addr;
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/pci-i386.h linux/arch/i386/kernel/pci-i386.h
--- v2.4.5/linux/arch/i386/kernel/pci-i386.h	Thu Jun 22 07:17:16 2000
+++ linux/arch/i386/kernel/pci-i386.h	Wed Jun 20 11:21:33 2001
@@ -12,14 +12,15 @@
 #define DBG(x...)
 #endif
 
-#define PCI_PROBE_BIOS 1
-#define PCI_PROBE_CONF1 2
-#define PCI_PROBE_CONF2 4
-#define PCI_NO_SORT 0x100
-#define PCI_BIOS_SORT 0x200
-#define PCI_NO_CHECKS 0x400
-#define PCI_ASSIGN_ROMS 0x1000
-#define PCI_BIOS_IRQ_SCAN 0x2000
+#define PCI_PROBE_BIOS		0x0001
+#define PCI_PROBE_CONF1		0x0002
+#define PCI_PROBE_CONF2		0x0004
+#define PCI_NO_SORT		0x0100
+#define PCI_BIOS_SORT		0x0200
+#define PCI_NO_CHECKS		0x0400
+#define PCI_ASSIGN_ROMS		0x1000
+#define PCI_BIOS_IRQ_SCAN	0x2000
+#define PCI_ASSIGN_ALL_BUSSES	0x4000
 
 extern unsigned int pci_probe;
 
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- v2.4.5/linux/arch/i386/kernel/pci-irq.c	Wed May 16 10:25:39 2001
+++ linux/arch/i386/kernel/pci-irq.c	Wed Jun 20 11:16:01 2001
@@ -411,7 +411,7 @@
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371MX,   pirq_piix_get, pirq_piix_set },
 	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_0, pirq_piix_get, pirq_piix_set },
-	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82820FW_0, pirq_piix_get, pirq_piix_set },
+	{ "PIIX", PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, pirq_piix_get, pirq_piix_set },
 
 	{ "ALI", PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, pirq_ali_get, pirq_ali_set },
 
@@ -587,13 +587,14 @@
 		if (info->irq[pin].link == pirq) {
 			/* We refuse to override the dev->irq information. Give a warning! */
 		    	if (dev2->irq && dev2->irq != irq) {
-		    		printk(KERN_INFO "IRQ routing conflict in pirq table for device %s\n", dev2->slot_name);
+		    		printk(KERN_INFO "IRQ routing conflict for %s, have irq %d, want irq %d\n",
+				       dev2->slot_name, dev2->irq, irq);
 		    		continue;
 		    	}
 			dev2->irq = irq;
 			pirq_penalty[irq]++;
 			if (dev != dev2)
-				printk(KERN_INFO "PCI: The same IRQ used for device %s\n", dev2->slot_name);
+				printk(KERN_INFO "PCI: Sharing IRQ %d with %s\n", irq, dev2->slot_name);
 		}
 	}
 	return 1;
@@ -656,10 +657,12 @@
 			if (pin) {
 				pin--;		/* interrupt pins are numbered starting from 1 */
 				irq = IO_APIC_get_PCI_irq_vector(dev->bus->number, PCI_SLOT(dev->devfn), pin);
-/*
- * Will be removed completely if things work out well with fuzzy parsing
- */
-#if 0
+	/*
+	 * Busses behind bridges are typically not listed in the MP-table.
+	 * In this case we have to look up the IRQ based on the parent bus,
+	 * parent slot, and pin number. The SMP code detects such bridged
+	 * busses itself so we should get into this branch reliably.
+	 */
 				if (irq < 0 && dev->bus->parent) { /* go back to the bridge */
 					struct pci_dev * bridge = dev->bus->self;
 
@@ -670,7 +673,6 @@
 						printk(KERN_WARNING "PCI: using PPB(B%d,I%d,P%d) to get irq %d\n", 
 							bridge->bus->number, PCI_SLOT(bridge->devfn), pin, irq);
 				}
-#endif
 				if (irq >= 0) {
 					printk(KERN_INFO "PCI->APIC IRQ transform: (B%d,I%d,P%d) -> %d\n",
 						dev->bus->number, PCI_SLOT(dev->devfn), pin, irq);
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.4.5/linux/arch/i386/kernel/pci-pc.c	Thu Apr 19 22:57:06 2001
+++ linux/arch/i386/kernel/pci-pc.c	Wed Jun 20 11:21:33 2001
@@ -940,18 +940,6 @@
 	pcibios_max_latency = 32;
 }
 
-static void __init pci_fixup_via_acpi(struct pci_dev *d)
-{
-	/*
-	 * VIA ACPI device: IRQ line in PCI config byte 0x42
-	 */
-	u8 irq;
-	pci_read_config_byte(d, 0x42, &irq);
-	irq &= 0x0f;
-	if (irq && (irq != 2))
-		d->irq = irq;
-}
-
 static void __init pci_fixup_piix4_acpi(struct pci_dev *d)
 {
 	/*
@@ -1006,8 +994,6 @@
 	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,			pci_fixup_ide_bases },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		pci_fixup_latency },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5598,		pci_fixup_latency },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_3,	pci_fixup_via_acpi },
-	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C686_4,	pci_fixup_via_acpi },
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C691,	pci_fixup_via691 },
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C598_1,	pci_fixup_via691_2 },
  	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	pci_fixup_piix4_acpi },
@@ -1104,6 +1090,9 @@
 	else if (!strcmp(str, "rom")) {
 		pci_probe |= PCI_ASSIGN_ROMS;
 		return NULL;
+	} else if (!strcmp(str, "assign-busses")) {
+		pci_probe |= PCI_ASSIGN_ALL_BUSSES;
+		return NULL;
 	} else if (!strncmp(str, "irqmask=", 8)) {
 		pcibios_irq_mask = simple_strtol(str+8, NULL, 0);
 		return NULL;
@@ -1112,6 +1101,11 @@
 		return NULL;
 	}
 	return str;
+}
+
+unsigned int pcibios_assign_all_busses(void)
+{
+	return (pci_probe & PCI_ASSIGN_ALL_BUSSES) ? 1 : 0;
 }
 
 int pcibios_enable_device(struct pci_dev *dev)
diff -u --recursive --new-file v2.4.5/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.4.5/linux/arch/i386/kernel/traps.c	Mon May  7 14:15:21 2001
+++ linux/arch/i386/kernel/traps.c	Wed Jun 20 13:59:44 2001
@@ -105,6 +105,7 @@
 	i = 1;
 	module_start = VMALLOC_START;
 	module_end = VMALLOC_END;
+	module_end = 0;
 	while (((long) stack & (THREAD_SIZE-1)) != 0) {
 		addr = *stack++;
 		/*
@@ -129,7 +130,12 @@
 
 void show_trace_task(struct task_struct *tsk)
 {
-	show_trace(&tsk->thread.esp);
+	unsigned long esp = tsk->thread.esp;
+
+	/* User space on another CPU? */
+	if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
+		return;
+	show_trace((unsigned long *)esp);
 }
 
 void show_stack(unsigned long * esp)
diff -u --recursive --new-file v2.4.5/linux/arch/i386/lib/Makefile linux/arch/i386/lib/Makefile
--- v2.4.5/linux/arch/i386/lib/Makefile	Wed Apr 25 13:31:03 2001
+++ linux/arch/i386/lib/Makefile	Mon Jul  2 16:15:33 2001
@@ -8,7 +8,7 @@
 L_TARGET = lib.a
 
 obj-y = checksum.o old-checksum.o delay.o \
-	usercopy.o getuser.o putuser.o \
+	usercopy.o getuser.o \
 	memcpy.o strstr.o
 
 obj-$(CONFIG_X86_USE_3DNOW) += mmx.o
diff -u --recursive --new-file v2.4.5/linux/arch/i386/lib/putuser.S linux/arch/i386/lib/putuser.S
--- v2.4.5/linux/arch/i386/lib/putuser.S	Mon Jan 12 13:37:26 1998
+++ linux/arch/i386/lib/putuser.S	Wed Dec 31 16:00:00 1969
@@ -1,71 +0,0 @@
-/*
- * __put_user functions.
- *
- * (C) Copyright 1998 Linus Torvalds
- *
- * These functions have a non-standard call interface
- * to make them more efficient.
- */
-
-/*
- * __put_user_X
- *
- * Inputs:	%eax contains the address
- *		%edx contains the value
- *
- * Outputs:	%eax is error code (0 or -EFAULT)
- *		%ecx is corrupted (will contain "current_task").
- *
- * These functions should not modify any other registers,
- * as they get called from within inline assembly.
- */
-
-addr_limit = 12
-
-.text
-.align 4
-.globl __put_user_1
-__put_user_1:
-	movl %esp,%ecx
-	andl $0xffffe000,%ecx
-	cmpl addr_limit(%ecx),%eax
-	jae bad_put_user
-1:	movb %dl,(%eax)
-	xorl %eax,%eax
-	ret
-
-.align 4
-.globl __put_user_2
-__put_user_2:
-	addl $1,%eax
-	movl %esp,%ecx
-	jc bad_put_user
-	andl $0xffffe000,%ecx
-	cmpl addr_limit(%ecx),%eax
-	jae bad_put_user
-2:	movw %dx,-1(%eax)
-	xorl %eax,%eax
-	ret
-
-.align 4
-.globl __put_user_4
-__put_user_4:
-	addl $3,%eax
-	movl %esp,%ecx
-	jc bad_put_user
-	andl $0xffffe000,%ecx
-	cmpl addr_limit(%ecx),%eax
-	jae bad_put_user
-3:	movl %edx,-3(%eax)
-	xorl %eax,%eax
-	ret
-
-bad_put_user:
-	movl $-14,%eax
-	ret
-
-.section __ex_table,"a"
-	.long 1b,bad_put_user
-	.long 2b,bad_put_user
-	.long 3b,bad_put_user
-.previous
diff -u --recursive --new-file v2.4.5/linux/arch/i386/math-emu/fpu_trig.c linux/arch/i386/math-emu/fpu_trig.c
--- v2.4.5/linux/arch/i386/math-emu/fpu_trig.c	Fri Apr  6 10:42:47 2001
+++ linux/arch/i386/math-emu/fpu_trig.c	Tue Jun 12 11:06:54 2001
@@ -1543,6 +1543,7 @@
 	  EXCEPTION(EX_INTERNAL | 0x116);
 	  return;
 #endif /* PARANOID */
+	  break;
 	}
     }
   else if ( (st0_tag == TAG_Valid) || (st0_tag == TW_Denormal) )
diff -u --recursive --new-file v2.4.5/linux/arch/i386/vmlinux.lds linux/arch/i386/vmlinux.lds
--- v2.4.5/linux/arch/i386/vmlinux.lds	Wed Jan  3 20:45:26 2001
+++ linux/arch/i386/vmlinux.lds	Mon Jul  2 14:40:14 2001
@@ -17,7 +17,7 @@
 
   _etext = .;			/* End of text section */
 
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/ia64/boot/bootloader.lds linux/arch/ia64/boot/bootloader.lds
--- v2.4.5/linux/arch/ia64/boot/bootloader.lds	Sun Feb  6 18:42:40 2000
+++ linux/arch/ia64/boot/bootloader.lds	Mon Jul  2 14:40:14 2001
@@ -12,7 +12,7 @@
 
   /* Global data */
   _data = .;
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .data    : { *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
   __gp = ALIGN (8) + 0x200000;
   .got           : { *(.got.plt) *(.got) }
diff -u --recursive --new-file v2.4.5/linux/arch/ia64/sn/fprom/fprom.lds linux/arch/ia64/sn/fprom/fprom.lds
--- v2.4.5/linux/arch/ia64/sn/fprom/fprom.lds	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/fprom/fprom.lds	Mon Jul  2 14:40:14 2001
@@ -24,7 +24,7 @@
   _data = .;
 
   .rodata : AT(ADDR(.rodata) - 0x0000000000000000 )
-	{ *(.rodata) }
+	{ *(.rodata) *(.rodata.*) }
   .opd : AT(ADDR(.opd) - 0x0000000000000000 )
 	{ *(.opd) }
   .data : AT(ADDR(.data) - 0x0000000000000000 )
diff -u --recursive --new-file v2.4.5/linux/arch/ia64/vmlinux.lds.S linux/arch/ia64/vmlinux.lds.S
--- v2.4.5/linux/arch/ia64/vmlinux.lds.S	Thu Apr  5 12:51:47 2001
+++ linux/arch/ia64/vmlinux.lds.S	Mon Jul  2 14:40:14 2001
@@ -83,7 +83,7 @@
   ia64_unw_end = .;
 
   .rodata : AT(ADDR(.rodata) - PAGE_OFFSET)
-	{ *(.rodata) }
+	{ *(.rodata) *(.rodata.*) }
   .kstrtab : AT(ADDR(.kstrtab) - PAGE_OFFSET)
 	{ *(.kstrtab) }
   .opd : AT(ADDR(.opd) - PAGE_OFFSET)
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.4.5/linux/arch/m68k/Makefile	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/Makefile	Mon Jun 11 19:15:27 2001
@@ -110,8 +110,8 @@
 endif
 
 ifdef CONFIG_SUN3X
-CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o
-SUBDIRS := $(SUBDIRS) arch/m68k/sun3x
+CORE_FILES := $(CORE_FILES) arch/m68k/sun3x/sun3x.o arch/m68k/sun3/sun3.o
+SUBDIRS := $(SUBDIRS) arch/m68k/sun3x arch/m68k/sun3
 endif
 
 ifdef CONFIG_SUN3
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/amisound.c linux/arch/m68k/amiga/amisound.c
--- v2.4.5/linux/arch/m68k/amiga/amisound.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/amiga/amisound.c	Mon Jun 11 19:15:27 2001
@@ -16,7 +16,7 @@
 #include <asm/system.h>
 #include <asm/amigahw.h>
 
-static u_short *snd_data = NULL;
+static unsigned short *snd_data = NULL;
 static const signed char sine_data[] = {
 	0,  39,  75,  103,  121,  127,  121,  103,  75,  39,
 	0, -39, -75, -103, -121, -127, -121, -103, -75, -39
@@ -28,7 +28,7 @@
      * device since it depends on htotal (for OCS/ECS/AGA)
      */
 
-volatile u_short amiga_audio_min_period = 124;	/* Default for pre-OCS */
+volatile unsigned short amiga_audio_min_period = 124; /* Default for pre-OCS */
 
 #define MAX_PERIOD	(65535)
 
@@ -37,9 +37,9 @@
      *	Current period (set by dmasound.c)
      */
 
-u_short amiga_audio_period = MAX_PERIOD;
+unsigned short amiga_audio_period = MAX_PERIOD;
 
-static u_long clock_constant;
+static unsigned long clock_constant;
 
 void __init amiga_init_sound(void)
 {
@@ -76,7 +76,7 @@
 	del_timer( &sound_timer );
 
 	if (hz > 20 && hz < 32767) {
-		u_long period = (clock_constant / hz);
+		unsigned long period = (clock_constant / hz);
 
 		if (period < amiga_audio_min_period)
 			period = amiga_audio_min_period;
@@ -86,7 +86,7 @@
 		/* setup pointer to data, period, length and volume */
 		custom.aud[2].audlc = snd_data;
 		custom.aud[2].audlen = sizeof(sine_data)/2;
-		custom.aud[2].audper = (u_short)period;
+		custom.aud[2].audper = (unsigned short)period;
 		custom.aud[2].audvol = 32; /* 50% of maxvol */
 	
 		if (ticks) {
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/cia.c linux/arch/m68k/amiga/cia.c
--- v2.4.5/linux/arch/m68k/amiga/cia.c	Mon Nov 27 17:57:34 2000
+++ linux/arch/m68k/amiga/cia.c	Mon Jun 11 19:15:27 2001
@@ -23,8 +23,8 @@
 
 struct ciabase {
 	volatile struct CIA *cia;
-	u_char icr_mask, icr_data;
-	u_short int_mask;
+	unsigned char icr_mask, icr_data;
+	unsigned short int_mask;
 	int handler_irq, cia_irq, server_irq;
 	char *name;
 	irq_handler_t irq_list[CIA_IRQS];
@@ -46,7 +46,7 @@
 
 unsigned char cia_set_irq(struct ciabase *base, unsigned char mask)
 {
-	u_char old;
+	unsigned char old;
 
 	old = (base->icr_data |= base->cia->icr);
 	if (mask & CIA_ICR_SETCLR)
@@ -65,7 +65,7 @@
 
 unsigned char cia_able_irq(struct ciabase *base, unsigned char mask)
 {
-	u_char old, tmp;
+	unsigned char old, tmp;
 	int i;
 
 	old = base->icr_mask;
@@ -91,7 +91,7 @@
                     void (*handler)(int, void *, struct pt_regs *),
                     unsigned long flags, const char *devname, void *dev_id)
 {
-	u_char mask;
+	unsigned char mask;
 
 	base->irq_list[irq].handler = handler;
 	base->irq_list[irq].flags   = flags;
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.4.5/linux/arch/m68k/amiga/config.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/m68k/amiga/config.c	Mon Jun 11 19:15:27 2001
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/init.h>
@@ -31,6 +30,7 @@
 #include <asm/amigahw.h>
 #include <asm/amigaints.h>
 #include <asm/irq.h>
+#include <asm/rtc.h>
 #include <asm/keyboard.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/amiga/pcmcia.c linux/arch/m68k/amiga/pcmcia.c
--- v2.4.5/linux/arch/m68k/amiga/pcmcia.c	Thu Dec 17 09:06:25 1998
+++ linux/arch/m68k/amiga/pcmcia.c	Mon Jun 11 19:15:27 2001
@@ -19,7 +19,7 @@
 #include <asm/amipcmcia.h>
 
 /* gayle config byte for program voltage and access speed */
-static u_char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
+static unsigned char cfg_byte = GAYLE_CFG_0V|GAYLE_CFG_150NS;
 
 void pcmcia_reset(void)
 {
@@ -64,7 +64,7 @@
 
 void pcmcia_program_voltage(int voltage)
 {
-	u_char v;
+	unsigned char v;
 
 	switch (voltage) {
 	case PCMCIA_0V:
@@ -87,7 +87,7 @@
 
 void pcmcia_access_speed(int speed)
 {
-	u_char s;
+	unsigned char s;
 
 	if (speed <= PCMCIA_SPEED_100NS)
 		s = GAYLE_CFG_100NS;
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/apollo/config.c linux/arch/m68k/apollo/config.c
--- v2.4.5/linux/arch/m68k/apollo/config.c	Wed Jan 26 12:44:20 2000
+++ linux/arch/m68k/apollo/config.c	Mon Jun 11 19:15:27 2001
@@ -2,7 +2,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 
@@ -12,6 +11,7 @@
 #include <asm/pgtable.h>
 #include <asm/apollohw.h>
 #include <asm/irq.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 
 u_long sio01_physaddr;
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/atari/time.c linux/arch/m68k/atari/time.c
--- v2.4.5/linux/arch/m68k/atari/time.c	Thu Aug 26 12:42:31 1999
+++ linux/arch/m68k/atari/time.c	Mon Jun 11 19:15:27 2001
@@ -12,10 +12,10 @@
 
 #include <linux/types.h>
 #include <linux/mc146818rtc.h>
-#include <linux/kd.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
+#include <asm/rtc.h>
 
 void __init
 atari_sched_init(void (*timer_routine)(int, void *, struct pt_regs *))
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c
--- v2.4.5/linux/arch/m68k/bvme6000/config.c	Mon Jan 31 10:32:53 2000
+++ linux/arch/m68k/bvme6000/config.c	Mon Jun 11 19:15:27 2001
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
@@ -30,6 +29,7 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/bvme6000hw.h>
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c
--- v2.4.5/linux/arch/m68k/bvme6000/rtc.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/m68k/bvme6000/rtc.c	Mon Jun 11 19:15:27 2001
@@ -76,7 +76,7 @@
 		unsigned char mon, day, hrs, min, sec, leap_yr;
 		unsigned int yrs;
 
-		if (!suser())
+		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 
 		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.4.5/linux/arch/m68k/config.in	Mon May 21 18:12:09 2001
+++ linux/arch/m68k/config.in	Mon Jun 11 19:15:27 2001
@@ -55,8 +55,8 @@
 if [ "$CONFIG_HP300" = "y" ]; then
    bool '  DIO bus support' CONFIG_DIO
 fi
-bool 'Sun3 support' CONFIG_SUN3
 bool 'Sun3x support' CONFIG_SUN3X
+bool 'Sun3 support' CONFIG_SUN3
   
 bool 'Q40/Q60 support' CONFIG_Q40
 
@@ -112,7 +112,7 @@
    bool 'Support for ST-RAM as swap space' CONFIG_STRAM_SWAP
    bool 'ST-RAM statistics in /proc' CONFIG_STRAM_PROC
 fi
-if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" ]; then
+if [ "$CONFIG_AMIGA" = "y" -o "$CONFIG_ATARI" = "y" -o "$CONFIG_Q40" = "y" ]; then
    bool 'Use power LED as a heartbeat' CONFIG_HEARTBEAT
 else
   if [ "$CONFIG_HP300" = "y" ]; then
@@ -142,13 +142,17 @@
    fi
    dep_tristate '  Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
    if [ "$CONFIG_PRINTER" != "n" ]; then
-      bool '    Support IEEE1284 status readback' CONFIG_PRINTER_READBACK
+      bool '    Support IEEE1284 status readback' CONFIG_PARPORT_1284
    fi
 fi
 
 source drivers/pci/Config.in
 source drivers/zorro/Config.in
 
+if [ "$CONFIG_Q40" = "y" ]; then
+source drivers/pnp/Config.in
+fi
+
 endmenu
 
 source drivers/mtd/Config.in
@@ -264,11 +268,11 @@
    fi
 
    if [ "$CONFIG_SUN3" = "y" ]; then
-	dep_tristate 'Sun3 NCR5380 SCSI' CONFIG_SUN3_SCSI $CONFIG_SCSI
+	dep_tristate 'Sun3 NCR5380 OBIO SCSI' CONFIG_SUN3_SCSI $CONFIG_SCSI
    fi
 
    if [ "$CONFIG_SUN3X" = "y" ]; then
-      bool 'ESP SCSI driver' CONFIG_SUN3X_ESP
+      bool 'Sun3x ESP SCSI' CONFIG_SUN3X_ESP
    fi
 
    endmenu
@@ -338,6 +342,9 @@
       if [ "$CONFIG_SUN3" = "y" -o "$CONFIG_SUN3X" = "y" ]; then
 	tristate '  Sun3/Sun3x on-board LANCE support' CONFIG_SUN3LANCE
       fi
+      if [ "$CONFIG_SUN3" = "y" ]; then
+	tristate '  Sun3 on-board Intel 82586 support' CONFIG_SUN3_82586
+      fi
       if [ "$CONFIG_HP300" = "y" ]; then
 	 bool '  HP on-board LANCE support' CONFIG_HPLANCE
       fi
@@ -367,7 +374,6 @@
 if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
    bool '    Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
    bool '    Support for sharing serial interrupts' CONFIG_SERIAL_SHARE_IRQ
-#   bool '    Autodetect IRQ - do not yet enable !!' CONFIG_SERIAL_DETECT_IRQ
    bool '    Support special multiport boards' CONFIG_SERIAL_MULTIPORT
    bool '    Support the Bell Technologies HUB6 card' CONFIG_HUB6
 fi
@@ -451,16 +457,16 @@
 else
    define_bool CONFIG_SUN3X_ZS n
 fi
-dep_bool '  Sun keyboard support' CONFIG_SUN_KEYBOARD $CONFIG_SUN3X_ZS
-dep_bool '  Sun mouse support' CONFIG_SUN_MOUSE $CONFIG_SUN3X_ZS
-if [ "$CONFIG_SUN_MOUSE" = "y" ]; then
-   define_bool CONFIG_BUSMOUSE y
-fi
 if [ "$CONFIG_SUN3X_ZS" = "y" ]; then
+   define_bool CONFIG_SUN_KEYBOARD y
+   define_bool CONFIG_SUN_MOUSE y
+   define_bool CONFIG_BUSMOUSE y
    define_bool CONFIG_SBUS y
    define_bool CONFIG_SBUSCHAR y
    define_bool CONFIG_SUN_SERIAL y
 else
+   define_bool CONFIG_SUN_KEYBOARD n
+   define_bool CONFIG_SUN_MOUSE n
    define_bool CONFIG_SBUS n
 fi
 
@@ -508,9 +514,6 @@
    else
       bool 'Generic /dev/rtc emulation' CONFIG_GEN_RTC
    fi
-fi
-if [ "$CONFIG_Q40" = "y" ]; then
-  bool 'Q40 Real Time Clock Support' CONFIG_Q40RTC
 fi
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S
--- v2.4.5/linux/arch/m68k/kernel/head.S	Tue Mar  6 19:44:36 2001
+++ linux/arch/m68k/kernel/head.S	Mon Jun 11 19:15:27 2001
@@ -1178,8 +1178,45 @@
 #ifdef CONFIG_SUN3X
 	is_not_sun3x(L(notsun3x))
 
+	/* oh, the pain..  We're gonna want the prom code after
+	 * starting the MMU, so we copy the mappings, translating
+	 * from 8k -> 4k pages as we go.
+	 */
+
+	/* copy maps from 0xfee00000 to 0xff000000 */
+	movel	#0xfee00000, %d0
+	moveq	#ROOT_INDEX_SHIFT, %d1
+	lsrl	%d1,%d0
+	mmu_get_root_table_entry	%d0
+
+	movel	#0xfee00000, %d0
+	moveq	#PTR_INDEX_SHIFT, %d1
+	lsrl	%d1,%d0
+	andl	#PTR_TABLE_SIZE-1, %d0
+	mmu_get_ptr_table_entry		%a0,%d0
+
+	movel	#0xfee00000, %d0
+	moveq	#PAGE_INDEX_SHIFT, %d1
+	lsrl	%d1,%d0
+	andl	#PAGE_TABLE_SIZE-1, %d0
+	mmu_get_page_table_entry	%a0,%d0
+
+	/* this is where the prom page table lives */	
+	movel	0xfefe00d4, %a1
+	movel	%a1@, %a1
+
+	movel	#((0x200000 >> 13)-1), %d1
+
+1:
+	movel	%a1@+, %d3
+	movel	%d3,%a0@+
+	addl	#0x1000,%d3
+	movel	%d3,%a0@+
+	
+	dbra	%d1,1b	
+		
 	/* setup tt1 for I/O */
-	mmu_map_tt	#1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S
+	mmu_map_tt	#1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S 
 	jbra	L(mmu_init_done)
 
 L(notsun3x):
@@ -1363,7 +1400,7 @@
 	is_not_sun3x(1f)
 
 	/* enable copro */
-	oriw	#0x4000,0x61000000
+	oriw	#0x4000,0x61000000 
 1:
 #endif
 
@@ -3061,6 +3098,16 @@
 2:
 #endif
 
+#ifdef CONFIG_SUN3X
+	is_not_sun3x(2f) 
+	movel	%d0,-(%sp)
+	movel	0xFEFE0018,%a1
+	jbsr	(%a1)
+	addq	#4,%sp
+	jbra	L(serial_putc_done)
+2:	
+#endif
+	
 #ifdef CONFIG_Q40
 	is_not_q40(2f)
 	tst.l	%pc@(L(q40_do_debug))	/* only debug if requested */
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.4.5/linux/arch/m68k/kernel/ptrace.c	Mon Nov 27 18:02:06 2000
+++ linux/arch/m68k/kernel/ptrace.c	Mon Jun 11 19:15:27 2001
@@ -107,15 +107,19 @@
 	ret = -ESRCH;
 	read_lock(&tasklist_lock);
 	child = find_task_by_pid(pid);
-	read_unlock(&tasklist_lock);	/* FIXME!!! */
+	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) {
 		if (child == current)
-			goto out;
+			goto out_tsk;
 		if ((!child->dumpable ||
 		    (current->uid != child->euid) ||
 		    (current->uid != child->suid) ||
@@ -124,10 +128,10 @@
 		    (current->gid != child->sgid) ||
 	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
 	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
-			goto out;
+			goto out_tsk;
 		/* the same process cannot be attached many times */
 		if (child->ptrace & PT_PTRACED)
-			goto out;
+			goto out_tsk;
 		child->ptrace |= PT_PTRACED;
 
 		write_lock_irqsave(&tasklist_lock, flags);
@@ -140,17 +144,17 @@
 
 		send_sig(SIGSTOP, child, 1);
 		ret = 0;
-		goto out;
+		goto out_tsk;
 	}
 	ret = -ESRCH;
 	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) {
 	/* when I and D space are separate, these will need to be fixed. */
@@ -162,9 +166,9 @@
 			copied = access_process_vm(child, 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. */
@@ -172,8 +176,9 @@
 			unsigned long tmp;
 			
 			ret = -EIO;
-			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
-				goto out;
+			if ((addr & 3) || addr < 0 ||
+			    addr > sizeof(struct user) - 3)
+				break;
 			
 			tmp = 0;  /* Default return condition */
 			addr = addr >> 2; /* temporary hack. */
@@ -193,9 +198,9 @@
 					      ((tmp & 0x0000ffff) << 16);
 #endif
 			} else
-				goto out;
+				break;
 			ret = put_user(tmp,(unsigned long *) data);
-			goto out;
+			break;
 		}
 
       /* when I and D space are separate, this will have to be fixed. */
@@ -203,14 +208,15 @@
 		case PTRACE_POKEDATA:
 			ret = 0;
 			if (access_process_vm(child, 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 */
 			ret = -EIO;
-			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
-				goto out;
+			if ((addr & 3) || addr < 0 ||
+			    addr > sizeof(struct user) - 3)
+				break;
 
 			addr = addr >> 2; /* temporary hack. */
 			    
@@ -221,9 +227,9 @@
 			}
 			if (addr < 19) {
 				if (put_reg(child, addr, data))
-					goto out;
+					break;
 				ret = 0;
-				goto out;
+				break;
 			}
 			if (addr >= 21 && addr < 48)
 			{
@@ -240,7 +246,7 @@
 				child->thread.fp[addr - 21] = data;
 				ret = 0;
 			}
-			goto out;
+			break;
 
 		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
 		case PTRACE_CONT: { /* restart after signal. */
@@ -248,7 +254,7 @@
 
 			ret = -EIO;
 			if ((unsigned long) data > _NSIG)
-				goto out;
+				break;
 			if (request == PTRACE_SYSCALL)
 				child->ptrace |= PT_TRACESYS;
 			else
@@ -259,7 +265,7 @@
 			put_reg(child, PT_SR, tmp);
 			wake_up_process(child);
 			ret = 0;
-			goto out;
+			break;
 		}
 
 /*
@@ -272,13 +278,13 @@
 
 			ret = 0;
 			if (child->state == TASK_ZOMBIE) /* already dead */
-				goto out;
+				break;
 			child->exit_code = SIGKILL;
 	/* make sure the single step bit is not set. */
 			tmp = get_reg(child, PT_SR) & ~(TRACE_BITS << 16);
 			put_reg(child, PT_SR, tmp);
 			wake_up_process(child);
-			goto out;
+			break;
 		}
 
 		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
@@ -286,7 +292,7 @@
 
 			ret = -EIO;
 			if ((unsigned long) data > _NSIG)
-				goto out;
+				break;
 			child->ptrace &= ~PT_TRACESYS;
 			tmp = get_reg(child, PT_SR) | (TRACE_BITS << 16);
 			put_reg(child, PT_SR, tmp);
@@ -295,7 +301,7 @@
 	/* give it a chance to run. */
 			wake_up_process(child);
 			ret = 0;
-			goto out;
+			break;
 		}
 
 		case PTRACE_DETACH: { /* detach a process that was attached. */
@@ -303,7 +309,7 @@
 
 			ret = -EIO;
 			if ((unsigned long) data > _NSIG)
-				goto out;
+				break;
 			child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
 			child->exit_code = data;
 			write_lock_irqsave(&tasklist_lock, flags);
@@ -316,7 +322,7 @@
 			put_reg(child, PT_SR, tmp);
 			wake_up_process(child);
 			ret = 0;
-			goto out;
+			break;
 		}
 
 		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
@@ -328,12 +334,12 @@
 				tmp >>= 16;
 			    if (put_user(tmp, (unsigned long *) data)) {
 				ret = -EFAULT;
-				goto out;
+				break;
 			    }
 			    data += sizeof(long);
 			}
 			ret = 0;
-			goto out;
+			break;
 		}
 
 		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
@@ -342,7 +348,7 @@
 			for (i = 0; i < 19; i++) {
 			    if (get_user(tmp, (unsigned long *) data)) {
 				ret = -EFAULT;
-				goto out;
+				break;
 			    }
 			    if (i == PT_SR) {
 				tmp &= SR_MASK;
@@ -353,7 +359,7 @@
 			    data += sizeof(long);
 			}
 			ret = 0;
-			goto out;
+			break;
 		}
 
 		case PTRACE_GETFPREGS: { /* Get the child FPU state. */
@@ -361,7 +367,7 @@
 			if (copy_to_user((void *)data, &child->thread.fp,
 					 sizeof(struct user_m68kfp_struct)))
 				ret = -EFAULT;
-			goto out;
+			break;
 		}
 
 		case PTRACE_SETFPREGS: { /* Set the child FPU state. */
@@ -369,13 +375,15 @@
 			if (copy_from_user(&child->thread.fp, (void *)data,
 					   sizeof(struct user_m68kfp_struct)))
 				ret = -EFAULT;
-			goto out;
+			break;
 		}
 
 		default:
 			ret = -EIO;
-			goto out;
+			break;
 	}
+out_tsk:
+	free_task_struct(child);
 out:
 	unlock_kernel();
 	return ret;
@@ -383,10 +391,9 @@
 
 asmlinkage void syscall_trace(void)
 {
-	lock_kernel();
 	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
 			!= (PT_PTRACED|PT_TRACESYS))
-		goto out;
+		return;
 	current->exit_code = SIGTRAP;
 	current->state = TASK_STOPPED;
 	notify_parent(current, SIGCHLD);
@@ -400,6 +407,4 @@
 		send_sig(current->exit_code, current, 1);
 		current->exit_code = 0;
 	}
-out:
-	unlock_kernel();
 }
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.4.5/linux/arch/m68k/kernel/setup.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/m68k/kernel/setup.c	Mon Jun 11 19:15:27 2001
@@ -34,6 +34,10 @@
 #ifdef CONFIG_ATARI
 #include <asm/atarihw.h>
 #endif
+#ifdef CONFIG_SUN3X
+#include <asm/dvma.h>
+extern void sun_serial_setup(void);
+#endif
 
 #ifdef CONFIG_BLK_DEV_INITRD
 #include <linux/blk.h>
@@ -106,6 +110,11 @@
 char *mach_sysrq_xlate = NULL;
 #endif
 
+#if defined(CONFIG_ISA)
+int isa_type;
+int isa_sex;
+#endif
+
 extern int amiga_parse_bootinfo(const struct bi_record *);
 extern int atari_parse_bootinfo(const struct bi_record *);
 extern int mac_parse_bootinfo(const struct bi_record *);
@@ -137,7 +146,7 @@
 {
     while (record->tag != BI_LAST) {
 	int unknown = 0;
-	const u_long *data = record->data;
+	const unsigned long *data = record->data;
 	switch (record->tag) {
 	    case BI_MACHTYPE:
 	    case BI_CPUTYPE:
@@ -186,7 +195,7 @@
 	if (unknown)
 	    printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
 		   record->tag);
-	record = (struct bi_record *)((u_long)record+record->size);
+	record = (struct bi_record *)((unsigned long)record+record->size);
     }
 
     m68k_realnum_memory = m68k_num_memory;
@@ -365,14 +374,44 @@
 	if (MACH_IS_ATARI)
 		atari_stram_reserve_pages(availmem);
 #endif
+#ifdef CONFIG_SUN3X
+	if (MACH_IS_SUN3X) {
+		dvma_init();
+#ifdef CONFIG_SUN3X_ZS
+		sun_serial_setup();
+#endif
+	}
+#endif
+
 #endif /* !CONFIG_SUN3 */
+
 	paging_init();
+
+/* set ISA defs early as possible */
+#if defined(CONFIG_ISA)
+#if defined(CONFIG_Q40) 
+	if (MACH_IS_Q40) {
+	    isa_type = Q40_ISA;
+	    isa_sex = 0;
+	} 
+#elif defined(CONFIG_GG2)
+	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(GG2_ISA)){
+	    isa_type = GG2_ISA;
+	    isa_sex = 0;
+	}
+#elif defined(CONFIG_AMIGA_PCMCIA)
+	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)){
+	    isa_type = AG_ISA;
+	    isa_sex = 1;
+	}
+#endif
+#endif
 }
 
 int get_cpuinfo(char * buffer)
 {
     const char *cpu, *mmu, *fpu;
-    u_long clockfreq, clockfactor;
+    unsigned long clockfreq, clockfactor;
 
 #define LOOP_CYCLES_68020	(8)
 #define LOOP_CYCLES_68030	(8)
@@ -447,7 +486,7 @@
 {
     int len = 0;
     char model[80];
-    u_long mem;
+    unsigned long mem;
     int i;
 
     if (mach_get_model)
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c
--- v2.4.5/linux/arch/m68k/kernel/sys_m68k.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/m68k/kernel/sys_m68k.c	Mon Jun 11 19:15:27 2001
@@ -267,7 +267,8 @@
   return -ENOSYS;
 }
 
-/* Convert virtual address VADDR to physical address PADDR */
+
+/* Convert virtual (user) address VADDR to physical address PADDR */
 #define virt_to_phys_040(vaddr)						\
 ({									\
   unsigned long _mmusr, _paddr;						\
@@ -447,6 +448,12 @@
 {
   unsigned long paddr, i;
 
+  /*
+   * 68060 manual says: 
+   *  cpush %dc : flush DC, remains valid (with our %cacr setup)
+   *  cpush %ic : invalidate IC
+   *  cpush %bc : flush DC + invalidate IC
+   */
   switch (scope)
     {
     case FLUSH_SCOPE_ALL:
@@ -455,20 +462,17 @@
 	case FLUSH_CACHE_DATA:
 	  __asm__ __volatile__ (".chip 68060\n\t"
 				"cpusha %dc\n\t"
-				"cinva %dc\n\t"
 				".chip 68k");
 	  break;
 	case FLUSH_CACHE_INSN:
 	  __asm__ __volatile__ (".chip 68060\n\t"
 				"cpusha %ic\n\t"
-				"cinva %ic\n\t"
 				".chip 68k");
 	  break;
 	default:
 	case FLUSH_CACHE_BOTH:
 	  __asm__ __volatile__ (".chip 68060\n\t"
 				"cpusha %bc\n\t"
-				"cinva %bc\n\t"
 				".chip 68k");
 	  break;
 	}
@@ -506,14 +510,12 @@
 	    case FLUSH_CACHE_DATA:
 	      __asm__ __volatile__ (".chip 68060\n\t"
 				    "cpushl %%dc,(%0)\n\t"
-				    "cinvl %%dc,(%0)\n\t"
 				    ".chip 68k"
 				    : : "a" (paddr));
 	      break;
 	    case FLUSH_CACHE_INSN:
 	      __asm__ __volatile__ (".chip 68060\n\t"
 				    "cpushl %%ic,(%0)\n\t"
-				    "cinvl %%ic,(%0)\n\t"
 				    ".chip 68k"
 				    : : "a" (paddr));
 	      break;
@@ -521,7 +523,6 @@
 	    case FLUSH_CACHE_BOTH:
 	      __asm__ __volatile__ (".chip 68060\n\t"
 				    "cpushl %%bc,(%0)\n\t"
-				    "cinvl %%bc,(%0)\n\t"
 				    ".chip 68k"
 				    : : "a" (paddr));
 	      break;
@@ -568,14 +569,12 @@
 	    case FLUSH_CACHE_DATA:
 	      __asm__ __volatile__ (".chip 68060\n\t"
 				    "cpushp %%dc,(%0)\n\t"
-				    "cinvp %%dc,(%0)\n\t"
 				    ".chip 68k"
 				    : : "a" (paddr));
 	      break;
 	    case FLUSH_CACHE_INSN:
 	      __asm__ __volatile__ (".chip 68060\n\t"
 				    "cpushp %%ic,(%0)\n\t"
-				    "cinvp %%ic,(%0)\n\t"
 				    ".chip 68k"
 				    : : "a" (paddr));
 	      break;
@@ -583,7 +582,6 @@
 	    case FLUSH_CACHE_BOTH:
 	      __asm__ __volatile__ (".chip 68060\n\t"
 				    "cpushp %%bc,(%0)\n\t"
-				    "cinvp %%bc,(%0)\n\t"
 				    ".chip 68k"
 				    : : "a" (paddr));
 	      break;
@@ -607,13 +605,14 @@
 		goto out;
 
 	if (scope == FLUSH_SCOPE_ALL) {
-		/* Only the superuser may flush the whole cache. */
+		/* Only the superuser may explicitly flush the whole cache. */
 		ret = -EPERM;
 		if (!capable(CAP_SYS_ADMIN))
 			goto out;
 	} else {
-		/* Verify that the specified address region actually belongs to
-		 * this process.
+		/*
+		 * Verify that the specified address region actually belongs
+		 * to this process.
 		 */
 		vma = find_vma (current->mm, addr);
 		ret = -EINVAL;
@@ -652,10 +651,21 @@
 		}
 		ret = 0;
 		goto out;
-	} else if (CPU_IS_040) {
+	} else {
+	    /*
+	     * 040 or 060: don't blindly trust 'scope', someone could
+	     * try to flush a few megs of memory.
+	     */
+
+	    if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
+	        scope=FLUSH_SCOPE_PAGE;
+	    if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
+	        scope=FLUSH_SCOPE_ALL;
+	    if (CPU_IS_040) {
 		ret = cache_flush_040 (addr, scope, cache, len);
-	} else if (CPU_IS_060) {
+	    } else if (CPU_IS_060) {
 		ret = cache_flush_060 (addr, scope, cache, len);
+	    }
 	}
 out:
 	unlock_kernel();
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/kernel/traps.c linux/arch/m68k/kernel/traps.c
--- v2.4.5/linux/arch/m68k/kernel/traps.c	Thu Jan  4 13:00:55 2001
+++ linux/arch/m68k/kernel/traps.c	Mon Jun 11 19:15:27 2001
@@ -72,6 +72,12 @@
  */
 void __init base_trap_init(void)
 {
+	if(MACH_IS_SUN3X) {
+		extern e_vector *sun3x_prom_vbr;
+
+		__asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr));
+	}
+	
 	/* setup the exception vector table */
 	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
 
@@ -245,9 +251,12 @@
 #endif /* CONFIG_M68060 */
 
 #if defined (CONFIG_M68040)
-static inline unsigned long probe040(int iswrite, unsigned long addr)
+static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
 {
 	unsigned long mmusr;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(MAKE_MM_SEG(wbs));
 
 	asm volatile (".chip 68040");
 
@@ -260,6 +269,8 @@
 
 	asm volatile (".chip 68k");
 
+	set_fs(old_fs); 
+
 	return mmusr;
 }
 
@@ -267,7 +278,9 @@
 				   unsigned long wbd)
 {
 	int res = 0;
+	mm_segment_t old_fs = get_fs();
 
+	/* set_fs can not be moved, otherwise put_user() may oops */
 	set_fs(MAKE_MM_SEG(wbs));
 
 	switch (wbs & WBSIZ_040) {
@@ -282,6 +295,10 @@
 		break;
 	}
 
+	/* set_fs can not be moved, otherwise put_user() may oops */
+	set_fs(old_fs); 
+	
+
 #ifdef DEBUG
 	printk("do_040writeback1, res=%d\n",res);
 #endif
@@ -293,10 +310,12 @@
  * to that exception is discarded, set a few bits in the old frame 
  * to simulate what it should look like
  */
-static inline void fix_xframe040(struct frame *fp, unsigned short wbs)
+static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
 {
-	fp->un.fmt7.faddr = current->thread.faddr;
+	fp->un.fmt7.faddr = wba;
 	fp->un.fmt7.ssw = wbs & 0xff;
+	if (wba != current->thread.faddr)
+	    fp->un.fmt7.ssw |= MA_040;
 }
 
 static inline void do_040writebacks(struct frame *fp)
@@ -312,7 +331,7 @@
 		res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
 				       fp->un.fmt7.wb2d);
 		if (res)
-			fix_xframe040(fp, fp->un.fmt7.wb2s);
+			fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
 		else 
 			fp->un.fmt7.wb2s = 0;
 	}
@@ -322,7 +341,14 @@
 		res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
 				       fp->un.fmt7.wb3d);
 		if (res)
-			fix_xframe040(fp, fp->un.fmt7.wb3s);
+		    {
+			fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
+
+			fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
+			fp->un.fmt7.wb3s &= (~WBV_040);
+			fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
+			fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
+		    }
 		else
 			fp->un.fmt7.wb3s = 0;
 	}
@@ -339,19 +365,15 @@
  */
 asmlinkage void berr_040cleanup(struct frame *fp)
 {
-	mm_segment_t old_fs = get_fs();
-
 	fp->un.fmt7.wb2s &= ~4;
 	fp->un.fmt7.wb3s &= ~4;
 
 	do_040writebacks(fp);
-	set_fs(old_fs);
 }
 
 static inline void access_error040(struct frame *fp)
 {
 	unsigned short ssw = fp->un.fmt7.ssw;
-	mm_segment_t old_fs = get_fs();
 	unsigned long mmusr;
 
 #ifdef DEBUG
@@ -374,9 +396,8 @@
 		if (ssw & MA_040)
 			addr = (addr + 7) & -8;
 
-		set_fs(MAKE_MM_SEG(ssw));
 		/* MMU error, get the MMUSR info for this access */
-		mmusr = probe040(!(ssw & RW_040), addr);
+		mmusr = probe040(!(ssw & RW_040), addr, ssw);
 #ifdef DEBUG
 		printk("mmusr = %lx\n", mmusr);
 #endif
@@ -386,8 +407,12 @@
 			__flush_tlb040_one(addr);
 			errorcode = 0;
 		}
-		if (!(ssw & RW_040))
+
+		/* despite what documentation seems to say, RMW 
+		 * accesses have always both the LK and RW bits set */
+		if (!(ssw & RW_040) || (ssw & LK_040))
 			errorcode |= 2;
+
 		if (do_page_fault(&fp->ptregs, addr, errorcode)) {
 #ifdef DEBUG
 		        printk("do_page_fault() !=0 \n");
@@ -415,7 +440,6 @@
 	}
 
 	do_040writebacks(fp);
-	set_fs(old_fs);
 }
 #endif /* CONFIG_M68040 */
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c
--- v2.4.5/linux/arch/m68k/mac/config.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/m68k/mac/config.c	Mon Jun 11 19:15:27 2001
@@ -13,7 +13,6 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/interrupt.h>
@@ -31,6 +30,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/pgtable.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 
 #include <asm/macintosh.h>
@@ -78,8 +78,6 @@
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
 extern void mac_mksound(unsigned int, unsigned int);
-extern int mac_floppy_init(void);
-extern void mac_floppy_setup(char *,int *);
 
 extern void nubus_sweep_video(void);
 
@@ -122,8 +120,6 @@
 }
 #endif
 
-extern struct fb_info *mac_fb_init(long *);
-
 extern void mac_default_handler(int, void *, struct pt_regs *);
 
 void (*mac_handlers[8])(int, void *, struct pt_regs *)=
@@ -387,8 +383,7 @@
 	{	MAC_MODEL_P460,  "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci,   MAC_SCSI_OLD, 	MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P475,  "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	{	MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
-	{	MAC_MODEL_P520,  "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
-
+	{	MAC_MODEL_P520,  "Performa 520", MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_OLD,    MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P550,  "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_OLD,    MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P575,  "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE,   MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	/* These have the comm slot, and therefore the possibility of SONIC ethernet */
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c
--- v2.4.5/linux/arch/m68k/mac/debug.c	Thu Oct 12 14:20:48 2000
+++ linux/arch/m68k/mac/debug.c	Mon Jun 11 19:15:27 2001
@@ -187,7 +187,7 @@
 
 
 
-/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
+/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
 
 #define uSEC 1
 
@@ -286,9 +286,9 @@
 		barrier();				\
     } while(0)
 
-/* loops_per_sec isn't initialized yet, so we can't use udelay(). This does a
+/* loops_per_jiffy isn't initialized yet, so we can't use udelay(). This does a
  * delay of ~ 60us. */
-/* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
+/* Mac: loops_per_jiffy min. 19000 ^= .5 us; MFPDELAY was 0.6 us*/
 #define LONG_DELAY()				\
     do {					\
 	int i;					\
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/iop.c linux/arch/m68k/mac/iop.c
--- v2.4.5/linux/arch/m68k/mac/iop.c	Sun Feb 13 11:21:42 2000
+++ linux/arch/m68k/mac/iop.c	Mon Jun 11 19:15:27 2001
@@ -51,9 +51,6 @@
  *   IOP hasn't died.
  * o Some of the IOP manager routines need better error checking and
  *   return codes. Nothing major, just prettying up.
- *
- * + share the stuff you were smoking when you wrote the iop_get_proc_info()
- *   for case when CONFIG_PROC_FS is undefined.
  */
 
 /*
@@ -129,9 +126,6 @@
 
 #ifdef CONFIG_PROC_FS
 static int iop_get_proc_info(char *, char **, off_t, int);
-#else
-/* What the bloody hell is THAT ??? */
-static int iop_get_proc_info(char *, char **, off_t, int) {}
 #endif /* CONFIG_PROC_FS */
 
 /* structure for tracking channel listeners */
@@ -307,7 +301,11 @@
 		iop_listeners[IOP_NUM_ISM][i].handler = NULL;
 	}
 
-	create_proc_info_entry("mac_iop",0,0,iop_get_proc_info);
+#if 0	/* Crashing in 2.4 now, not yet sure why.   --jmt */
+#ifdef CONFIG_PROC_FS
+	create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info);
+#endif
+#endif
 }
 
 /*
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c
--- v2.4.5/linux/arch/m68k/mac/macints.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/m68k/mac/macints.c	Mon Jun 11 19:15:27 2001
@@ -129,9 +129,13 @@
 #include <asm/macintosh.h>
 #include <asm/mac_via.h>
 #include <asm/mac_psc.h>
+#include <asm/hwtest.h>
 
 #include <asm/macints.h>
 
+#define DEBUG_SPURIOUS
+#define SHUTUP_SONIC
+
 /*
  * The mac_irq_list array is an array of linked lists of irq_node_t nodes.
  * Each node contains one handler to be called whenever the interrupt
@@ -233,6 +237,17 @@
 
 	scc_mask = 0;
 
+	/* Make sure the SONIC interrupt is cleared or things get ugly */
+#ifdef SHUTUP_SONIC
+	printk("Killing onboard sonic... ");
+	/* This address should hopefully be mapped already */
+	if (hwreg_present((void*)(0x50f0a000))) {
+		*(long *)(0x50f0a014) = 0x7fffL;
+		*(long *)(0x50f0a010) = 0L;
+	}
+	printk("Done.\n");
+#endif /* SHUTUP_SONIC */
+
 	/* 
 	 * Now register the handlers for the the master IRQ handlers
 	 * at levels 1-7. Most of the work is done elsewhere.
@@ -627,9 +642,7 @@
 void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 #ifdef DEBUG_SPURIOUS
-	if (console_loglevel > 6) {
-		printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
-	}
+	printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
 #endif
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/misc.c linux/arch/m68k/mac/misc.c
--- v2.4.5/linux/arch/m68k/mac/misc.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/m68k/mac/misc.c	Mon Jun 11 19:15:27 2001
@@ -2,7 +2,6 @@
  * Miscellaneous Mac68K-specific stuff 
  */
 
-#include <stdarg.h>
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/errno.h>
@@ -12,7 +11,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/time.h>
-#include <linux/kd.h>
+
 #include <linux/mm.h>
 
 #include <linux/adb.h>
@@ -21,6 +20,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
+#include <asm/rtc.h>
 #include <asm/system.h>
 #include <asm/segment.h>
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/psc.c linux/arch/m68k/mac/psc.c
--- v2.4.5/linux/arch/m68k/mac/psc.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/m68k/mac/psc.c	Mon Jun 11 19:15:27 2001
@@ -139,7 +139,6 @@
 	int irq_bit,i;
 	unsigned char events;
 
-	irq -= VEC_SPUR;
 	base_irq = irq << 3;
 
 #ifdef DEBUG_IRQS
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mac/via.c linux/arch/m68k/mac/via.c
--- v2.4.5/linux/arch/m68k/mac/via.c	Sun Dec  3 17:45:20 2000
+++ linux/arch/m68k/mac/via.c	Mon Jun 11 19:15:27 2001
@@ -410,8 +410,6 @@
 	int irq_bit, i;
 	unsigned char events, mask;
 
-	irq -= VEC_SPUR;
-
 	mask = via1[vIER] & 0x7F;
 	if (!(events = via1[vIFR] & mask)) return;
 
@@ -423,6 +421,7 @@
 			via1[vIER] = irq_bit | 0x80;
 		}
 
+#if 0 /* freakin' pmu is doing weird stuff */
 	if (!oss_present) {
 		/* This (still) seems to be necessary to get IDE
 		   working.  However, if you enable VBL interrupts,
@@ -435,14 +434,13 @@
 		mac_do_irq_list(IRQ_MAC_NUBUS, regs);
 		via_irq_enable(IRQ_MAC_NUBUS);
 	}
+#endif
 }
 
 void via2_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
 	int irq_bit, i;
 	unsigned char events, mask;
-
-	irq -= VEC_SPUR;
 
 	mask = via2[gIER] & 0x7F;
 	if (!(events = via2[gIFR] & mask)) return;
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/math-emu/multi_arith.h linux/arch/m68k/math-emu/multi_arith.h
--- v2.4.5/linux/arch/m68k/math-emu/multi_arith.h	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/multi_arith.h	Mon Jun 11 19:15:27 2001
@@ -329,7 +329,7 @@
 	int carry;
 
 	/* we assume here, gcc only insert move and a clr instr */
-	asm volatile ("add.b %1,%0" : "=d,=g" (dest->lowmant)
+	asm volatile ("add.b %1,%0" : "=d,g" (dest->lowmant)
 		: "g,d" (src->lowmant), "0,0" (dest->lowmant));
 	asm volatile ("addx.l %1,%0" : "=d" (dest->mant.m32[1])
 		: "d" (src->mant.m32[1]), "0" (dest->mant.m32[1]));
@@ -360,7 +360,7 @@
 extern inline void fp_submant(struct fp_ext *dest, struct fp_ext *src1, struct fp_ext *src2)
 {
 	/* we assume here, gcc only insert move and a clr instr */
-	asm volatile ("sub.b %1,%0" : "=d,=g" (dest->lowmant)
+	asm volatile ("sub.b %1,%0" : "=d,g" (dest->lowmant)
 		: "g,d" (src2->lowmant), "0,0" (src1->lowmant));
 	asm volatile ("subx.l %1,%0" : "=d" (dest->mant.m32[1])
 		: "d" (src2->mant.m32[1]), "0" (src1->mant.m32[1]));
@@ -383,7 +383,7 @@
 })
 #define fp_addx96(dest, src) ({						\
 	/* we assume here, gcc only insert move and a clr instr */	\
-	asm volatile ("add.l %1,%0" : "=d,=g" (dest->m32[2])		\
+	asm volatile ("add.l %1,%0" : "=d,g" (dest->m32[2])		\
 		: "g,d" (temp.m32[1]), "0,0" (dest->m32[2]));		\
 	asm volatile ("addx.l %1,%0" : "=d" (dest->m32[1])		\
 		: "d" (temp.m32[0]), "0" (dest->m32[1]));		\
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.4.5/linux/arch/m68k/mm/init.c	Mon Oct 16 12:58:51 2000
+++ linux/arch/m68k/mm/init.c	Mon Jun 11 19:15:27 2001
@@ -32,11 +32,7 @@
 #include <asm/atari_stram.h>
 #endif
 
-static unsigned long totalram_pages;
-
-#ifdef CONFIG_SUN3
-void mmu_emu_reserve_pages(unsigned long max_page);
-#endif
+unsigned long totalram_pages = 0;
 
 int do_check_pgt_cache(int low, int high)
 {
@@ -86,7 +82,7 @@
 void show_mem(void)
 {
     unsigned long i;
-    int free = 0, total = 0, reserved = 0, nonshared = 0, shared = 0;
+    int free = 0, total = 0, reserved = 0, shared = 0;
     int cached = 0;
 
     printk("\nMem-info:\n");
@@ -101,15 +97,12 @@
 	    cached++;
 	else if (!page_count(mem_map+i))
 	    free++;
-	else if (page_count(mem_map+i) == 1)
-	    nonshared++;
 	else
 	    shared += page_count(mem_map+i) - 1;
     }
     printk("%d pages of RAM\n",total);
     printk("%d free pages\n",free);
     printk("%d reserved pages\n",reserved);
-    printk("%d pages nonshared\n",nonshared);
     printk("%d pages shared\n",shared);
     printk("%d pages swap cached\n",cached);
     printk("%ld pages in page table cache\n",pgtable_cache_size);
@@ -137,17 +130,11 @@
 
 #ifdef CONFIG_ATARI
 	if (MACH_IS_ATARI)
-		atari_stram_reserve_pages( start_mem );
-#endif
-
-#ifdef CONFIG_SUN3
-	/* reserve rom pages */
-	mmu_emu_reserve_pages(max_mapnr);
+		atari_stram_mem_init_hook();
 #endif
 
 	/* this will put all memory onto the freelists */
 	totalram_pages = free_all_bootmem();
-	printk("tp:%ld\n", totalram_pages);
 
 	for (tmp = PAGE_OFFSET ; tmp < (unsigned long)high_memory; tmp += PAGE_SIZE) {
 #if 0
@@ -201,13 +188,15 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
+	int pages = 0;
 	for (; start < end; start += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(start));
 		set_page_count(virt_to_page(start), 1);
 		free_page(start);
 		totalram_pages++;
+		pages++;
 	}
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	printk ("Freeing initrd memory: %dk freed\n", pages);
 }
 #endif
 
@@ -220,15 +209,8 @@
     val->sharedram = 0;
     val->freeram = nr_free_pages();
     val->bufferram = atomic_read(&buffermem_pages);
-    while (i-- > 0) {
-	if (PageReserved(mem_map+i))
-	    continue;
-	val->totalram++;
-	if (!page_count(mem_map+i))
-	    continue;
-	val->sharedram += page_count(mem_map+i) - 1;
-    }
     val->totalhigh = 0;
     val->freehigh = 0;
+    val->mem_unit = PAGE_SIZE;
     return;
 }
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.4.5/linux/arch/m68k/mm/memory.c	Sat May 19 17:43:05 2001
+++ linux/arch/m68k/mm/memory.c	Mon Jun 11 19:15:27 2001
@@ -39,6 +39,7 @@
 	pgd_set(pgd, (pmd_t *)BAD_PAGETABLE);
 }
 
+#if 0
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
 	pte_t *pte;
@@ -63,7 +64,9 @@
 	}
 	return (pte_t *)__pmd_page(*pmd) + offset;
 }
+#endif
 
+#if 0
 pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long offset)
 {
 	pmd_t *pmd;
@@ -84,7 +87,7 @@
 	}
 	return (pmd_t *)__pgd_page(*pgd) + offset;
 }
-
+#endif
 
 /* ++andreas: {get,free}_pointer_table rewritten to use unused fields from
    struct page instead of separately kmalloced struct.  Stolen from
@@ -250,6 +253,10 @@
 	if (voff == 0)
 		return m68k_memory[i-1].addr + m68k_memory[i-1].size;
 
+	/* As a special case allow `__pa(high_memory)'.  */
+	if (voff == 0)
+		return m68k_memory[i-1].addr + m68k_memory[i-1].size;
+
 	return mm_vtop_fallback(vaddr);
 }
 #endif
@@ -454,16 +461,21 @@
 			      ".chip 68k"		\
 			      : : "a" (paddr))
 
-/* push and invalidate page in both caches */
+/* push and invalidate page in both caches, must disable ints
+ * to avoid invalidating valid data */
 #define	pushcl040(paddr)			\
-	do { push040(paddr);			\
+	do { unsigned long flags;               \
+             save_flags(flags);                 \
+	     cli();                             \
+             push040(paddr);			\
 	     if (CPU_IS_060) clear040(paddr);	\
+	     restore_flags(flags);              \
 	} while(0)
 
 /* push page in both caches, invalidate in i-cache */
+/* RZ: cpush %bc DOES invalidate %ic, regardless of DPI */
 #define	pushcli040(paddr)			\
 	do { push040(paddr);			\
-	     if (CPU_IS_060) cleari040(paddr);	\
 	} while(0)
 
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mvme147/config.c linux/arch/m68k/mvme147/config.c
--- v2.4.5/linux/arch/m68k/mvme147/config.c	Mon Nov 27 17:11:26 2000
+++ linux/arch/m68k/mvme147/config.c	Mon Jun 11 19:15:27 2001
@@ -16,7 +16,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
@@ -29,6 +28,7 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/mvme147hw.h>
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mvme16x/config.c linux/arch/m68k/mvme16x/config.c
--- v2.4.5/linux/arch/m68k/mvme16x/config.c	Mon Jan 31 10:32:53 2000
+++ linux/arch/m68k/mvme16x/config.c	Mon Jun 11 19:15:27 2001
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
@@ -30,11 +29,10 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/mvme16xhw.h>
 
-int atari_SCC_reset_done = 1;		/* So SCC doesn't get reset */
-u_long atari_mch_cookie = 0;
 extern t_bdid mvme_bdid;
 
 static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c
--- v2.4.5/linux/arch/m68k/mvme16x/rtc.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/m68k/mvme16x/rtc.c	Mon Jun 11 19:15:27 2001
@@ -72,7 +72,7 @@
 		unsigned char mon, day, hrs, min, sec, leap_yr;
 		unsigned int yrs;
 
-		if (!suser())
+		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
 
 		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/q40/README linux/arch/m68k/q40/README
--- v2.4.5/linux/arch/m68k/q40/README	Tue Mar  6 19:44:36 2001
+++ linux/arch/m68k/q40/README	Mon Jun 11 19:15:27 2001
@@ -3,43 +3,48 @@
 
 You may try http://www.geocities.com/SiliconValley/Bay/2602/ for
 some up to date information. Booter and other tools will be also
-available from this place and ftp.uni-erlangen.de/linux/680x0/q40/
+available from this place or ftp.uni-erlangen.de/linux/680x0/q40/
 and mirrors.
 
 Hints to documentation usually refer to the linux source tree in
 /usr/src/linux/Documentation unless URL given.
 
-It seems IRQ unmasking can't be safely done on a Q40. Autoprobing is 
-not yet implemented - do not try it! (See below)
+It seems IRQ unmasking can't be safely done on a Q40. IRQ probing 
+is not implemented - do not try it! (See below)
 
-For a list of kernel commandline options read the documentation for the
+For a list of kernel command-line options read the documentation for the
 particular device drivers.
 
 The floppy imposes a very high interrupt load on the CPU, approx 30K/s.
 When something blocks interrupts (HD) it will loose some of them, so far 
-this is not known to have caused any data loss. On hihgly loaded systems
-it can make the floppy very slow or practicaly stop. Other Q40 OS' simply 
+this is not known to have caused any data loss. On highly loaded systems
+it can make the floppy very slow or practically stop. Other Q40 OS' simply 
 poll the floppy for this reason - something that can't be done in Linux.
-Only possible cure is getting a 82072 contoler with fifo instead of 
-the 8272A
+Only possible cure is getting a 82072 controller with fifo instead of 
+the 8272A.
 
-drivers used by the Q40, appart from the very obvious (console etc.):
+drivers used by the Q40, apart from the very obvious (console etc.):
 	drivers/char/q40_keyb.c		# use PC keymaps for national keyboards
 		     serial.c		# normal PC driver - any speed
 	             lp.c		# printer driver
-		char/joystick/*		# most of this should work
+		     genrtc.c		# RTC
+		char/joystick/*		# most of this should work, not 
+				        # in default config.in
 	        block/q40ide.c		# startup for ide
 		      ide*		# see Documentation/ide.txt
 		      floppy.c		# normal PC driver, DMA emu in asm/floppy.h
 					# and arch/m68k/kernel/entry.S
 					# see drivers/block/README.fd
+		net/ne.c
 		video/q40fb.c
-		misc/parport_pc.c
+		parport/*
+		sound/dmasound_core.c
+		      dmasound_q40.c
 
 Various other PC drivers can be enabled simply by adding them to 
 arch/m68k/config.in, especially 8 bit devices should be without any
 problems. For cards using 16bit io/mem more care is required, like 
-checking byteorder issues, hacking memcpy_*_io etc.
+checking byte order issues, hacking memcpy_*_io etc.
 
 
 Debugging
@@ -47,7 +52,7 @@
 
 Upon startup the kernel will usually output "ABCQGHIJ" into the SRAM, 
 preceded by the booter signature. This is a trace just in case something 
-went wrong during earliest setup stages. 
+went wrong during earliest setup stages of head.S. 
 **Changed** to preserve SRAM contents by default, this is only done when 
 requested - SRAM must start with '%LX$' signature to do this. '-d' option 
 to 'lxx' loader enables this.
@@ -55,13 +60,15 @@
 SRAM can also be used as additional console device, use debug=mem.
 This will save kernel startup msgs into SRAM, the screen will display 
 only the penguin - and shell prompt if it gets that far..
+Unfortunately only 2000 bytes are available.
 
 Serial console works and can also be used for debugging, see loader_txt
 
 Most problems seem to be caused by fawlty or badly configured io-cards or 
-harddrives anyway..there are so many things that can go wrong here.
-Make sure to configure the parallel port as SPP for first testing..the
-Q40 may have trouble with parallel interrupts.
+hard drives anyway.
+Make sure to configure the parallel port as SPP and remove IRQ/DMA jumpers
+for first testing. The Q40 does not support DMA and may have trouble with
+parallel ports version of interrupts.
 
 
 Q40 Hardware Description
@@ -71,30 +78,27 @@
 questions.
 
 The Q40 consists of a 68040@40 MHz, 1MB video RAM, up to 32MB RAM, AT-style
-keyboard interface, 1 Programmable LED, 2 8bit DACs and up to 1MB ROM, 1MB
+keyboard interface, 1 Programmable LED, 2x8bit DACs and up to 1MB ROM, 1MB
 shadow ROM.
+The Q60 has any of 68060 or 68LC060 and up to 128 MB RAM.
 
-Most interfacing like floppy, hd, serial, parallel ports is done via ISA 
+Most interfacing like floppy, IDE, serial and parallel ports is done via ISA 
 slots. The ISA io and mem range is mapped (sparse&byteswapped!) into separate 
 regions of the memory.
 The main interrupt register IIRQ_REG will indicate whether an IRQ was internal 
 or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
 
 The Q40 custom chip is programmable to provide 2 periodic timers:
-	- 50 or 200 Hz - level 2,
-	- 10 or 20 KHz - level 4 
-  !!THIS CANT BE DISABLED!!
-
+	- 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
+	- 10 or 20 KHz - level 4, used for dma-sound 
+  
 Linux uses the 200 Hz interrupt for timer and beep by default.
 
 
 Interrupts
 ==========
 
-q40 master chip handles only level triggered interrupts :-((
-
-IRQ sharing is not yet implemented but this should be only a minor
-problem..
+q40 master chip handles only a subset of level triggered interrupts.
 
 Linux has some requirements wrt interrupt architecture, these are
 to my knowledge:
@@ -103,27 +107,28 @@
 	(b) working enable/disable_irq
 
 Luckily these requirements are only important for drivers shared
-with other architectures - ide,serial,parallel, ethernet..
+with other architectures - ide,serial,parallel, ethernet.
 q40ints.c now contains a trivial hack for (a), (b) is more difficult
-because only irq's 4-15 can be disabled - and only all o them at once.
+because only irq's 4-15 can be disabled - and only all of them at once.
 Thus disable_irq() can effectively block the machine if the driver goes
 asleep.
-One thing to keep in minde when hacking around the interrupt code is 
-that there is no way to find out which IRQ caused a request.
+One thing to keep in mind when hacking around the interrupt code is 
+that there is no way to find out which IRQ caused a request, [EI]IRQ_REG
+displays current state of the various IRQ lines.
 
 Keyboard
 ========
 
 q40 receives AT make/break codes from the keyboard, these are translated to
 the PC scancodes x86 Linux uses. So by theory every national keyboard should
-work just by loading the apropriate x86 keytable - see any national-HOWTO.
+work just by loading the appropriate x86 keytable - see any national-HOWTO.
 
 Unfortunately the AT->PC translation isn't quite trivial and even worse, my 
 documentation of it is absolutely minimal - thus some exotic keys may not 
 behave exactly as expected.
 
 There is still hope that it can be fixed completely though. If you encounter 
-problems, email me idealy this:
+problems, email me ideally this:
 	- exact keypress/release sequence
 	- 'showkey -s' run on q40, non-X session
 	- 'showkey -s' run on a PC, non-X session
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/q40/config.c linux/arch/m68k/q40/config.c
--- v2.4.5/linux/arch/m68k/q40/config.c	Fri Apr  6 10:42:48 2001
+++ linux/arch/m68k/q40/config.c	Mon Jun 11 19:15:27 2001
@@ -13,11 +13,9 @@
  */
 
 #include <linux/config.h>
-#include <stdarg.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/linkage.h>
@@ -25,6 +23,7 @@
 #include <linux/major.h>
 #include <linux/serial_reg.h>
 
+#include <asm/io.h>
 #include <asm/rtc.h>
 #include <asm/bootinfo.h>
 #include <asm/system.h>
@@ -32,6 +31,7 @@
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/traps.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/q40_master.h>
 #include <asm/keyboard.h>
@@ -39,6 +39,8 @@
 extern void floppy_eject(void);
 extern void floppy_setup(char *str, int *ints);
 
+extern int q40kbd_translate(unsigned char scancode, unsigned char *keycode,
+			    char raw_mode);
 extern void q40_process_int (int level, struct pt_regs *regs);
 extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
 extern void q40_init_IRQ (void);
@@ -50,16 +52,17 @@
 static int  q40_get_hardware_list(char *buffer);
 extern int  q40_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id);
 extern void q40_sched_init(void (*handler)(int, void *, struct pt_regs *));
-extern int  q40_keyb_init(void);
-extern int  q40_kbdrate (struct kbd_repeat *);
+
 extern unsigned long q40_gettimeoffset (void);
 extern void q40_gettod (int *year, int *mon, int *day, int *hour,
                            int *min, int *sec);
 extern int q40_hwclk (int, struct hwclk_time *);
 extern int q40_set_clock_mmss (unsigned long);
 extern void q40_reset (void);
+void q40_halt(void);
 extern void q40_waitbut(void);
 void q40_set_vectors (void);
+
 extern void (*kd_mksound)(unsigned int, unsigned int);
 void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/ );
 
@@ -67,16 +70,9 @@
 extern char m68k_debug_device[];
 static void q40_mem_console_write(struct console *co, const char *b,
 				    unsigned int count);
-#if 0
-extern int ql_ticks=0;
-extern int sound_ticks=0;
-#endif
 
 extern int ql_ticks;
 
-static unsigned char bcd2bin (unsigned char b);
-static unsigned char bin2bcd (unsigned char b);
-
 static int q40_wait_key(struct console *co){return 0;}
 static struct console q40_console_driver = {
 	name:		"debug",
@@ -90,11 +86,13 @@
 extern char *q40_mem_cptr; /*=(char *)0xff020000;*/
 static int _cpleft;
 
+#if 0
 int q40_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode)
 {
         *keycodep = keycode;
         return 1;
 }
+#endif
 
 static void q40_mem_console_write(struct console *co, const char *s,
 				  unsigned int count)
@@ -130,13 +128,36 @@
 }
 #endif
 
-void q40_reset()
+static int halted=0;
+
+#ifdef CONFIG_HEARTBEAT
+static void q40_heartbeat(int on)
 {
+  if (halted) return;
 
+  if (on)
+    Q40_LED_ON();
+  else
+    Q40_LED_OFF();
+}
+#endif
+
+void q40_reset()
+{
+        halted=1;
         printk ("\n\n*******************************************\n"
 		"Called q40_reset : press the RESET button!! \n"
 		"*******************************************\n");
-	
+	Q40_LED_ON();
+	while(1) ;
+}
+void q40_halt()
+{
+        halted=1;
+        printk ("\n\n*******************\n"
+		    "  Called q40_halt\n"
+		    "*******************\n");
+	Q40_LED_ON();
 	while(1) ;
 }
 
@@ -202,17 +223,17 @@
 
 void __init config_q40(void)
 {
-    mach_sched_init      = q40_sched_init;           /* ok */
-    /*mach_kbdrate         = q40_kbdrate;*/          /* unneeded ?*/
-    mach_keyb_init       = q40_keyb_init;            /* OK */
-    mach_kbd_translate   = q40_kbd_translate;
+    mach_sched_init      = q40_sched_init;
+
+    mach_keyb_init       = q40kbd_init_hw;
+    mach_kbd_translate   = q40kbd_translate;
     mach_init_IRQ        = q40_init_IRQ;   
     mach_gettimeoffset   = q40_gettimeoffset; 
     mach_gettod  	 = q40_gettod;
     mach_hwclk           = q40_hwclk; 
     mach_set_clock_mmss	 = q40_set_clock_mmss;
-/*  mach_mksound         = q40_mksound; */
-    mach_reset		 = q40_reset;           /* use reset button instead !*/
+
+    mach_reset		 = q40_reset;
     mach_free_irq	 = q40_free_irq; 
     mach_process_int	 = q40_process_int;
     mach_get_irq_list	 = q40_get_irq_list;
@@ -220,26 +241,28 @@
     enable_irq		 = q40_enable_irq;
     disable_irq          = q40_disable_irq;
     mach_default_handler = &q40_sys_default_handler;
-    mach_get_model       = q40_get_model; /* no use..*/
-    mach_get_hardware_list = q40_get_hardware_list; /* no use */
+    mach_get_model       = q40_get_model;
+    mach_get_hardware_list = q40_get_hardware_list;
     kd_mksound             = q40_mksound;
-    /*mach_kbd_leds        = q40kbd_leds;*/
+
 #ifdef CONFIG_MAGIC_SYSRQ
     mach_sysrq_key       = 0x54;
 #endif
-    conswitchp = &dummy_con;
-#if 0 /*def CONFIG_BLK_DEV_FD*/
-    mach_floppy_setup    = floppy_setup;
-    mach_floppy_eject    = floppy_eject;
-    /**/
+#ifdef CONFIG_HEARTBEAT
+    mach_heartbeat = q40_heartbeat;
 #endif
+    mach_halt = q40_halt;
+    conswitchp = &dummy_con;
 
+    /* disable a few things that SMSQ might have left enabled */
     q40_disable_irqs();
-    mach_max_dma_address = 32*1024*1024;   /* no DMA at all, but ide-scsi requires it.. */
 
+    /* no DMA at all, but ide-scsi requires it.. make sure
+     * all physical RAM fits into the boundary - otherwise 
+     * allocator may play costly and useless tricks */
+    mach_max_dma_address = 1024*1024*1024;   
 
-/* useful for early debugging stages - writes kernel messages into SRAM */
-
+    /* useful for early debugging stages - writes kernel messages into SRAM */
     if (!strncmp( m68k_debug_device,"mem",3 ))
       {
 	/*printk("using NVRAM debug, q40_mem_cptr=%p\n",q40_mem_cptr);*/
@@ -252,109 +275,24 @@
 
 int q40_parse_bootinfo(const struct bi_record *rec)
 {
-  return 1;  /* unknown */
+  return 1;
 }
 
-#if 0
-#define DAC_LEFT  ((unsigned char *)0xff008000)
-#define DAC_RIGHT ((unsigned char *)0xff008004)
-void q40_mksound(unsigned int hz, unsigned int ticks)
-{
-  /* for now ignore hz, except that hz==0 switches off sound */
-  /* simply alternate the ampl 0-255-0-.. at 200Hz */
-  if (hz==0)
-    {
-      if (sound_ticks)
-	sound_ticks=1; /* atomic - no irq spinlock used */
-
-      *DAC_LEFT=0;
-      *DAC_RIGHT=0;
 
-      return;
-    }
-  /* sound itself is done in q40_timer_int */
-  if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */
-  sound_ticks=ticks<<1;
-}
-
-static void (*q40_timer_routine)(int, void *, struct pt_regs *);
-static short rtc_oldsecs=0;
-unsigned rtc_irq_flags=0;
-unsigned rtc_irq_ctrl=0;
-
-static void q40_timer_int (int irq, void *dev_id, struct pt_regs *fp)
-{
-#if (HZ==10000)
-    master_outb(-1,SAMPLE_CLEAR_REG);
-#else /* must be 50 or 100 */
-    master_outb(-1,FRAME_CLEAR_REG);
-#endif
-
-#if (HZ==100)
-    ql_ticks = ql_ticks ? 0 : 1;
-    if (sound_ticks)
-      {
-	unsigned char sval=(sound_ticks & 1) ? 0 : 255;
-	sound_ticks--;
-	*DAC_LEFT=sval;
-	*DAC_RIGHT=sval;
-      }
-#ifdef CONFIG_Q40RTC
-    if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS))
-      {
-	rtc_oldsecs = RTC_SECS;
-	rtc_irq_flags = RTC_UIE;
-	rtc_interrupt();
-      }
-#endif
-    if (ql_ticks) return;
-#endif
-    q40_timer_routine(irq, dev_id, fp);
+static inline unsigned char bcd2bin (unsigned char b)
+{
+	return ((b>>4)*10 + (b&15));
 }
-#endif
 
-#if 0
-extern void (*q40_timer_routine)(int, void *, struct pt_regs *);
-extern void q40_timer_int();
-
-void q40_sched_init (void (*timer_routine)(int, void *, struct pt_regs *))
+static inline unsigned char bin2bcd (unsigned char b)
 {
-    int timer_irq;
-
-    q40_timer_routine = timer_routine;
-
-#if (HZ==10000)
-    timer_irq=Q40_IRQ_TIMER;
-#else
-    timer_irq=Q40_IRQ_FRAME;
-#endif
-
-    /*printk("registering sched/timer IRQ %d\n", timer_irq);*/
-
-    if (request_irq(timer_irq, q40_timer_int, 0,
-				"timer", q40_timer_int))
-	panic ("Couldn't register timer int");
-
-#if (HZ==10000)
-    master_outb(SAMPLE_LOW,SAMPLE_RATE_REG);
-    master_outb(-1,SAMPLE_CLEAR_REG);
-    master_outb(1,SAMPLE_ENABLE_REG);
-#else
-    master_outb(-1,FRAME_CLEAR_REG);   /* not necessary ? */
-#if (HZ==100)
-    master_outb( 1,FRAME_RATE_REG);
-#endif
-#endif
+	return (((b/10)*16) + (b%10));
 }
-#endif
+
 
 unsigned long q40_gettimeoffset (void)
 {
-#if (HZ==100)
     return 5000*(ql_ticks!=0);
-#else
-    return 0;
-#endif
 }
 
 extern void q40_gettod (int *year, int *mon, int *day, int *hour,
@@ -362,7 +300,7 @@
 {
 	RTC_CTRL |= RTC_READ;
 	*year = bcd2bin (RTC_YEAR);
-	*mon = bcd2bin (RTC_MNTH)-1;
+	*mon = bcd2bin (RTC_MNTH);
 	*day = bcd2bin (RTC_DATE);
 	*hour = bcd2bin (RTC_HOUR);
 	*min = bcd2bin (RTC_MINS);
@@ -371,15 +309,6 @@
 
 }
 
-static unsigned char bcd2bin (unsigned char b)
-{
-	return ((b>>4)*10 + (b&15));
-}
-
-static unsigned char bin2bcd (unsigned char b)
-{
-	return (((b/10)*16) + (b%10));
-}
 
 
 /*
@@ -439,8 +368,6 @@
 /*
  * Set the minutes and seconds from seconds value 'nowtime'.  Fail if
  * clock is out by > 30 minutes.  Logic lifted from atari code.
- * Algorithm is to wait for the 10ms register to change, and then to
- * wait a short while, and then set it.
  */
 
 int q40_set_clock_mmss (unsigned long nowtime)
@@ -469,18 +396,3 @@
 	return retval;
 }
 
-extern void q40kbd_init_hw(void);
-
-int q40_keyb_init (void)
-{
-        q40kbd_init_hw();
-	return 0;
-}
-
-#if 0
-/* dummy to cause */
-void q40_slow_io()
-{
-  return;
-}
-#endif
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/q40/q40ints.c linux/arch/m68k/q40/q40ints.c
--- v2.4.5/linux/arch/m68k/q40/q40ints.c	Mon Nov 27 17:11:26 2000
+++ linux/arch/m68k/q40/q40ints.c	Mon Jun 11 19:15:27 2001
@@ -1,7 +1,7 @@
 /*
  * arch/m68k/q40/q40ints.c
  *
- * Copyright (C) 1999 Richard Zidlicky
+ * Copyright (C) 1999,2001 Richard Zidlicky
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
@@ -44,7 +44,7 @@
 void q40_irq2_handler (int, void *, struct pt_regs *fp);
 
 
-extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);  /* added just for debugging */
+extern void (*q40_sys_default_handler[]) (int, void *, struct pt_regs *);
 
 static void q40_defhand (int irq, void *dev_id, struct pt_regs *fp);
 static void sys_default_handler(int lev, void *dev_id, struct pt_regs *regs);
@@ -97,9 +97,9 @@
 	sys_request_irq(IRQ2,q40_irq2_handler, 0, "q40 ISA and master chip", NULL);
 
 	/* now enable some ints.. */
-	master_outb(1,EXT_ENABLE_REG);  /* hm, aint that too early? */
+	master_outb(1,EXT_ENABLE_REG);  /* ISA IRQ 5-15 */
 
-	/* would be spurious ints by now, q40kbd_init_hw() does that */
+	/* make sure keyboard IRQ is disabled */
 	master_outb(0,KEY_IRQ_ENABLE_REG);
 }
 
@@ -139,7 +139,7 @@
 	    if (dev_id==NULL)
 		  {
 		printk("WARNING: dev_id == NULL in request_irq\n");
-		dev_id=1;
+		dev_id=(void*)1;
 	      }
 	    irq_tab[irq].handler = handler;
 	    irq_tab[irq].flags   = flags;
@@ -202,7 +202,8 @@
 /* 
  * this stuff doesn't really belong here..
 */
-int ql_ticks=0;
+
+int ql_ticks=0;              /* 200Hz ticks since last jiffie */
 static int sound_ticks=0;
 
 #define SVOL 45
@@ -214,7 +215,7 @@
   if (hz==0)
     {
       if (sound_ticks)
-	sound_ticks=1; /* atomic - no irq spinlock used */
+	sound_ticks=1;
 
       *DAC_LEFT=128;
       *DAC_RIGHT=128;
@@ -227,14 +228,9 @@
 }
 
 static void (*q40_timer_routine)(int, void *, struct pt_regs *);
-static short rtc_oldsecs=0;
-unsigned rtc_irq_flags=0;
-unsigned rtc_irq_ctrl=0;
 
 static void q40_timer_int (int irq, void * dev, struct pt_regs * regs)
 {
-
-  
 #if (HZ==100)
     ql_ticks = ql_ticks ? 0 : 1;
     if (sound_ticks)
@@ -244,12 +240,12 @@
 	*DAC_LEFT=sval;
 	*DAC_RIGHT=sval;
       }
-#ifdef CONFIG_Q40RTC
-    if (rtc_irq_ctrl && (rtc_oldsecs != RTC_SECS))
+#if defined(CONFIG_Q40RTC) || defined(CONFIG_GEN_RTC)
+    if (gen_rtc_irq_ctrl && (q40rtc_oldsecs != RTC_SECS))
       {
-	rtc_oldsecs = RTC_SECS;
-	rtc_irq_flags = RTC_UIE;
-	rtc_interrupt();
+	q40rtc_oldsecs = RTC_SECS;
+	gen_rtc_irq_flags = RTC_UIE;
+	gen_rtc_interrupt(0);
       }
 #endif
     if (ql_ticks) return;
@@ -322,16 +318,14 @@
 static int ccleirq=60;    /* ISA dev IRQ's*/
 /*static int cclirq=60;*/     /* internal */
 
-/* FIX: add shared ints,mask,unmask,probing.... */
-
+/* FIXME: add shared ints,mask,unmask,probing.... */
 
 #define IRQ_INPROGRESS 1
 /*static unsigned short saved_mask;*/
 static int do_tint=0;
 
 #define DEBUG_Q40INT
-#define IP_USE_DISABLE /* would be nice, but crashes ???? */
-/*static int dd_count=0;*/
+/*#define IP_USE_DISABLE *//* would be nice, but crashes ???? */
 
 static int mext_disabled=0;  /* ext irq disabled by master chip? */
 static int aliased_irq=0;  /* how many times inside handler ?*/
@@ -404,40 +398,36 @@
 		    if ( disabled ) 
 		      {
 #ifdef IP_USE_DISABLE
-		  if (irq>4){
-		    disabled=0;
-		    /*dd_count--;*/
-		    enable_irq(irq);}
+			if (irq>4){
+			  disabled=0;
+			  enable_irq(irq);}
 #else
-		  disabled=0;
+			disabled=0;
 			/*printk("reenabling irq %d\n",irq); */
-#if 0
-		  fp->sr = ((fp->sr) & (~0x700)); /* unneeded ?! */
-#endif
 #endif
 		      }
 	      goto repeat;  /* return;  */
 		  }
 	      }
-      if (mer && ccleirq>0 && !aliased_irq) 
+	    if (mer && ccleirq>0 && !aliased_irq) 
 	      printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--;
 	  } 
  iirq:
-  mir=master_inb(IIRQ_REG);
-  if (mir&IRQ_FRAME_MASK) 
+	mir=master_inb(IIRQ_REG);
+	if (mir&IRQ_FRAME_MASK) 
 	  {
-      do_tint++;
-      master_outb(-1,FRAME_CLEAR_REG);
-    }
-  for(;do_tint>0;do_tint--) 
-	      {
-      irq_tab[Q40_IRQ_FRAME].count++;
-      irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);    
-    }
-  if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/
-		      {
-      irq_tab[Q40_IRQ_KEYBOARD].count++;
-      irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
+	    do_tint++;
+	    master_outb(-1,FRAME_CLEAR_REG);
+	  }
+	for(;do_tint>0;do_tint--) 
+	  {
+	    irq_tab[Q40_IRQ_FRAME].count++;
+	    irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp);    
+	  }
+	if (mir&IRQ_KEYB_MASK) /* may handle it even if actually disabled*/
+	  {
+	    irq_tab[Q40_IRQ_KEYBOARD].count++;
+	    irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp);
 	  }
 }
 
@@ -499,7 +489,7 @@
 void q40_disable_irq (unsigned int irq)
 {
   /* disable ISA iqs : only do something if the driver has been
-  * verified to be Q40 "compatible" - right now only IDE
+  * verified to be Q40 "compatible" - right now IDE, NE2K
   * Any driver should not attempt to sleep accross disable_irq !!
   */
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/Makefile linux/arch/m68k/sun3/Makefile
--- v2.4.5/linux/arch/m68k/sun3/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/sun3/Makefile	Mon Jun 11 19:15:27 2001
@@ -14,7 +14,9 @@
 
 export-objs	:= sun3_ksyms.o
 
-obj-y		:= config.o idprom.o mmu_emu.o sun3ints.o leds.o dvma.o \
-			sbus.o intersil.o sun3_ksyms.o
+obj-y	:= sun3_ksyms.o sun3ints.o sun3dvma.o sbus.o
+
+obj-$(CONFIG_SUN3) += config.o idprom.o mmu_emu.o leds.o dvma.o \
+			intersil.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/config.c linux/arch/m68k/sun3/config.c
--- v2.4.5/linux/arch/m68k/sun3/config.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/sun3/config.c	Mon Jun 11 19:15:27 2001
@@ -8,13 +8,10 @@
  * for more details.
  */
 
-#include <stdarg.h>
-
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/kd.h>
 #include <linux/tty.h>
 #include <linux/console.h>
 #include <linux/init.h>
@@ -27,10 +24,12 @@
 #include <asm/pgtable.h>
 #include <asm/sun3-head.h>
 #include <asm/sun3mmu.h>
+#include <asm/rtc.h>
 #include <asm/machdep.h>
 #include <asm/intersil.h>
 #include <asm/irq.h>
 #include <asm/segment.h>
+#include <asm/sun3ints.h>
 
 extern char _text, _end;
 
@@ -39,15 +38,6 @@
 extern unsigned long sun3_gettimeoffset(void);
 extern int sun3_get_irq_list (char *);
 extern void sun3_sched_init(void (*handler)(int, void *, struct pt_regs *));
-extern void sun3_init_IRQ (void);
-extern void (*sun3_default_handler[]) (int, void *, struct pt_regs *);
-extern int sun3_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-                              unsigned long flags, const char *devname, void *dev_id);
-extern void sun3_free_irq (unsigned int irq, void *dev_id);
-extern void sun3_enable_irq (unsigned int);
-extern void sun3_disable_irq (unsigned int);
-extern void sun3_enable_interrupts (void);
-extern void sun3_disable_interrupts (void);
 extern void sun3_get_model (char* model);
 extern void idprom_init (void);
 extern void sun3_gettod (int *yearp, int *monp, int *dayp,
@@ -56,7 +46,7 @@
 
 extern void sun_serial_setup(void);
 volatile char* clock_va; 
-extern unsigned char* sun3_intreg;
+extern volatile unsigned char* sun3_intreg;
 extern unsigned long availmem;
 unsigned long num_pages;
 
@@ -76,7 +66,7 @@
 	prom_init((void *)LINUX_OPPROM_BEGVM);
 		
 	GET_CONTROL_BYTE(AC_SENABLE,enable_register);
-	enable_register |= 0x40; /* Enable FPU */	
+	enable_register |= 0x50; /* Enable FPU */	
 	SET_CONTROL_BYTE(AC_SENABLE,enable_register);
 	GET_CONTROL_BYTE(AC_SENABLE,enable_register);
 	
@@ -154,6 +144,7 @@
 //	mach_keyb_init       =  sun3_keyb_init;
 	enable_irq     	     =  sun3_enable_irq;
         disable_irq  	     =  sun3_disable_irq;
+	mach_process_int     =  sun3_process_int;
         mach_get_irq_list    =  sun3_get_irq_list;
         mach_gettod          =  sun3_gettod;	
         mach_reset           =  sun3_reboot;
@@ -161,7 +152,7 @@
 	mach_get_model	     =  sun3_get_model;
 	mach_hwclk           =  sun3_hwclk;
 	mach_halt	     =  sun3_halt;
-#ifndef CONFIG_SERIAL_CONSOLE
+#if !defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_FB)
 	conswitchp 	     = &dummy_con;
 #endif
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/dvma.c linux/arch/m68k/sun3/dvma.c
--- v2.4.5/linux/arch/m68k/sun3/dvma.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/sun3/dvma.c	Mon Jun 11 19:15:27 2001
@@ -4,42 +4,62 @@
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/bootmem.h>
+#include <linux/list.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/sun3mmu.h>
 #include <asm/dvma.h>
 
-unsigned long dvma_next_free = DVMA_START;
-unsigned long dvma_region_end = DVMA_START + (DVMA_RESERVED_PMEGS * SUN3_PMEG_SIZE);
 
+static unsigned long ptelist[120];
 
-/* reserve such dma memory as we see fit */
-void sun3_dvma_init(void)
+inline unsigned long dvma_page(unsigned long kaddr, unsigned long vaddr)
 {
-	unsigned long dvma_phys_start;
-	
-	dvma_phys_start = (sun3_get_pte(DVMA_START) & 
-			   SUN3_PAGE_PGNUM_MASK);
-	dvma_phys_start <<= PAGE_SHIFT;
+	unsigned long pte;
+	unsigned long j;
+	pte_t ptep;
 	
-	reserve_bootmem(dvma_phys_start,
-			(DVMA_RESERVED_PMEGS * SUN3_PMEG_SIZE));
+	j = *(volatile unsigned long *)kaddr;
+	*(volatile unsigned long *)kaddr = j;
 
-}
+	ptep = __mk_pte(kaddr, PAGE_KERNEL);
+	pte = pte_val(ptep);
+//		printk("dvma_remap: addr %lx -> %lx pte %08lx len %x\n", 
+//		       kaddr, vaddr, pte, len);
+	if(ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] != pte) {
+		sun3_put_pte(vaddr, pte);
+		ptelist[(vaddr & 0xff000) >> PAGE_SHIFT] = pte;
+	}
 
-/* get needed number of free dma pages, or panic if not enough */
+	return (vaddr + (kaddr & ~PAGE_MASK));
 
-void *sun3_dvma_malloc(int len)
+}
+
+int dvma_map_iommu(unsigned long kaddr, unsigned long baddr, 
+			      int len)
 {
+
+	unsigned long end;
 	unsigned long vaddr;
 
-       	if((dvma_next_free + len) > dvma_region_end) 
-		panic("sun3_dvma_malloc: out of dvma pages");
+	vaddr = dvma_btov(baddr);
+
+	end = vaddr + len;
 	
-	vaddr = dvma_next_free;
-	dvma_next_free = DVMA_ALIGN(dvma_next_free + len);
+	while(vaddr < end) {
+		dvma_page(kaddr, vaddr);
+		kaddr += PAGE_SIZE;
+		vaddr += PAGE_SIZE;
+	}
+
+	return 0;
 
-	return (void *)vaddr;
 }
-     
 
+void sun3_dvma_init(void)
+{
+
+	memset(ptelist, 0, sizeof(ptelist));
+
+
+}
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/intersil.c linux/arch/m68k/sun3/intersil.c
--- v2.4.5/linux/arch/m68k/sun3/intersil.c	Wed Jan 26 12:44:21 2000
+++ linux/arch/m68k/sun3/intersil.c	Mon Jun 11 19:15:27 2001
@@ -11,9 +11,9 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/kd.h>
 
 #include <asm/system.h>
+#include <asm/rtc.h>
 #include <asm/intersil.h>
 
 
@@ -30,7 +30,7 @@
 void sun3_gettod (int *yearp, int *monp, int *dayp,
                    int *hourp, int *minp, int *secp)
 {
-	u_char wday;
+	unsigned char wday;
 	volatile struct intersil_dt* todintersil;
 	unsigned long flags;
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/mmu_emu.c linux/arch/m68k/sun3/mmu_emu.c
--- v2.4.5/linux/arch/m68k/sun3/mmu_emu.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/sun3/mmu_emu.c	Mon Jun 11 19:15:27 2001
@@ -29,6 +29,7 @@
 extern void prom_reboot (char *) __attribute__ ((__noreturn__));
 
 #undef DEBUG_MMU_EMU
+#define DEBUG_PROM_MAPS
 
 /*
 ** Defines
@@ -157,9 +158,12 @@
 	j = 0;
 	for (num=0, seg=0x0F800000; seg<0x10000000; seg+=16*PAGE_SIZE) {
 		if (sun3_get_segmap (seg) != SUN3_INVALID_PMEG) {
-#ifdef DEBUG_MMU_EMU
-			printk ("mapped:");
-			print_pte_vaddr (seg);
+#ifdef DEBUG_PROM_MAPS
+			for(i = 0; i < 16; i++) {
+				printk ("mapped:");
+				print_pte_vaddr (seg + (i*PAGE_SIZE));
+				break;
+			}
 #endif
 			// the lowest mapping here is the end of our
 			// vmalloc region
@@ -174,7 +178,7 @@
 	}
 
 	
-	sun3_dvma_init();
+	dvma_init();
 	
 	
 	/* blank everything below the kernel, and we've got the base
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sbus.c linux/arch/m68k/sun3/sbus.c
--- v2.4.5/linux/arch/m68k/sun3/sbus.c	Wed Sep  8 11:20:42 1999
+++ linux/arch/m68k/sun3/sbus.c	Mon Jun 11 19:15:27 2001
@@ -12,8 +12,12 @@
 #include <linux/types.h>
 #include <linux/init.h>
 
+extern void rs_init(void);
+
 void __init sbus_init(void)
 {
+
+	rs_init();
 
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sun3_ksyms.c linux/arch/m68k/sun3/sun3_ksyms.c
--- v2.4.5/linux/arch/m68k/sun3/sun3_ksyms.c	Fri Jan 28 08:04:58 2000
+++ linux/arch/m68k/sun3/sun3_ksyms.c	Mon Jun 11 19:15:27 2001
@@ -6,5 +6,8 @@
 /*
  * Add things here when you find the need for it.
  */
-EXPORT_SYMBOL(sun3_dvma_malloc);
+EXPORT_SYMBOL(dvma_map_align);
+EXPORT_SYMBOL(dvma_unmap);
+EXPORT_SYMBOL(dvma_malloc_align);
+EXPORT_SYMBOL(dvma_free);
 EXPORT_SYMBOL(idprom);
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sun3dvma.c linux/arch/m68k/sun3/sun3dvma.c
--- v2.4.5/linux/arch/m68k/sun3/sun3dvma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3/sun3dvma.c	Mon Jun 11 19:15:27 2001
@@ -0,0 +1,295 @@
+/*
+ * linux/arch/m68k/mm/sun3dvma.c
+ *
+ * Copyright (C) 2000 Sam Creasey
+ *
+ * Contains common routines for sun3/sun3x DVMA management.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/list.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/dvma.h>
+
+#ifdef CONFIG_SUN3X
+extern void dvma_unmap_iommu(unsigned long baddr, int len);
+#else
+static inline void dvma_unmap_iommu(unsigned long a, int b)
+{
+}
+#endif
+
+unsigned long iommu_use[IOMMU_TOTAL_ENTRIES];
+
+#define dvma_index(baddr) ((baddr - DVMA_START) >> DVMA_PAGE_SHIFT)
+
+#define dvma_entry_use(baddr)		(iommu_use[dvma_index(baddr)])
+
+struct hole {
+	unsigned long start;
+	unsigned long end;
+	unsigned long size;
+	struct list_head list;
+};
+
+static struct list_head hole_list;
+static struct list_head hole_cache;
+static struct hole initholes[64];
+
+static inline int refill(void)
+{
+
+	struct hole *hole;
+	struct hole *prev = NULL;
+	struct list_head *cur;
+	int ret = 0;
+	
+	list_for_each(cur, &hole_list) {
+		hole = list_entry(cur, struct hole, list);
+
+		if(!prev) {
+			prev = hole;
+			continue;
+		}
+		
+		if(hole->end == prev->start) {
+			hole->size += prev->size;
+			hole->end = prev->end;
+			list_del(&(prev->list));
+			list_add(&(prev->list), &hole_cache);
+			ret++;
+		}
+		
+	}
+
+	return ret;
+}
+	
+static inline struct hole *rmcache(void)
+{
+	struct hole *ret;
+
+	if(list_empty(&hole_cache)) {
+		if(!refill()) {
+			printk("out of dvma hole cache!\n");
+			BUG();
+		}
+	}
+
+	ret = list_entry(hole_cache.next, struct hole, list);
+	list_del(&(ret->list));
+
+	return ret;
+
+}
+
+static inline unsigned long get_baddr(int len, unsigned long align)
+{
+	
+	struct list_head *cur;
+	struct hole *hole;
+
+	if(list_empty(&hole_list)) {
+		printk("out of dvma holes!\n");
+		BUG();
+	}
+
+	list_for_each(cur, &hole_list) {
+		unsigned long newlen;
+
+		hole = list_entry(cur, struct hole, list);
+
+		if(align > DVMA_PAGE_SIZE) 
+			newlen = len + ((hole->end - len) & (align-1));
+		else
+			newlen = len;
+		
+		if(hole->size > newlen) {
+			hole->end -= newlen;
+			hole->size -= newlen;
+			dvma_entry_use(hole->end) = newlen;
+			return hole->end;
+		} else if(hole->size == newlen) {
+			list_del(&(hole->list));
+			list_add(&(hole->list), &hole_cache);
+			dvma_entry_use(hole->start) = newlen;
+			return hole->start;
+		}
+
+	}
+
+	printk("unable to find dvma hole!\n");
+	BUG();
+	return 0;
+}
+
+static inline int free_baddr(unsigned long baddr)
+{
+	
+	unsigned long len;
+	struct hole *hole;
+	struct list_head *cur;
+	unsigned long orig_baddr;
+
+	orig_baddr = baddr;
+	len = dvma_entry_use(baddr);
+	dvma_entry_use(baddr) = 0;
+	baddr &= DVMA_PAGE_MASK;
+	dvma_unmap_iommu(baddr, len);
+
+	list_for_each(cur, &hole_list) {
+		hole = list_entry(cur, struct hole, list);
+		
+		if(hole->end == baddr) {
+			hole->end += len;
+			hole->size += len;
+			return 0;
+		} else if(hole->start == (baddr + len)) {
+			hole->start = baddr;
+			hole->size += len;
+			return 0;
+		}
+
+	}
+
+	hole = rmcache();
+	
+	hole->start = baddr;
+	hole->end = baddr + len;
+	hole->size = len;
+	
+//	list_add_tail(&(hole->list), cur);
+	list_add(&(hole->list), cur);
+	
+	return 0;
+	
+}
+
+void dvma_init(void)
+{
+	
+	struct hole *hole;
+	int i;
+
+	INIT_LIST_HEAD(&hole_list);
+	INIT_LIST_HEAD(&hole_cache);
+
+	/* prepare the hole cache */
+	for(i = 0; i < 64; i++) 
+		list_add(&(initholes[i].list), &hole_cache);
+		
+	hole = rmcache();
+	hole->start = DVMA_START;
+	hole->end = DVMA_END;
+	hole->size = DVMA_SIZE;
+	
+	list_add(&(hole->list), &hole_list);
+
+	memset(iommu_use, 0, sizeof(iommu_use));
+
+	dvma_unmap_iommu(DVMA_START, DVMA_SIZE);
+
+#ifdef CONFIG_SUN3
+	sun3_dvma_init();
+#endif
+
+}
+
+inline unsigned long dvma_map_align(unsigned long kaddr, int len, int align)
+{
+
+	unsigned long baddr;
+	unsigned long off;
+
+	if(!len)
+		len = 0x800;
+
+	if(!kaddr || !len) {
+//		printk("error: kaddr %lx len %x\n", kaddr, len);
+//		*(int *)4 = 0;
+		return 0;
+	}
+
+#ifdef DEBUG
+	printk("dvma_map request %08lx bytes from %08lx\n", 
+	       len, kaddr);
+#endif
+	off = kaddr & ~DVMA_PAGE_MASK;
+	kaddr &= PAGE_MASK;
+	len += off;
+	len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK);
+
+	if(align == 0)
+		align = DVMA_PAGE_SIZE;
+	else
+		align = ((align + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK);
+
+	baddr = get_baddr(len, align);
+//	printk("using baddr %lx\n", baddr);
+
+	if(!dvma_map_iommu(kaddr, baddr, len))
+		return (baddr + off);
+	
+	printk("dvma_map failed kaddr %lx baddr %lx len %x\n", kaddr, baddr, len);
+	BUG();
+	return 0;
+}
+
+void dvma_unmap(void *baddr)
+{
+
+	free_baddr((unsigned long)baddr);
+	
+	return;
+
+}
+
+
+void *dvma_malloc_align(unsigned long len, unsigned long align)
+{
+	unsigned long kaddr;
+	unsigned long baddr;
+	unsigned long vaddr;
+
+	if(!len)
+		return NULL;
+
+#ifdef DEBUG
+	printk("dvma_malloc request %lx bytes\n", len);
+#endif
+	len = ((len + (DVMA_PAGE_SIZE-1)) & DVMA_PAGE_MASK);
+
+        if((kaddr = __get_free_pages(GFP_ATOMIC, get_order(len))) == 0)
+		return NULL;
+
+	if((baddr = (unsigned long)dvma_map_align(kaddr, len, align)) == 0) {
+		free_pages(kaddr, get_order(len));
+		return NULL;
+	}
+
+	vaddr = dvma_btov(baddr);
+
+	if(dvma_map_cpu(kaddr, vaddr, len) < 0) {
+		dvma_unmap((void *)baddr);
+		free_pages(kaddr, get_order(len));
+		return NULL;
+	}
+
+#ifdef DEBUG
+	printk("mapped %08lx bytes %08lx kern -> %08lx bus\n",
+	       len, kaddr, baddr);
+#endif
+
+	return (void *)vaddr;
+
+}
+
+void dvma_free(void *vaddr)
+{
+
+	return;
+
+}
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3/sun3ints.c linux/arch/m68k/sun3/sun3ints.c
--- v2.4.5/linux/arch/m68k/sun3/sun3ints.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/sun3/sun3ints.c	Mon Jun 11 19:15:27 2001
@@ -1,5 +1,5 @@
  /*
- * linux/arch/m68k/sun3/sun3ints.c -- Sun-3 Linux interrupt handling code
+ * linux/arch/m68k/sun3/sun3ints.c -- Sun-3(x) Linux interrupt handling code
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file COPYING in the main directory of this archive
@@ -35,7 +35,7 @@
        ~(0x10), ~(0x08)
 };
 
-unsigned char* sun3_intreg;
+volatile unsigned char* sun3_intreg;
 
 void sun3_insert_irq(irq_node_t **list, irq_node_t *node)
 {
@@ -45,10 +45,6 @@
 {
 }
 
-void sun3_free_irq(unsigned int irq, void *dev_id)
-{
-}
-
 void sun3_enable_irq(unsigned int irq)
 {
 	*sun3_intreg |=  (1<<irq);
@@ -71,41 +67,54 @@
 	return 0;
 }
 
+static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
+{
+	sun3_do_irq(irq,fp);
+	if(!(kstat.irqs[0][SYS_IRQS + irq] % 2000)) 
+		sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%16000)/2000]);
+}
+
 static void sun3_int5(int irq, void *dev_id, struct pt_regs *fp)
 {
         kstat.irqs[0][SYS_IRQS + irq]++;
-        *sun3_intreg &= ~(1<<irq);
+#ifdef CONFIG_SUN3
 	intersil_clear();
+#endif
+        *sun3_intreg &= ~(1<<irq);
         *sun3_intreg |=  (1<<irq);
+#ifdef CONFIG_SUN3
+	intersil_clear();
+#endif
         do_timer(fp);
         if(!(kstat.irqs[0][SYS_IRQS + irq] % 20))
                 sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%160)
                 /20]);
 }
 
-static void sun3_int7(int irq, void *dev_id, struct pt_regs *fp)
-{
-	sun3_do_irq(irq,fp);
-	if(!(kstat.irqs[0][SYS_IRQS + irq] % 2000)) 
-		sun3_leds(led_pattern[(kstat.irqs[0][SYS_IRQS+irq]%16000)/2000]);
-}
-
 /* handle requested ints, excepting 5 and 7, which always do the same
    thing */
 static void *dev_ids[SYS_IRQS];
-static void (*inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
+static void (*sun3_inthandler[SYS_IRQS])(int, void *, struct pt_regs *) = {
 	NULL, NULL, NULL, NULL, NULL, sun3_int5, NULL, sun3_int7
 };
+static void (*sun3_vechandler[192])(int, void *, struct pt_regs *);
+static void *vec_ids[192];
+static char *vec_names[192];
 
 static void sun3_inthandle(int irq, void *dev_id, struct pt_regs *fp)
 {
-	if(inthandler[irq] == NULL)
+	if(sun3_inthandler[irq] == NULL)
 		panic ("bad interrupt %d received (id %p)\n",irq, dev_id);
 
         kstat.irqs[0][SYS_IRQS + irq]++;
         *sun3_intreg &= ~(1<<irq);
 
-	inthandler[irq](irq, dev_ids[irq], fp);
+	sun3_inthandler[irq](irq, dev_ids[irq], fp);
+}
+
+static void sun3_vec255(int irq, void *dev_id, struct pt_regs *fp)
+{
+//	intersil_clear();
 }
 
 void (*sun3_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
@@ -120,6 +129,8 @@
 {
 	int i;
 
+	*sun3_intreg = 1;
+
 	for(i = 0; i < SYS_IRQS; i++)
 	{
 		if(dev_names[i])
@@ -127,25 +138,94 @@
 					0, dev_names[i], NULL);
 	}
 
+	for(i = 0; i < 192; i++) 
+		sun3_vechandler[i] = NULL;
+	
+	sun3_vechandler[191] = sun3_vec255;
 }
                                 
 int sun3_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
                       unsigned long flags, const char *devname, void *dev_id)
 {
-	if(inthandler[irq] != NULL) {
-		printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
-		return -1;
-	}
 
-	inthandler[irq] = handler;
-	dev_ids[irq] = dev_id;
-	dev_names[irq] = devname;
+	if(irq < SYS_IRQS) {
+		if(sun3_inthandler[irq] != NULL) {
+			printk("sun3_request_irq: request for irq %d -- already taken!\n", irq);
+			return 1;
+		}
+		
+		sun3_inthandler[irq] = handler;
+		dev_ids[irq] = dev_id;
+		dev_names[irq] = devname;
+		
+		/* setting devname would be nice */
+		sys_request_irq(irq, sun3_default_handler[irq], 0, devname, NULL);
+
+		return 0;
+	} else {
+		if((irq >= 64) && (irq <= 255)) {
+		        int vec;
+
+			vec = irq - 64;
+			if(sun3_vechandler[vec] != NULL) {
+				printk("sun3_request_irq: request for vec %d -- already taken!\n", irq);
+				return 1;
+			}
+
+			sun3_vechandler[vec] = handler;
+			vec_ids[vec] = dev_id;
+			vec_names[vec] = devname;
+			
+			return 0;
+		}
+	}
 
-	/* setting devname would be nice */
-	
-	sys_request_irq(irq, sun3_default_handler[irq], 0, devname, NULL);
-	
+	printk("sun3_request_irq: invalid irq %d\n", irq);
+	return 1;
 
-	return 0;
 }
                         
+void sun3_free_irq(unsigned int irq, void *dev_id)
+{
+
+	if(irq < SYS_IRQS) {
+		if(sun3_inthandler[irq] == NULL) 
+			panic("sun3_free_int: attempt to free unused irq %d\n", irq);
+		if(dev_ids[irq] != dev_id)
+			panic("sun3_free_int: incorrect dev_id for irq %d\n", irq);
+		
+		sun3_inthandler[irq] = NULL;
+		return;
+	} else if((irq >= 64) && (irq <= 255)) {
+		int vec;
+
+		vec = irq - 64;
+		if(sun3_vechandler[vec] == NULL)
+			panic("sun3_free_int: attempt to free unused vector %d\n", irq);
+		if(vec_ids[irq] != dev_id)
+			panic("sun3_free_int: incorrect dev_id for vec %d\n", irq);
+		
+		sun3_vechandler[vec] = NULL;
+		return;
+	} else {
+		panic("sun3_free_irq: invalid irq %d\n", irq);
+	}		
+}
+
+void sun3_process_int(int irq, struct pt_regs *regs)
+{
+
+	if((irq >= 64) && (irq <= 255)) {
+		int vec;
+
+		vec = irq - 64;
+		if(sun3_vechandler[vec] == NULL) 
+			panic ("bad interrupt vector %d received\n",irq);
+			
+		sun3_vechandler[vec](irq, vec_ids[vec], regs);
+		return;
+	} else {
+		panic("sun3_process_int: unable to handle interrupt vector %d\n",
+		      irq);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/Makefile linux/arch/m68k/sun3x/Makefile
--- v2.4.5/linux/arch/m68k/sun3x/Makefile	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/sun3x/Makefile	Mon Jun 11 19:15:27 2001
@@ -9,6 +9,6 @@
 
 O_TARGET := sun3x.o
 
-obj-y		:= config.o time.o dvma.o sbus.o
+obj-y		:= config.o time.o dvma.o prom.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/config.c linux/arch/m68k/sun3x/config.c
--- v2.4.5/linux/arch/m68k/sun3x/config.c	Thu Aug 26 12:42:31 1999
+++ linux/arch/m68k/sun3x/config.c	Mon Jun 11 19:15:27 2001
@@ -14,39 +14,24 @@
 #include <asm/system.h>
 #include <asm/machdep.h>
 #include <asm/irq.h>
-#include <asm/sun3x.h>
+#include <asm/sun3xprom.h>
+#include <asm/sun3ints.h>
+#include <asm/setup.h>
 
 #include "time.h"
 
-static volatile unsigned char *sun3x_intreg = (unsigned char *)SUN3X_INTREG;
-extern int serial_console;
+volatile char *clock_va;
+extern volatile unsigned char *sun3_intreg;
 
-void sun3x_halt(void)
-{
-    /* Disable interrupts */
-    cli();
-
-    /* we can't drop back to PROM, so we loop here */
-    for (;;);
-}
-
-void sun3x_reboot(void)
-{
-    /* This never returns, don't bother saving things */
-    cli();
-
-    /* no idea, whether this works */
-    asm ("reset");
-}
 
 int __init sun3x_keyb_init(void)
 {
-    return 0;
+	return 0;
 }
 
 int sun3x_kbdrate(struct kbd_repeat *r)
 {
-    return 0;
+	return 0;
 }
 
 void sun3x_kbd_leds(unsigned int i)
@@ -54,36 +39,15 @@
 
 }
 
-static void sun3x_badint (int irq, void *dev_id, struct pt_regs *fp)
+void sun3_leds(unsigned int i)
 {
-    printk ("received spurious interrupt %d\n",irq);
-    num_spurious += 1;
-}
 
-void (*sun3x_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = {
-    sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint,
-    sun3x_badint, sun3x_badint, sun3x_badint, sun3x_badint
-};
-
-void sun3x_enable_irq(unsigned int irq)
-{
-    *sun3x_intreg |= (1 << irq);
 }
 
-void sun3x_disable_irq(unsigned int irq)
+/* should probably detect types of these eventually. */
+static void sun3x_get_model(char *model)
 {
-    *sun3x_intreg &= ~(1 << irq);
-}
-
-void __init sun3x_init_IRQ(void)
-{
-    /* disable all interrupts initially */
-    *sun3x_intreg = 1;  /* master enable only */
-}
-
-int sun3x_get_irq_list(char *buf)
-{
-    return 0;
+	sprintf(model, "Sun3x");
 }
 
 /*
@@ -91,38 +55,51 @@
  */
 void __init config_sun3x(void)
 {
-    mach_get_irq_list	 = sun3x_get_irq_list;
-    mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
 
-    mach_keyb_init       = sun3x_keyb_init;
-    mach_kbdrate         = sun3x_kbdrate;
-    mach_kbd_leds        = sun3x_kbd_leds;
-
-    mach_sched_init      = sun3x_sched_init;
-    mach_init_IRQ        = sun3x_init_IRQ;
-    enable_irq           = sun3x_enable_irq;
-    disable_irq          = sun3x_disable_irq;
-    mach_request_irq     = sys_request_irq;
-    mach_free_irq        = sys_free_irq;
-    mach_default_handler = &sun3x_default_handler;
-    mach_gettimeoffset   = sun3x_gettimeoffset;
-    mach_reset           = sun3x_reboot;
+	sun3x_prom_init();
+
+	mach_get_irq_list	 = sun3_get_irq_list;
+	mach_max_dma_address = 0xffffffff; /* we can DMA anywhere, whee */
 
-    mach_gettod          = sun3x_gettod;
+	mach_keyb_init       = sun3x_keyb_init;
+	mach_kbdrate         = sun3x_kbdrate;
+	mach_kbd_leds        = sun3x_kbd_leds;
+
+	mach_default_handler = &sun3_default_handler;
+	mach_sched_init      = sun3x_sched_init;
+	mach_init_IRQ        = sun3_init_IRQ;
+	enable_irq           = sun3_enable_irq;
+	disable_irq          = sun3_disable_irq;
+	mach_request_irq     = sun3_request_irq;
+	mach_free_irq        = sun3_free_irq;
+	mach_process_int     = sun3_process_int;
     
-    switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
+	mach_gettimeoffset   = sun3x_gettimeoffset;
+	mach_reset           = sun3x_reboot;
+
+	mach_gettod          = sun3x_gettod;
+	mach_hwclk           = sun3x_hwclk;
+	mach_get_model       = sun3x_get_model;
+
+	sun3_intreg = (unsigned char *)SUN3X_INTREG;
+
+	/* only the serial console is known to work anyway... */
+#if 0    
+	switch (*(unsigned char *)SUN3X_EEPROM_CONS) {
 	case 0x10:
-	    serial_console = 1;
-	    conswitchp = NULL;
-	    break;
+		serial_console = 1;
+		conswitchp = NULL;
+		break;
 	case 0x11:
-	    serial_console = 2;
-	    conswitchp = NULL;
-	    break;
+		serial_console = 2;
+		conswitchp = NULL;
+		break;
 	default:
-	    serial_console = 0;
-	    conswitchp = &dummy_con;
-	    break;
-    }
+		serial_console = 0;
+		conswitchp = &dummy_con;
+		break;
+	}
+#endif
 
 }
+
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/dvma.c linux/arch/m68k/sun3x/dvma.c
--- v2.4.5/linux/arch/m68k/sun3x/dvma.c	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/sun3x/dvma.c	Mon Jun 11 19:15:27 2001
@@ -2,21 +2,31 @@
  * Virtual DMA allocation
  *
  * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de) 
+ *
+ * 11/26/2000 -- disabled the existing code because it didn't work for 
+ * me in 2.4.  Replaced with a significantly more primitive version 
+ * similar to the sun3 code.  the old functionality was probably more 
+ * desirable, but....   -- Sam Creasey (sammy@oh.verio.com)
+ *
  */
 
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/bitops.h>
 #include <linux/mm.h>
+#include <linux/bootmem.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
 
 #include <asm/sun3x.h>
 #include <asm/dvma.h>
 #include <asm/io.h>
 #include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 
 /* IOMMU support */
 
-#define IOMMU_ENTRIES		   2048
 #define IOMMU_ADDR_MASK            0x03ffe000
 #define IOMMU_CACHE_INHIBIT        0x00000040
 #define IOMMU_FULL_BLOCK           0x00000020
@@ -28,135 +38,170 @@
 #define IOMMU_DT_VALID             0x00000001
 #define IOMMU_DT_BAD               0x00000002
 
-#define DVMA_PAGE_SHIFT	13
-#define DVMA_PAGE_SIZE	(1UL << DVMA_PAGE_SHIFT)
-#define DVMA_PAGE_MASK	(~(DVMA_PAGE_SIZE-1))
-
 
 static volatile unsigned long *iommu_pte = (unsigned long *)SUN3X_IOMMU;
-static unsigned long iommu_use[IOMMU_ENTRIES];
-static unsigned long iommu_bitmap[IOMMU_ENTRIES/32];
 
 
 #define dvma_entry_paddr(index) 	(iommu_pte[index] & IOMMU_ADDR_MASK)
 #define dvma_entry_vaddr(index,paddr) 	((index << DVMA_PAGE_SHIFT) |  \
 					 (paddr & (DVMA_PAGE_SIZE-1)))
+#if 0
+#define dvma_entry_set(index,addr)	(iommu_pte[index] =            \
+					    (addr & IOMMU_ADDR_MASK) | \
+				             IOMMU_DT_VALID | IOMMU_CACHE_INHIBIT)
+#else
 #define dvma_entry_set(index,addr)	(iommu_pte[index] =            \
 					    (addr & IOMMU_ADDR_MASK) | \
 				             IOMMU_DT_VALID)
+#endif
 #define dvma_entry_clr(index)		(iommu_pte[index] = IOMMU_DT_INVALID)
-#define dvma_entry_use(index)		(iommu_use[index])
-#define dvma_entry_inc(index)		(iommu_use[index]++)
-#define dvma_entry_dec(index)		(iommu_use[index]--)
 #define dvma_entry_hash(addr)		((addr >> DVMA_PAGE_SHIFT) ^ \
 					 ((addr & 0x03c00000) >>     \
 						(DVMA_PAGE_SHIFT+4)))
-#define dvma_map			iommu_bitmap
-#define dvma_map_size			(IOMMU_ENTRIES/2)
-#define dvma_slow_offset		(IOMMU_ENTRIES/2)
-#define dvma_is_slow(addr)		((addr) & 		      \
-					 (dvma_slow_offset << DVMA_PAGE_SHIFT))
 
-static int fixed_dvma;
+#undef DEBUG
 
-void __init dvma_init(void)
+#ifdef DEBUG
+/* code to print out a dvma mapping for debugging purposes */
+void dvma_print (unsigned long dvma_addr)
 {
-    unsigned long tmp;
 
-    if ((unsigned long)high_memory < (IOMMU_ENTRIES << DVMA_PAGE_SHIFT)) {
-	printk ("Sun3x fixed DVMA mapping\n");
-	fixed_dvma = 1;
-	for (tmp = 0; tmp < (unsigned long)high_memory; tmp += DVMA_PAGE_SIZE)
-	dvma_entry_set (tmp >> DVMA_PAGE_SHIFT, virt_to_phys((void *)tmp));
-	fixed_dvma = 1;
-    } else {
-	printk ("Sun3x variable DVMA mapping\n");
-	for (tmp = 0; tmp < IOMMU_ENTRIES; tmp++)
-	    dvma_entry_clr (tmp);
-	fixed_dvma = 0;
-    }
+        unsigned long index;
+
+        index = dvma_addr >> DVMA_PAGE_SHIFT;
+
+        printk("idx %lx dvma_addr %08lx paddr %08lx\n", index, dvma_addr,
+               dvma_entry_paddr(index));
+
+
 }
+#endif
 
-unsigned long dvma_slow_alloc (unsigned long paddr, int npages)
+
+/* create a virtual mapping for a page assigned within the IOMMU
+   so that the cpu can reach it easily */
+inline int dvma_map_cpu(unsigned long kaddr, 
+			       unsigned long vaddr, int len)
 {
-    int scan, base;
-    
-    scan = 0;
-    for (;;) {
-	scan = find_next_zero_bit(dvma_map, dvma_map_size, scan);
-	if ((base = scan) + npages > dvma_map_size) {
-	    printk ("dvma_slow_alloc failed for %d pages\n",npages);
-	    return 0;
-	}
-	for  (;;) {
-	    if (scan >= base + npages) goto found;
-	    if (test_bit(scan, dvma_map)) break;
-	    scan++;
-	}
-    }
+	pgd_t *pgd;
+	unsigned long end;
+	int ret = 0;
+
+	kaddr &= PAGE_MASK;
+	vaddr &= PAGE_MASK;
+
+	end = PAGE_ALIGN(vaddr + len);
+
+#ifdef DEBUG
+	printk("dvma: mapping kern %08lx to virt %08lx\n",
+	       kaddr, vaddr);
+#endif
+	pgd = pgd_offset_k(vaddr);
+	
+	do {
+		pmd_t *pmd;
+		unsigned long end2;
+
+		if((pmd = pmd_alloc_kernel(pgd, vaddr)) == NULL) {
+			ret = -ENOMEM;
+			goto out;
+		}
+
+		if((end & PGDIR_MASK) > (vaddr & PGDIR_MASK)) 
+			end2 = (vaddr + (PGDIR_SIZE-1)) & PGDIR_MASK;
+		else
+			end2 = end;
+
+		do {
+			pte_t *pte;
+			unsigned long end3;
+
+			if((pte = pte_alloc_kernel(pmd, vaddr)) == NULL) {
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			if((end2 & PMD_MASK) > (vaddr & PMD_MASK)) 
+				end3 = (vaddr + (PMD_SIZE-1)) & PMD_MASK;
+			else
+				end3 = end2;
+
+			do {
+#ifdef DEBUG
+				printk("mapping %08lx phys to %08lx\n",
+				       __pa(kaddr), vaddr);
+#endif
+				set_pte(pte, __mk_pte(kaddr, PAGE_KERNEL));
+				pte++;
+				kaddr += PAGE_SIZE;
+				vaddr += PAGE_SIZE;
+			} while(vaddr < end3);
+			
+		} while(vaddr < end2);
+
+	} while(vaddr < end);
+	
+	flush_tlb_all();
 
-found:
-    for (scan = base; scan < base+npages; scan++) {
-	dvma_entry_set(scan+dvma_slow_offset, paddr);
-	paddr += DVMA_PAGE_SIZE;
-	set_bit(scan, dvma_map);
-    }
-    return (dvma_entry_vaddr((base+dvma_slow_offset),paddr));
+ out:
+	return ret;
 }
 
-unsigned long dvma_alloc (unsigned long paddr, unsigned long size)
+
+inline int dvma_map_iommu(unsigned long kaddr, unsigned long baddr,
+				 int len) 
 {
-    int index;
-    int pages = ((paddr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
-		DVMA_PAGE_SHIFT;
-
-    if (fixed_dvma)
-	return ((unsigned long)phys_to_virt (paddr));
-
-    if (pages > 1) /* multi page, allocate from slow pool */
-	return dvma_slow_alloc (paddr, pages);
-    
-    index = dvma_entry_hash (paddr);
-
-    if (dvma_entry_use(index)) {
-	if (dvma_entry_paddr(index) == (paddr & DVMA_PAGE_MASK)) {
-	    dvma_entry_inc(index);
-	    return dvma_entry_vaddr(index,paddr);
+	unsigned long end, index;
+
+	index = baddr >> DVMA_PAGE_SHIFT;
+	end = ((baddr+len) >> DVMA_PAGE_SHIFT);
+	
+	if(len & ~DVMA_PAGE_MASK)
+		end++;
+
+	for(; index < end ; index++) {
+//		if(dvma_entry_use(index))
+//			BUG();
+//		printk("mapping pa %lx to ba %lx\n", __pa(kaddr), index << DVMA_PAGE_SHIFT);
+
+		dvma_entry_set(index, __pa(kaddr));
+
+		iommu_pte[index] |= IOMMU_FULL_BLOCK;
+//		dvma_entry_inc(index);
+		
+		kaddr += DVMA_PAGE_SIZE;
 	}
-	/* collision, allocate from slow pool */
-	return dvma_slow_alloc (paddr, pages);
-    }
-    
-    dvma_entry_set(index,paddr); 
-    dvma_entry_inc(index);
-    return dvma_entry_vaddr(index,paddr);
+
+#ifdef DEBUG	
+	for(index = (baddr >> DVMA_PAGE_SHIFT); index < end; index++) 
+		dvma_print(index << DVMA_PAGE_SHIFT);
+#endif
+	return 0;
+
 }
 
-void dvma_free (unsigned long dvma_addr, unsigned long size)
+void dvma_unmap_iommu(unsigned long baddr, int len)
 {
-    int npages;
-    int index;
-    
-    if (fixed_dvma)
-	return;
-
-    if (!dvma_is_slow(dvma_addr)) {
-	index = (dvma_addr >> DVMA_PAGE_SHIFT);
-	if (dvma_entry_use(index) == 0) {
-	    printk ("dvma_free: %lx entry already free\n",dvma_addr);
-	    return;
+
+	int index, end;
+	
+	
+	index = baddr >> DVMA_PAGE_SHIFT;
+	end = (DVMA_PAGE_ALIGN(baddr+len) >> DVMA_PAGE_SHIFT);
+	
+	for(; index < end ; index++) {
+#ifdef DEBUG
+		printk("freeing bus mapping %08x\n", index << DVMA_PAGE_SHIFT);
+#endif
+#if 0
+		if(!dvma_entry_use(index)) 
+			printk("dvma_unmap freeing unused entry %04x\n",
+			       index);
+		else
+			dvma_entry_dec(index);
+#endif
+		dvma_entry_clr(index);
 	}
-        dvma_entry_dec(index);
-	if (dvma_entry_use(index) == 0)
-	    dvma_entry_clr(index);
-	return;
-    }
-
-    /* free in slow pool */
-    npages = ((dvma_addr & ~DVMA_PAGE_MASK) + size + (DVMA_PAGE_SIZE-1)) >>
-	    DVMA_PAGE_SHIFT;
-    for (index = (dvma_addr >> DVMA_PAGE_SHIFT); npages--; index++) {
-	dvma_entry_clr(index);
-	clear_bit (index,dvma_map);
-    }
+
 }
+
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/prom.c linux/arch/m68k/sun3x/prom.c
--- v2.4.5/linux/arch/m68k/sun3x/prom.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/prom.c	Mon Jun 11 19:15:27 2001
@@ -0,0 +1,165 @@
+/* Prom access routines for the sun3x */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
+#include <asm/traps.h>
+#include <asm/sun3xprom.h>
+#include <asm/idprom.h>
+#include <asm/segment.h>
+#include <asm/sun3ints.h>
+#include <asm/openprom.h>
+#include <asm/machines.h>
+
+void (*sun3x_putchar)(int);
+int (*sun3x_getchar)(void);
+int (*sun3x_mayget)(void);
+int (*sun3x_mayput)(int);
+void (*sun3x_prom_reboot)(void);
+e_vector sun3x_prom_abort;
+struct idprom *idprom;
+static struct idprom idprom_buffer;
+struct linux_romvec *romvec;
+
+/* prom vector table */
+e_vector *sun3x_prom_vbr;
+
+extern e_vector vectors[256];  /* arch/m68k/kernel/traps.c */
+
+/* Handle returning to the prom */
+void sun3x_halt(void)
+{
+    unsigned long flags;
+    
+    /* Disable interrupts while we mess with things */
+    save_flags(flags); cli();
+
+    /* Restore prom vbr */
+    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+
+    /* Restore prom NMI clock */
+//    sun3x_disable_intreg(5);
+    sun3_enable_irq(7);
+
+    /* Let 'er rip */
+    __asm__ volatile ("trap #14" : : );
+
+    /* Restore everything */
+    sun3_disable_irq(7);
+    sun3_enable_irq(5);
+
+    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+    restore_flags(flags);
+}
+
+void sun3x_reboot(void)
+{
+    /* This never returns, don't bother saving things */
+    cli();
+
+    /* Restore prom vbr */
+    __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)sun3x_prom_vbr));
+
+    /* Restore prom NMI clock */
+    sun3_disable_irq(5);
+    sun3_enable_irq(7);
+
+    /* Let 'er rip */
+    (*romvec->pv_reboot)("vmlinux");
+}
+
+extern char m68k_debug_device[];
+
+static void sun3x_prom_write(struct console *co, const char *s,
+                             unsigned int count)
+{
+    while (count--) {
+        if (*s == '\n')
+            sun3x_putchar('\r');
+        sun3x_putchar(*s++);
+    }
+}
+
+/* debug console - write-only */
+
+static struct console sun3x_debug = {
+	"debug",
+	sun3x_prom_write,  	/* write */
+	NULL,			/* read */
+	NULL,			/* device */
+	NULL,			/* wait_key */
+	NULL,			/* unblank */
+	NULL,			/* setup */
+	CON_PRINTBUFFER,
+	-1,
+	0,
+	NULL
+};
+
+void sun3x_prom_init(void)
+{
+    /* Read the vector table */
+	int i;
+
+
+    sun3x_putchar = *(void (**)(int)) (SUN3X_P_PUTCHAR);
+    sun3x_getchar = *(int (**)(void)) (SUN3X_P_GETCHAR);
+    sun3x_mayget = *(int (**)(void))  (SUN3X_P_MAYGET);
+    sun3x_mayput = *(int (**)(int))   (SUN3X_P_MAYPUT);
+    sun3x_prom_reboot = *(void (**)(void)) (SUN3X_P_REBOOT);
+    sun3x_prom_abort = *(e_vector *)  (SUN3X_P_ABORT);
+    romvec = (struct linux_romvec *)SUN3X_PROM_BASE;
+
+    /* make a copy of the idprom structure */
+    for(i = 0; i < sizeof(struct idprom); i++) 
+	    ((unsigned char *)(&idprom_buffer))[i] = ((unsigned char *)SUN3X_IDPROM)[i];
+    idprom = &idprom_buffer;
+
+    if((idprom->id_machtype & SM_ARCH_MASK) != SM_SUN3X) {
+	    printk("Warning: machine reports strange type %02x\n");
+	    printk("Pretending it's a 3/80, but very afraid...\n");
+	    idprom->id_machtype = SM_SUN3X | SM_3_80;
+    }
+
+    /* point trap #14 at abort.
+     * XXX this is futile since we restore the vbr first - oops
+     */
+    vectors[VEC_TRAP14] = sun3x_prom_abort;
+    
+    /* If debug=prom was specified, start the debug console */
+
+    if (!strcmp(m68k_debug_device, "prom"))
+        register_console(&sun3x_debug);
+
+    
+}
+
+/* some prom functions to export */
+int prom_getintdefault(int node, char *property, int deflt)
+{
+	return deflt;
+}
+
+int prom_getbool (int node, char *prop)
+{
+	return 1;
+}
+
+void prom_printf(char *fmt, ...)
+{
+
+}
+
+void prom_halt (void)
+{
+	sun3x_halt();
+}
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/sbus.c linux/arch/m68k/sun3x/sbus.c
--- v2.4.5/linux/arch/m68k/sun3x/sbus.c	Thu Aug 26 12:42:31 1999
+++ linux/arch/m68k/sun3x/sbus.c	Wed Dec 31 16:00:00 1969
@@ -1,44 +0,0 @@
-/*
- * SBus helper functions
- *
- * Sun3x don't have a sbus, but many of the used devices are also
- * used on Sparc machines with sbus. To avoid having a lot of
- * duplicate code, we provide necessary glue stuff to make using
- * of the sbus driver code possible.
- *
- * (C) 1999 Thomas Bogendoerfer (tsbogend@alpha.franken.de)
- */
-
-#include <linux/types.h>
-#include <linux/init.h>
-
-void __init sbus_init(void)
-{
-
-}
-
-void *sparc_alloc_io (u32 address, void *virtual, int len, char *name,
-                      u32 bus_type, int rdonly)
-{
-	return (void *)address;
-}
-
-int prom_getintdefault(int node, char *property, int deflt)
-{
-	return deflt;
-}
-
-int prom_getbool (int node, char *prop)
-{
-	return 1;
-}
-
-void prom_printf(char *fmt, ...)
-{
-
-}
-
-void prom_halt (void)
-{
-
-}
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/sun3x_ksyms.c linux/arch/m68k/sun3x/sun3x_ksyms.c
--- v2.4.5/linux/arch/m68k/sun3x/sun3x_ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/m68k/sun3x/sun3x_ksyms.c	Mon Jun 11 19:15:27 2001
@@ -0,0 +1,13 @@
+#include <linux/module.h>
+#include <linux/types.h>
+#include <asm/dvma.h>
+#include <asm/idprom.h>
+
+/*
+ * Add things here when you find the need for it.
+ */
+EXPORT_SYMBOL(dvma_map_align);
+EXPORT_SYMBOL(dvma_unmap);
+EXPORT_SYMBOL(dvma_malloc_align);
+EXPORT_SYMBOL(dvma_free);
+EXPORT_SYMBOL(idprom);
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/time.c linux/arch/m68k/sun3x/time.c
--- v2.4.5/linux/arch/m68k/sun3x/time.c	Thu Aug 26 12:42:31 1999
+++ linux/arch/m68k/sun3x/time.c	Mon Jun 11 19:15:27 2001
@@ -5,6 +5,7 @@
  */
 
 #include <linux/types.h>
+#include <linux/kd.h>
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/kernel_stat.h>
@@ -15,6 +16,8 @@
 #include <asm/system.h>
 #include <asm/traps.h>
 #include <asm/sun3x.h>
+#include <asm/sun3ints.h>
+#include <asm/rtc.h>
 
 #include "time.h"
 
@@ -33,6 +36,7 @@
 #define C_CALIB   0x1f
 
 #define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
+#define BIN_TO_BCD(val) (((val/10) << 4) | (val % 10))
 
 /* Read the Mostek */
 void sun3x_gettod (int *yearp, int *monp, int *dayp,
@@ -45,7 +49,7 @@
 
     /* Read values */
     *yearp = BCD_TO_BIN(*(eeprom + M_YEAR));
-    *monp  = BCD_TO_BIN(*(eeprom + M_MONTH));
+    *monp  = BCD_TO_BIN(*(eeprom + M_MONTH)) +1;
     *dayp  = BCD_TO_BIN(*(eeprom + M_DATE));
     *hourp = BCD_TO_BIN(*(eeprom + M_HOUR));
     *minp  = BCD_TO_BIN(*(eeprom + M_MIN));
@@ -55,6 +59,40 @@
     *(eeprom + M_CONTROL) &= ~C_READ;
 }
 
+int sun3x_hwclk(int set, struct hwclk_time *t)
+{
+	volatile struct mostek_dt *h = 
+		(unsigned char *)(SUN3X_EEPROM+M_CONTROL);
+	unsigned long flags;
+
+	save_and_cli(flags);
+	
+	if(set) {
+		h->csr |= C_WRITE;
+		h->sec = BIN_TO_BCD(t->sec);
+		h->min = BIN_TO_BCD(t->min);
+		h->hour = BIN_TO_BCD(t->hour);
+		h->wday = BIN_TO_BCD(t->wday);
+		h->mday = BIN_TO_BCD(t->day);
+		h->month = BIN_TO_BCD(t->mon);
+		h->year = BIN_TO_BCD(t->year);
+		h->csr &= ~C_WRITE;
+	} else {
+		h->csr |= C_READ;
+		t->sec = BCD_TO_BIN(h->sec);
+		t->min = BCD_TO_BIN(h->min);
+		t->hour = BCD_TO_BIN(h->hour);
+		t->wday = BCD_TO_BIN(h->wday);
+		t->day = BCD_TO_BIN(h->mday);
+		t->mon = BCD_TO_BIN(h->month);
+		t->year = BCD_TO_BIN(h->year);
+		h->csr &= ~C_READ;
+	}
+
+	restore_flags(flags);
+
+	return 0;
+}
 /* Not much we can do here */
 unsigned long sun3x_gettimeoffset (void)
 {
@@ -74,9 +112,12 @@
 
 void __init sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *))
 {
-    sys_request_irq(5, sun3x_timer_tick, IRQ_FLG_STD, "timer tick", vector);
+	
+	sun3_disable_interrupts();
+	
 
     /* Pulse enable low to get the clock started */
-    disable_irq(5);
-    enable_irq(5);
+	sun3_disable_irq(5);
+	sun3_enable_irq(5);
+	sun3_enable_interrupts();
 }
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/sun3x/time.h linux/arch/m68k/sun3x/time.h
--- v2.4.5/linux/arch/m68k/sun3x/time.h	Tue May 11 09:57:14 1999
+++ linux/arch/m68k/sun3x/time.h	Mon Jun 11 19:15:27 2001
@@ -1,9 +1,21 @@
 #ifndef SUN3X_TIME_H
 #define SUN3X_TIME_H
 
-void sun3x_gettod (int *yearp, int *monp, int *dayp,
+extern void sun3x_gettod (int *yearp, int *monp, int *dayp,
                    int *hourp, int *minp, int *secp);
+extern int sun3x_hwclk(int set, struct hwclk_time *t);
 unsigned long sun3x_gettimeoffset (void);
 void sun3x_sched_init(void (*vector)(int, void *, struct pt_regs *));
+
+struct mostek_dt {
+	volatile unsigned char csr;
+	volatile unsigned char sec;
+	volatile unsigned char min;
+	volatile unsigned char hour;
+	volatile unsigned char wday;
+	volatile unsigned char mday;
+	volatile unsigned char month;
+	volatile unsigned char year;
+};
 
 #endif
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/vmlinux-sun3.lds linux/arch/m68k/vmlinux-sun3.lds
--- v2.4.5/linux/arch/m68k/vmlinux-sun3.lds	Sat Sep  4 13:06:41 1999
+++ linux/arch/m68k/vmlinux-sun3.lds	Mon Jul  2 14:40:14 2001
@@ -20,6 +20,7 @@
 
   .data : {			/* Data */
 	*(.rodata)
+	*(.rodata.*)
 	*(.data)
 	CONSTRUCTORS
   	. = ALIGN(16);		/* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/m68k/vmlinux.lds linux/arch/m68k/vmlinux.lds
--- v2.4.5/linux/arch/m68k/vmlinux.lds	Sat Sep  4 13:06:41 1999
+++ linux/arch/m68k/vmlinux.lds	Mon Jul  2 14:40:14 2001
@@ -12,7 +12,7 @@
 	*(.text.lock)		/* out-of-line lock text */
 	*(.gnu.warning)
 	} = 0x4e75
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/mips/Makefile linux/arch/mips/Makefile
--- v2.4.5/linux/arch/mips/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/Makefile	Mon Jul  2 13:56:40 2001
@@ -17,10 +17,8 @@
 #
 ifdef CONFIG_CPU_LITTLE_ENDIAN
 tool-prefix	= mipsel-linux-
-output-format	= elf32-littlemips
 else
 tool-prefix	= mips-linux-
-output-format	= elf32-bigmips
 endif
 
 ifdef CONFIG_CROSSCOMPILE
@@ -51,9 +49,6 @@
 ifdef CONFIG_CPU_R3000
 GCCFLAGS	+= -mcpu=r3000 -mips1
 endif
-ifdef CONFIG_CPU_R3912
-GCCFLAGS	+= -mcpu=r3000 -mips1
-endif
 ifdef CONFIG_CPU_R6000
 GCCFLAGS	+= -mcpu=r6000 -mips2 -Wa,--trap
 endif
@@ -67,22 +62,19 @@
 GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5432
-GCCFLAGS        += -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS        += -mcpu=r5000 -mips2 -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap -mmad
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap -mmad
 endif
 ifdef CONFIG_CPU_RM7000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
-endif
-ifdef CONFIG_CPU_R8000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
 endif
-ifdef CONFIG_CPU_R10000
-GCCFLAGS	+= -mcpu=r8000 -mips2 -Wa,--trap
+ifdef CONFIG_CPU_SB1
+GCCFLAGS	+= -mcpu=sb1 -mips2 -Wa,--trap
 endif
 
 ifdef CONFIG_MIPS_FPU_EMULATOR
@@ -90,14 +82,11 @@
 SUBDIRS		+=arch/mips/math-emu
 endif
 
-#
-# The pipe options is bad for my low-mem machine
-# Uncomment this if you want this.
-#
 GCCFLAGS	+= -pipe
 
 CFLAGS		:= -I $(TOPDIR)/include/asm/gcc $(CFLAGS) $(GCCFLAGS)
 AFLAGS		+= $(GCCFLAGS)
+ASFLAGS		+= $(GCCFLAGS)
 
 #
 # Board-dependent options and extra files
@@ -178,15 +167,6 @@
 endif
 
 #
-# Orion Board
-#
-ifdef CONFIG_ORION
-LIBS          += arch/mips/orion/orionkern.a
-SUBDIRS       += arch/mips/orion
-LINKSCRIPT    = arch/mips/orion/ld.script.orion
-endif
-
-#
 #
 # NEC DDB Vrc-5476
 #
@@ -197,6 +177,17 @@
 endif
 
 #
+#
+# NEC DDB Vrc-5477
+#
+ifdef CONFIG_DDB5477
+SUBDIRS       += arch/mips/ddb5xxx/common arch/mips/ddb5xxx/ddb5477
+LIBS          += arch/mips/ddb5xxx/common/ddb5xxx.o \
+                 arch/mips/ddb5xxx/ddb5477/ddb5477.o
+LOADADDR      += 0x80080000
+endif
+
+#
 # Galileo EV64120 Board
 #
 ifdef CONFIG_MIPS_EV64120
@@ -218,7 +209,9 @@
 # Momentum Ocelot board
 #
 ifdef CONFIG_MOMENCO_OCELOT
-LIBS          += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
+# The Ocelot setup.o must be linked early - it does the ioremap() for the
+# mips_io_port_base.
+CORE_FILES    += arch/mips/gt64120/common/gt64120.o arch/mips/gt64120/momenco_ocelot/momenco_ocelot.o
 SUBDIRS       += arch/mips/gt64120/common arch/mips/gt64120/momenco_ocelot
 LOADADDR      += 0x80100000
 endif
@@ -227,9 +220,8 @@
 # Philips Nino
 #
 ifdef CONFIG_NINO
-CORE_FILES    += arch/mips/philips/nino/nino.o \
-		 arch/mips/philips/drivers/drivers.o
-SUBDIRS       += arch/mips/philips/nino arch/mips/philips/drivers
+CORE_FILES    += arch/mips/philips/nino/nino.o
+SUBDIRS       += arch/mips/philips/nino
 LOADADDR      += 0x80000000
 endif
 
@@ -252,8 +244,7 @@
 vmlinux: arch/$(ARCH)/ld.script
 
 arch/$(ARCH)/ld.script: arch/$(ARCH)/ld.script.in arch/$(ARCH)/Makefile
-	sed -e 's/@@OUTPUT_FORMAT@@/$(output-format)/' \
-	    -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
+	sed -e 's/@@LOADADDR@@/$(LOADADDR)/' <$< >$@
 LINKFLAGS	+= -T arch/$(ARCH)/ld.script
 
 HEAD := arch/mips/kernel/head.o arch/mips/kernel/init_task.o
@@ -269,13 +260,6 @@
 balo:  vmlinux
 	$(BAGETBOOT) balo
 
-endif
-
-ifdef CONFIG_ORION
-ORIONBOOT = $(MAKE) -C arch/$(ARCH)/orion
-
-orionboot:
-	$(ORIONBOOT) orionboot
 endif
 
 ifdef CONFIG_MIPS_EV64120
diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/cmdline.c linux/arch/mips/arc/cmdline.c
--- v2.4.5/linux/arch/mips/arc/cmdline.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/cmdline.c	Mon Jul  2 13:56:40 2001
@@ -25,10 +25,49 @@
 	"SystemPartition=",
 	"OSLoader=",
 	"OSLoadPartition=",
-	"OSLoadFilename="
+	"OSLoadFilename=",
+	"OSLoadOptions="
 };
 #define NENTS(foo) ((sizeof((foo)) / (sizeof((foo[0])))))
 
+static char *used_arc[][2] = {
+	{ "OSLoadPartition=", "root=" },
+	{ "OSLoadOptions=", "" }
+};
+
+static char * __init move_firmware_args(char* cp)
+{
+	char *s;
+	int actr, i;
+
+	actr = 1; /* Always ignore argv[0] */
+
+	while (actr < prom_argc) {
+		for(i = 0; i < NENTS(used_arc); i++) {
+			int len = strlen(used_arc[i][0]);
+
+			if(!strncmp(prom_argv[actr], used_arc[i][0], len)) {
+			/* Ok, we want it. First append the replacement... */
+				strcat(cp, used_arc[i][1]);
+				cp += strlen(used_arc[i][1]);
+				/* ... and now the argument */
+				s = strstr(prom_argv[actr], "=");
+				if(s) {
+					s++;
+					strcpy(cp, s);
+					cp += strlen(s);
+				}
+				*cp++ = ' ';
+				break;
+			}
+		}
+		actr++;
+	}
+
+	return cp;
+}
+
+
 void __init prom_init_cmdline(void)
 {
 	char *cp;
@@ -37,8 +76,14 @@
 	actr = 1; /* Always ignore argv[0] */
 
 	cp = &(arcs_cmdline[0]);
-	while(actr < prom_argc) {
-		for(i = 0; i < NENTS(ignored); i++) {
+	/* 
+	 * Move ARC variables to the beginning to make sure they can be
+	 * overridden by later arguments.
+	 */
+	cp = move_firmware_args(cp);
+
+	while (actr < prom_argc) {
+		for (i = 0; i < NENTS(ignored); i++) {
 			int len = strlen(ignored[i]);
 
 			if(!strncmp(prom_argv[actr], ignored[i], len))
diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/console.c linux/arch/mips/arc/console.c
--- v2.4.5/linux/arch/mips/arc/console.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/console.c	Mon Jul  2 13:56:40 2001
@@ -15,10 +15,6 @@
 #include <linux/kdev_t.h>
 #include <linux/major.h>
 
-#ifdef CONFIG_ARC_CONSOLE
-#define __init
-#endif
-
 /*
  * IP22 boardcache is not compatible with board caches.  Thus we disable it
  * during romvec action.  Since r4xx0.c is always compiled and linked with your
@@ -29,7 +25,7 @@
  * in some way. You should be careful with them.
  */
 
-void __init prom_putchar(char c)
+void prom_putchar(char c)
 {
 	long cnt;
 	char it = c;
@@ -53,7 +49,7 @@
 
 static char ppbuf[1024];
 
-void __init prom_printf(char *fmt, ...)
+void prom_printf(char *fmt, ...)
 {
 	va_list args;
 	char ch, *bptr;
@@ -71,29 +67,4 @@
 		prom_putchar(ch);
 	}
 	va_end(args);
-}
-
-static void
-arc_console_write(struct console *con, const char *s, unsigned n)
-{
-	prom_printf("%s", s);
-}
-
-static kdev_t 
-arc_console_dev(struct console *c)
-{
-	return MKDEV(TTY_MAJOR, 64 + c->index);
-}
-
-static struct console arc_prom_console = {
-    name:	"prom",
-    write:	arc_console_write,
-    device:	arc_console_dev,
-    flags:	CON_PRINTBUFFER,
-    index:	-1,
-};
-
-__init void arc_setup_console(void)
-{
-	register_console(&arc_prom_console);
 }
diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/identify.c linux/arch/mips/arc/identify.c
--- v2.4.5/linux/arch/mips/arc/identify.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/identify.c	Mon Jul  2 13:56:40 2001
@@ -36,7 +36,7 @@
 {
 	int i;
 
-	for (i = 0; i < sizeof(mach_table); i++) {
+	for (i = 0; i < (sizeof(mach_table) / sizeof (mach_table[0])); i++) {
 		if (!strcmp(s, mach_table[i].name))
 			return &mach_table[i];
 	}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/memory.c linux/arch/mips/arc/memory.c
--- v2.4.5/linux/arch/mips/arc/memory.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/memory.c	Mon Jul  2 13:56:40 2001
@@ -32,7 +32,7 @@
 	"Free/Contig RAM",
 	"Generic Free RAM",
 	"Bad Memory",
-	"Standlong Program Pages",
+	"Standalone Program Pages",
 	"ARCS Temp Storage Area",
 	"ARCS Permanent Storage Area"
 };
diff -u --recursive --new-file v2.4.5/linux/arch/mips/arc/misc.c linux/arch/mips/arc/misc.c
--- v2.4.5/linux/arch/mips/arc/misc.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/arc/misc.c	Mon Jul  2 13:56:40 2001
@@ -56,7 +56,7 @@
 	romvec->reboot();
 }
 
-void prom_imode(void)
+void ArcEnterInteractiveMode(void)
 {
 	bc_disable();
 	cli();
diff -u --recursive --new-file v2.4.5/linux/arch/mips/baget/ld.script.balo linux/arch/mips/baget/ld.script.balo
--- v2.4.5/linux/arch/mips/baget/ld.script.balo	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/baget/ld.script.balo	Mon Jul  2 14:40:14 2001
@@ -31,6 +31,7 @@
     _ftext = . ;
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -u --recursive --new-file v2.4.5/linux/arch/mips/boot/mkboot.c linux/arch/mips/boot/mkboot.c
--- v2.4.5/linux/arch/mips/boot/mkboot.c	Thu Jun 26 12:33:36 1997
+++ linux/arch/mips/boot/mkboot.c	Mon Jul  2 13:56:40 2001
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996 by Ralf Baechle
+ * Copyright (C) 1996, 2001 by Ralf Baechle
  *
  * This file is written in plain Kernighan & Ritchie C as it has to run
  * on all crosscompile hosts no matter how braindead.  This code might
@@ -80,7 +80,6 @@
  * Acceptable machine type in e_machine.
  */
 #define EM_MIPS         8               /* MIPS R3000 big-endian */
-#define EM_MIPS_RS4_BE 10               /* MIPS R4000 big-endian */
 
 /*
  * The type of ELF file we accept.
@@ -462,7 +461,7 @@
 		fprintf(stderr, "Input file isn't a executable.\n");
 		exit(1);
 	}
-	if(eh.e_machine != EM_MIPS && eh.e_machine != EM_MIPS_RS4_BE) {
+	if(eh.e_machine != EM_MIPS) {
 		fprintf(stderr, "Input file isn't a MIPS executable.\n");
 		exit(1);
 	}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/config.in linux/arch/mips/config.in
--- v2.4.5/linux/arch/mips/config.in	Tue Apr 17 17:19:25 2001
+++ linux/arch/mips/config.in	Mon Jul  2 13:56:40 2001
@@ -2,6 +2,9 @@
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
+define_bool CONFIG_MIPS y
+define_bool CONFIG_SMP n
+
 mainmenu_name "Linux Kernel Configuration"
 
 mainmenu_option next_comment
@@ -15,18 +18,55 @@
    bool 'Support for Acer PICA 1 chipset' CONFIG_ACER_PICA_61
    bool 'Support for Algorithmics P4032 (EXPERIMENTAL)' CONFIG_ALGOR_P4032
    bool 'Support for BAGET MIPS series (EXPERIMENTAL)' CONFIG_BAGET_MIPS
-   bool 'Support for Cobalt Server' CONFIG_COBALT_MICRO_SERVER
-   if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
-      bool '  Support for 2800' CONFIG_COBALT_28
-   fi
    bool 'Support for DECstations (EXPERIMENTAL)' CONFIG_DECSTATION
    bool 'Support for NEC DDB Vrc-5074 (EXPERIMENTAL)' CONFIG_DDB5074
-   bool 'Support for Galileo Evaluation board or CoSine Orion' CONFIG_ORION
+   bool 'Support for Galileo EV96100 Evaluation board' CONFIG_MIPS_EV96100
+   bool 'Support for Galileo EV64120 Evaluation board' CONFIG_MIPS_EV64120
+   if [ "$CONFIG_MIPS_EV64120" = "y" ]; then
+		  bool 'Enable Second PCI (PCI1)' CONFIG_EVB_PCI1
+      choice 'Galileo Chip Clock' \
+        "75 CONFIG_SYSCLK_75\
+         83.3 CONFIG_SYSCLK_83\
+         100 CONFIG_SYSCLK_100" CONFIG_SYSCLK_83
+   fi
+   bool 'Support for MIPS Atlas board' CONFIG_MIPS_ATLAS
+   bool 'Support for MIPS Malta board' CONFIG_MIPS_MALTA
+   bool 'Support for Philips Nino (EXPERIMENTAL)' CONFIG_NINO
+   if [ "$CONFIG_NINO" = "y" ]; then
+      choice 'Nino Model Number' \
+        "Model-300/301/302/319 CONFIG_NINO_4MB \
+         Model-200/210/312/320/325/350/390 CONFIG_NINO_8MB \
+         Model-500/510 CONFIG_NINO_16MB" CONFIG_NINO_8MB
+   fi
 fi
 bool 'Support for Mips Magnum 4000' CONFIG_MIPS_MAGNUM_4000
+bool 'Support for Momentum Ocelot board' CONFIG_MOMENCO_OCELOT
+bool 'Support for NEC DDB Vrc-5476' CONFIG_DDB5476
+bool 'Support for NEC DDB Vrc-5477' CONFIG_DDB5477
 bool 'Support for Olivetti M700-10' CONFIG_OLIVETTI_M700
 bool 'Support for SGI IP22' CONFIG_SGI_IP22
 bool 'Support for SNI RM200 PCI' CONFIG_SNI_RM200_PCI
+bool 'Support for ITE 8172G board' CONFIG_MIPS_ITE8172
+   if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
+       bool '    Support for older IT8172 (Rev C)' CONFIG_IT8172_REVC
+       bool '    Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD
+       if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
+	   define_bool CONFIG_IT8172_CIR y
+       else
+           bool '    Enable PS2 Keyboard Support ' CONFIG_PC_KEYB
+       fi
+       bool '    Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
+       bool '    Enable Smart Card Reader 1 Support ' CONFIG_IT8172_SCR1
+   fi
+   bool 'Support for Globespan IVR board' CONFIG_MIPS_IVR
+   if [ "$CONFIG_MIPS_IVR" = "y" ]; then
+       bool '    Enable Qtronix 990P Keyboard Support' CONFIG_QTRONIX_KEYBOARD
+       if [ "$CONFIG_QTRONIX_KEYBOARD" = "y" ]; then
+	   define_bool CONFIG_IT8172_CIR y
+       fi
+       bool '    Enable Smart Card Reader 0 Support ' CONFIG_IT8172_SCR0
+   fi
+bool 'Support for Alchemy Semi PB1000 board' CONFIG_MIPS_PB1000
 
 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK y
 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM n
@@ -35,54 +75,127 @@
 # Select some configuration options automatically for certain systems.
 #
 unset CONFIG_ARC32
+unset CONFIG_BOARD_SCACHE
+unset CONFIG_HAVE_STD_PC_SERIAL_PORT
+unset CONFIG_I8259
 unset CONFIG_ISA
-unset CONFIG_EISA
 unset CONFIG_PCI
 unset CONFIG_MIPS_JAZZ
+unset CONFIG_SWAP_IO_SPACE
 unset CONFIG_VIDEO_G364
 unset CONFIG_PC_KEYB
 
 define_bool CONFIG_MCA n
 define_bool CONFIG_SBUS n
 
+if [ "$CONFIG_MIPS_EV96100" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_MIPS_GT96100 y
+   define_bool CONFIG_SWAP_IO_SPACE y
+fi
+if [ "$CONFIG_MIPS_EV64120" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_ISA n
+   define_bool CONFIG_MIPS_GT64120 y
+   define_bool CONFIG_OLD_TIME_C y
+fi
+
 if [ "$CONFIG_ALGOR_P4032" = "y" ]; then
    define_bool CONFIG_PCI y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_MIPS_MAGNUM_4000" = "y" -o \
      "$CONFIG_OLIVETTI_M700" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
    define_bool CONFIG_FB y
    define_bool CONFIG_FB_G364 y	
    define_bool CONFIG_MIPS_JAZZ y
    define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_ACER_PICA_61" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
    define_bool CONFIG_MIPS_JAZZ y
    define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
 fi
-if [ "$CONFIG_COBALT_MICRO_SERVER" = "y" ]; then
-   define_bool CONFIG_COBALT_27 y
-   define_bool CONFIG_COBALT_LCD y
-   define_bool CONFIG_COBALT_SERIAL y
+if [ "$CONFIG_MIPS_ATLAS" = "y" ]; then
    define_bool CONFIG_PCI y
+   define_bool CONFIG_SWAP_IO_SPACE y
+fi
+if [ "$CONFIG_MIPS_MALTA" = "y" ]; then
+   define_bool CONFIG_I8259 y
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y
+   define_bool CONFIG_SWAP_IO_SPACE y
+fi
+if [ "$CONFIG_MOMENCO_OCELOT" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_SYSCLK_100 y
+   define_bool CONFIG_SWAP_IO_SPACE y
+   define_bool CONFIG_NEW_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_SGI_IP22" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_BOARD_SCACHE y
    define_bool CONFIG_PC_KEYB y
    define_bool CONFIG_SGI y
+   define_bool CONFIG_NEW_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
 fi
 if [ "$CONFIG_SNI_RM200_PCI" = "y" ]; then
    define_bool CONFIG_ARC32 y
+   define_bool CONFIG_I8259 y
+   define_bool CONFIG_ISA y
+   define_bool CONFIG_PC_KEYB y
    define_bool CONFIG_PCI y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_OLD_TIME_C y
+fi
+if [ "$CONFIG_DDB5074" = "y"]; then
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
+   define_bool CONFIG_PCI y
    define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y
+   define_bool CONFIG_OLD_TIME_C y
 fi
-if [ "$CONFIG_DDB5074" = "y" ]; then
+if [ "$CONFIG_DDB5476"  = "y" ]; then
+   define_bool CONFIG_I8259 y
    define_bool CONFIG_ISA y
    define_bool CONFIG_PCI y
+   define_bool CONFIG_PC_KEYB y
+   define_bool CONFIG_ROTTEN_IRQ y
+   define_bool CONFIG_HAVE_STD_PC_SERIAL_PORT y
+   define_bool CONFIG_NEW_TIME_C y
+fi
+if [ "$CONFIG_DDB5477" = "y" ]; then
+   define_bool CONFIG_CPU_LITTLE_ENDIAN y
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_NEW_TIME_C y
+   define_bool CONFIG_NEW_IRQ y
+fi
+if [ "$CONFIG_MIPS_ITE8172" = "y" ]; then
+   define_bool CONFIG_PCI y
+   define_bool CONFIG_IT8712 y
+   define_bool CONFIG_PC_KEYB y
+fi
+if [ "$CONFIG_MIPS_IVR" = "y" ]; then
+   define_bool CONFIG_PCI y
+fi
+if [ "$CONFIG_MIPS_PB1000" = "y" ]; then
+   define_bool CONFIG_MIPS_AU1000 y
+   define_bool CONFIG_NEW_IRQ y
+fi
+if [ "$CONFIG_NINO" = "y" ]; then
+   define_bool CONFIG_PC_KEYB y
 fi
 
 if [ "$CONFIG_ISA" != "y" ]; then
@@ -95,6 +208,10 @@
 if [ "$CONFIG_PCI" != "y" ]; then
    define_bool CONFIG_PCI n
 fi
+
+if [ "$CONFIG_I8259" != "y" ]; then
+   define_bool CONFIG_I8259 n
+fi
 endmenu
 
 mainmenu_option next_comment
@@ -115,9 +232,12 @@
 	 R4300 CONFIG_CPU_R4300	\
 	 R4x00 CONFIG_CPU_R4X00	\
 	 R5000 CONFIG_CPU_R5000	\
-	 R56x0 CONFIG_CPU_NEVADA \
-	 R8000 CONFIG_CPU_R8000	\
-	 R10000 CONFIG_CPU_R10000" R4x00
+         R5432 CONFIG_CPU_R5432 \
+	 RM7000 CONFIG_CPU_RM7000 \
+	 R52xx CONFIG_CPU_NEVADA \
+	 R10000 CONFIG_CPU_R10000 \
+	 SB1    CONFIG_CPU_SB1    \
+	 MIPS32 CONFIG_CPU_MIPS32" R4x00
 
 bool 'Override CPU Options' CONFIG_CPU_ADVANCED
 
@@ -134,19 +254,23 @@
 	 define_bool CONFIG_CPU_HAS_WB n
       fi
    else
-      define_bool CONFIG_CPU_HAS_LLSC y
-      define_bool CONFIG_CPU_HAS_WB n
+	 define_bool CONFIG_CPU_HAS_LLSC y
+	 define_bool CONFIG_CPU_HAS_WB n
    fi
 fi
 endmenu
 
 mainmenu_option next_comment
 comment 'General setup'
-if [ "$CONFIG_DECSTATION" = "y" -o "$CONFIG_DDB5074" = "y" ]; then
+if [ "$CONFIG_DECSTATION" = "y" -o \
+     "$CONFIG_DDB5074" = "y" -o    \
+     "$CONFIG_DDB5476" = "y" -o    \
+     "$CONFIG_NINO" = "y" ]; then
    define_bool CONFIG_CPU_LITTLE_ENDIAN y
 else
    bool 'Generate little endian code' CONFIG_CPU_LITTLE_ENDIAN
 fi
+bool 'Kernel floating-point emulation' CONFIG_MIPS_FPU_EMULATOR
 
 if [ "$CONFIG_PROC_FS" = "y" ]; then
    define_bool CONFIG_KCORE_ELF y
@@ -158,22 +282,30 @@
    bool 'Include forward keyboard' CONFIG_FORWARD_KEYBOARD 
 fi
 
+if [ "$CONFIG_ARC32" = "y" ]; then
+   bool 'ARC console support' CONFIG_ARC_CONSOLE
+fi
+
 define_bool CONFIG_BINFMT_AOUT n
 define_bool CONFIG_BINFMT_ELF y
 tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
 
 bool 'Networking support' CONFIG_NET
 
-if [ "$CONFIG_PCI" = "y" ]; then
-    source drivers/pci/Config.in
+source drivers/pci/Config.in
+
+bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+   source drivers/pcmcia/Config.in
+else
+   define_bool CONFIG_PCMCIA n
 fi
 
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
 
-source drivers/parport/Config.in
-
 if [ "$CONFIG_DECSTATION" = "y" ]; then
     bool 'TURBOchannel support' CONFIG_TC
 #    if [ "$CONFIG_TC" = "y" ]; then
@@ -186,14 +318,10 @@
    source drivers/pnp/Config.in
 fi
 
-if [ "$CONFIG_HOTPLUG" = "y" ] ; then
-   source drivers/pcmcia/Config.in
-else
-   define_bool CONFIG_PCMCIA n
-fi
-
 source drivers/mtd/Config.in
 
+source drivers/parport/Config.in
+
 source drivers/block/Config.in
 
 source drivers/md/Config.in
@@ -202,10 +330,7 @@
    source net/Config.in
 fi
 
-if [ "$CONFIG_DECSTATION" != "y" -a \
-     "$CONFIG_SGI_IP22" != "y" ]; then
-   source drivers/telephony/Config.in
-fi
+source drivers/telephony/Config.in
 
 if [ "$CONFIG_SGI_IP22" != "y" -a \
      "$CONFIG_DECSTATION" != "y" ]; then
@@ -236,7 +361,7 @@
 
 if [ "$CONFIG_DECSTATION" != "y" -a \
      "$CONFIG_SGI_IP22" != "y" ]; then
-   source drivers/i2o/Config.in
+   source drivers/message/i2o/Config.in
 fi
 
 if [ "$CONFIG_NET" = "y" ]; then
@@ -245,69 +370,40 @@
 
    bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-
-      if [ "$CONFIG_SGI_IP22" != "y" -a \
-      	   "$CONFIG_DECSTATION" != "y" -a \
-	   "$CONFIG_BAGET_MIPS" != "y" ]; then
-
-	 source drivers/net/Config.in
-
-	 if [ "$CONFIG_ATM" = "y" ]; then
-	    source drivers/atm/Config.in
-	 fi
-      else
-	 tristate 'Dummy net driver support' CONFIG_DUMMY
-	 tristate 'SLIP (serial line) support' CONFIG_SLIP
-	 if [ "$CONFIG_SLIP" != "n" ]; then
-	    bool ' CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
-	    bool ' Keepalive and linefill' CONFIG_SLIP_SMART
-	 fi
-	 tristate 'PPP (point-to-point) support' CONFIG_PPP
-	 if [ ! "$CONFIG_PPP" = "n" ]; then
-	    comment 'CCP compressors for PPP are only built as modules.'
-	 fi
-         if [ "$CONFIG_SGI_IP22" = "y" ]; then
-	    bool 'SGI Seeq ethernet controller support' CONFIG_SGISEEQ
-	 fi
-	 if [ "$CONFIG_DECSTATION" = "y" ]; then
-	    bool 'DEC LANCE ethernet controller support' CONFIG_DECLANCE
-	 fi
-	 if [ "$CONFIG_BAGET_MIPS" = "y" ]; then
-	    tristate 'Baget AMD LANCE support' CONFIG_BAGETLANCE
-	 fi
+      source drivers/net/Config.in
+      if [ "$CONFIG_ATM" = "y" ]; then
+         source drivers/atm/Config.in
       fi
    fi
    endmenu
 fi
 
-if [ "$CONFIG_ISA" = "y" -o "$CONFIG_PCI" = "y" ]; then
-   mainmenu_option next_comment
-   comment 'ISDN subsystem'
-
-   if [ "$CONFIG_NET" != "n" ]; then
-      tristate 'ISDN support' CONFIG_ISDN
-      if [ "$CONFIG_ISDN" != "n" ]; then
-	 source drivers/isdn/Config.in
-      fi
-   fi
-   endmenu
+source net/ax25/Config.in
 
-   mainmenu_option next_comment
-   comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+source net/irda/Config.in
 
-   bool 'Support non-SCSI/IDE/ATAPI drives' CONFIG_CD_NO_IDESCSI
-   if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
-      source drivers/cdrom/Config.in
+mainmenu_option next_comment
+comment 'ISDN subsystem'
+if [ "$CONFIG_NET" != "n" ]; then
+   tristate 'ISDN support' CONFIG_ISDN
+   if [ "$CONFIG_ISDN" != "n" ]; then
+      source drivers/isdn/Config.in
    fi
-   endmenu
 fi
+endmenu
 
-if [ "$CONFIG_DECSTATION" != "y" -a \
-     "$CONFIG_SGI_IP22" != "y" ]; then
-   source drivers/char/Config.in
+mainmenu_option next_comment
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
 
-   source drivers/media/Config.in
+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
+
+source drivers/char/Config.in
+
+source drivers/media/Config.in
 
 if [ "$CONFIG_DECSTATION" = "y" ]; then
    mainmenu_option next_comment
@@ -332,9 +428,7 @@
 #   if [ "$CONFIG_ACCESSBUS" = "y" ]; then
 #      bool 'MAXINE Access.Bus mouse (VSXXX-BB/GB) support' CONFIG_DTOP_MOUSE
 #   fi
-   bool 'Enhanced Real Time Clock Support' CONFIG_MIPS_RTC
-
-   define_tristate CONFIG_RTC $CONFIG_MIPS_RTC
+   bool 'Enhanced Real Time Clock Support' CONFIG_RTC
 
    endmenu
 fi
@@ -351,7 +445,10 @@
       else
 	 define_bool CONFIG_FONT_8x16 y
       fi
-      bool 'SGI PROM Console Support' CONFIG_SGI_PROM_CONSOLE
+   fi
+   bool 'PS/2 mouse support' CONFIG_PSMOUSE
+   if [ "$CONFIG_PSMOUSE" != "n" ]; then
+      define_bool CONFIG_MOUSE y
    fi
    bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
    if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
@@ -364,13 +461,12 @@
 
 if [ "$CONFIG_VT" = "y" ]; then
    mainmenu_option next_comment
-
    comment 'Console drivers'
-      if [ "$CONFIG_DECSTATION" != "y" ]; then
-	 bool 'VGA text console' CONFIG_VGA_CONSOLE
-      fi
-      bool 'Support for frame buffer devices' CONFIG_FB
+   bool 'VGA text console' CONFIG_VGA_CONSOLE
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+      tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
       source drivers/video/Config.in
+   fi
    endmenu
 fi
 
@@ -399,8 +495,15 @@
 if [ "$CONFIG_MODULES" = "y" ]; then
    bool ' Build fp execption handler module' CONFIG_MIPS_FPE_MODULE
 fi
-if [ "$CONFIG_SERIAL" = "y" ]; then
+if [ "$CONFIG_SERIAL" = "y" -o "$CONFIG_AU1000_UART" = "y" ]; then
   bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
+  dep_bool 'Console output to GDB' CONFIG_GDB_CONSOLE $CONFIG_REMOTE_DEBUG
+fi
+if [ "$CONFIG_SERIAL" = "y" ]; then
+  bool 'Low-level debugging' CONFIG_LL_DEBUG
 fi
 bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+if [ "$CONFIG_SMP" != "y" ]; then
+   bool 'Run uncached' CONFIG_MIPS_UNCACHED
+fi
 endmenu
diff -u --recursive --new-file v2.4.5/linux/arch/mips/dec/boot/ld.ecoff linux/arch/mips/dec/boot/ld.ecoff
--- v2.4.5/linux/arch/mips/dec/boot/ld.ecoff	Fri Jun 25 17:40:12 1999
+++ linux/arch/mips/dec/boot/ld.ecoff	Mon Jul  2 14:40:14 2001
@@ -13,7 +13,7 @@
   }
   .rdata :
   {
-    *(.rodata .rdata)
+    *(.rodata .rodata.* .rdata)
   }
   .data :
   {
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/Makefile linux/arch/mips/kernel/Makefile
--- v2.4.5/linux/arch/mips/kernel/Makefile	Tue Jul 11 11:14:42 2000
+++ linux/arch/mips/kernel/Makefile	Mon Jul  2 13:56:40 2001
@@ -6,93 +6,58 @@
 # unless it's something special (ie not a .c file).
 #
 
+.S.s:
+	$(CPP) $(AFLAGS) $< -o $@
 .S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
+	$(CC) $(AFLAGS) -c $< -o $@
+
+EXTRA_AFLAGS = -mips3 -mcpu=r4000
 
 all:	kernel.o head.o init_task.o
-EXTRA_ASFLAGS = -mips3 -mcpu=r4000
+
 O_TARGET := kernel.o
-O_OBJS	:= branch.o process.o signal.o entry.o traps.o ptrace.o vm86.o \
-	   ioport.o reset.o semaphore.o setup.o syscall.o sysmips.o ipc.o \
-	   scall_o32.o softfp.o unaligned.o
-OX_OBJS := mips_ksyms.o
+
+obj-y				+= branch.o process.o signal.o entry.o \
+				   traps.o ptrace.o vm86.o ioport.o reset.o \
+				   semaphore.o setup.o syscall.o sysmips.o \
+				   ipc.o scall_o32.o unaligned.o
+obj-$(CONFIG_MODULES)		+= mips_ksyms.o
 
 ifdef CONFIG_CPU_R3000
-O_OBJS	+= r2300_misc.o r2300_fpu.o r2300_switch.o
+obj-y	+= r2300_misc.o r2300_fpu.o r2300_switch.o
 else
-O_OBJS	+= r4k_misc.o r4k_switch.o 
+obj-y	+= r4k_misc.o r4k_switch.o 
 ifdef CONFIG_CPU_R6000
-O_OBJS	+= r6000_fpu.o
+obj-y	+= r6000_fpu.o
 else
-O_OBJS	+= r4k_fpu.o
-endif
-endif
-
-ifdef CONFIG_MIPS_FPE_MODULE
-M_OBJS += fpe.o
+obj-y	+= r4k_fpu.o
 endif
-
-#
-# SGIs have very different interrupt/timer hardware.
-#
-ifndef CONFIG_DECSTATION
-  ifndef CONFIG_BAGET_MIPS
-    O_OBJS += time.o
-    ifndef CONFIG_SGI_IP22
-      ifndef CONFIG_ORION
-        OX_OBJS += irq.o
-      endif
-    endif
-  endif
 endif
 
-#
-# Do we want to be able to execute IRIX elf binaries?
-#
-ifdef CONFIG_BINFMT_IRIX
-O_OBJS += irixelf.o irixioctl.o irixsig.o sysirix.o irixinv.o
+obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_MIPS_FPE_MODULE)	+= fpe.o
+ifndef CONFIG_MIPS_FPU_EMULATOR
+  obj-y				+= softfp.o
 endif
 
-#
-# Kernel debugging
-#
-ifdef CONFIG_REMOTE_DEBUG
-O_OBJS += gdb-low.o gdb-stub.o 
-endif
+# Old style irq support, going to die in 2.5.
+export-objs			+= old-irq.o
+obj-$(CONFIG_NEW_IRQ)		+= irq.o
+obj-$(CONFIG_ROTTEN_IRQ)	+= old-irq.o
 
-#
-# Depending from some other kernel option
-#
-ifdef CONFIG_PROC_FS
-O_OBJS += proc.o
-endif
+# transition from old time.c to new time.c
+# some boards uses old-time.c, some use time.c, and some use their own ones
+export-objs			+= old-time.o time.o
+obj-$(CONFIG_OLD_TIME_C)	+= old-time.o
+obj-$(CONFIG_NEW_TIME_C)	+= time.o
 
-#
-# Since we add the same object files to O_OBJS for different configurations.
-# O_OBJS might contain duplicate files.  We correct this by filtering out
-# duplicate files.  Just to avoid users having to know about all the
-# compatibility stuff between various boards and boards.
-#
-O_OBJS := $(sort $(O_OBJS))
+obj-$(CONFIG_BINFMT_IRIX)	+= irixelf.o irixioctl.o irixsig.o sysirix.o \
+				   irixinv.o
+obj-$(CONFIG_REMOTE_DEBUG)	+= gdb-low.o gdb-stub.o 
+obj-$(CONFIG_PCI)		+= pci-dma.o
+obj-$(CONFIG_PROC_FS)		+= proc.o
 
 entry.o: entry.S
-
 head.o: head.S
-
-#r4k_switch.o: r4k_switch.S
-#
-#r4k_misc.o: r4k_misc.S
-#
-#r4k_fpu.o: r4k_fpu.S
-#
-#r2300_switch.o: r2300_switch.S
-#
-#r2300_misc.o: r2300_misc.S
-#
-#r2300_fpu.o: r2300_fpu.S
-#
-#r6000_fpu.o: r6000_fpu.S
-
-clean:
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/entry.S linux/arch/mips/kernel/entry.S
--- v2.4.5/linux/arch/mips/kernel/entry.S	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/kernel/entry.S	Mon Jul  2 13:56:40 2001
@@ -12,6 +12,7 @@
 #include <linux/config.h>
 #include <linux/sys.h>
 
+#include <asm/addrspace.h>
 #include <asm/asm.h>
 #include <asm/current.h>
 #include <asm/errno.h>
@@ -43,11 +44,16 @@
 EXPORT(ret_from_sys_call)
 EXPORT(ret_from_irq)
 		.type	ret_from_irq,@function
-		lw	t0, irq_stat		# softirq_active
-		lw	t1, irq_stat+4		# softirq_mask.  unused delay slot
+		la	t1, irq_stat		# softirq_active
+#ifdef CONFIG_SMP
+		lw	t0, TASK_PROCESSOR($28)
+		sll	t0, t0, 5
+		addu	t1, t0
+#endif
+		lw	t0, 0(t1)		# softirq_active
+		lw	t1, 4(t1)		# softirq_mask.  unused delay slot
 		and	t0, t1
 		bnez	t0, handle_softirq
-
 
 9:		lw	t0,PT_STATUS(sp)	# returning to kernel mode?
 		lw	t2, TASK_NEED_RESCHED($28)
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/gdb-stub.c linux/arch/mips/kernel/gdb-stub.c
--- v2.4.5/linux/arch/mips/kernel/gdb-stub.c	Sun Oct  1 20:35:15 2000
+++ linux/arch/mips/kernel/gdb-stub.c	Mon Jul  2 13:56:40 2001
@@ -64,6 +64,61 @@
  * Host:                  Reply:
  * $m0,10#2a               +$00010203040506070809101112131415#42
  *
+ * 
+ *  ==============
+ *  MORE EXAMPLES:
+ *  ==============
+ *
+ *  For reference -- the following are the steps that one
+ *  company took (RidgeRun Inc) to get remote gdb debugging
+ *  going. In this scenario the host machine was a PC and the
+ *  target platform was a Galileo EVB64120A MIPS evaluation
+ *  board.
+ *   
+ *  Step 1:
+ *  First download gdb-5.0.tar.gz from the internet.
+ *  and then build/install the package.
+ * 
+ *  Example:
+ *    $ tar zxf gdb-5.0.tar.gz
+ *    $ cd gdb-5.0
+ *    $ ./configure --target=mips-linux-elf
+ *    $ make
+ *    $ install
+ *    $ which mips-linux-elf-gdb
+ *    /usr/local/bin/mips-linux-elf-gdb
+ * 
+ *  Step 2:
+ *  Configure linux for remote debugging and build it.
+ * 
+ *  Example:
+ *    $ cd ~/linux
+ *    $ make menuconfig <go to "Kernel Hacking" and turn on remote debugging>
+ *    $ make dep; make vmlinux
+ * 
+ *  Step 3:
+ *  Download the kernel to the remote target and start
+ *  the kernel running. It will promptly halt and wait 
+ *  for the host gdb session to connect. It does this
+ *  since the "Kernel Hacking" option has defined 
+ *  CONFIG_REMOTE_DEBUG which in turn enables your calls
+ *  to:
+ *     set_debug_traps();
+ *     breakpoint();
+ * 
+ *  Step 4:
+ *  Start the gdb session on the host.
+ * 
+ *  Example:
+ *    $ mips-linux-elf-gdb vmlinux
+ *    (gdb) set remotebaud 115200
+ *    (gdb) target remote /dev/ttyS1
+ *    ...at this point you are connected to 
+ *       the remote target and can use gdb
+ *       in the normal fasion. Setting 
+ *       breakpoints, single stepping,
+ *       printing variables, etc.
+ *
  */
 
 #include <linux/string.h>
@@ -71,6 +126,8 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/init.h>
 
 #include <asm/asm.h>
 #include <asm/mipsregs.h>
@@ -315,13 +372,10 @@
  * signals, which are primarily what GDB understands.  It also indicates
  * which hardware traps we need to commandeer when initializing the stub.
  */
-static struct hard_trap_info
-{
+static struct hard_trap_info {
 	unsigned char tt;		/* Trap type code for MIPS R3xxx and R4xxx */
 	unsigned char signo;		/* Signal that we map this trap into */
 } hard_trap_info[] = {
-	{ 4, SIGBUS },			/* address error (load) */
-	{ 5, SIGBUS },			/* address error (store) */
 	{ 6, SIGBUS },			/* instruction bus error */
 	{ 7, SIGBUS },			/* data bus error */
 	{ 9, SIGTRAP },			/* break */
@@ -350,6 +404,7 @@
 	for (ht = hard_trap_info; ht->tt && ht->signo; ht++)
 		set_except_vector(ht->tt, trap_low);
   
+	putDebugChar('+'); /* 'hello world' */
 	/*
 	 * In case GDB is started before us, ack any packets
 	 * (presumably "$?#xx") sitting there.
@@ -373,7 +428,7 @@
  */
 extern void fltr_set_mem_err(void)
 {
-  /* FIXME: Needs to be written... */
+	/* FIXME: Needs to be written... */
 }
 
 /*
@@ -401,8 +456,7 @@
 
 	*intValue = 0;
 
-	while (**ptr)
-	{
+	while (**ptr) {
 		hexValue = hex(**ptr);
 		if (hexValue < 0)
 			break;
@@ -904,3 +958,47 @@
 			lw	$9,0($8)
 	");
 }
+
+#ifdef CONFIG_GDB_CONSOLE
+
+void gdb_puts(const char *str)
+{
+	int l = strlen(str);
+	char outbuf[18];
+
+	outbuf[0]='O';
+
+	while(l) {
+		int i = (l>8)?8:l;
+		mem2hex((char *)str, &outbuf[1], i, 0);
+		outbuf[(i*2)+1]=0;
+		putpacket(outbuf); 
+		str += i;
+		l -= i;
+	}
+}
+
+static kdev_t gdb_console_dev(struct console *con)
+{
+	return MKDEV(1, 3); /* /dev/null */
+}
+
+static void gdb_console_write(struct console *con, const char *s, unsigned n)
+{
+	gdb_puts(s);
+}
+
+static struct console gdb_console = {
+	name:	"gdb",
+	write:	gdb_console_write,
+	device:	gdb_console_dev,
+	flags:	CON_PRINTBUFFER,
+	index:	-1
+};
+
+__init void register_gdb_console(void)
+{
+	register_console(&gdb_console);
+}
+     
+#endif
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/head.S linux/arch/mips/kernel/head.S
--- v2.4.5/linux/arch/mips/kernel/head.S	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/kernel/head.S	Mon Jul  2 13:56:40 2001
@@ -1,5 +1,4 @@
-/* $Id: head.S,v 1.18 2000/03/03 22:17:07 kevink Exp $
- *
+/*
  * arch/mips/kernel/head.S
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -15,6 +14,14 @@
  * Copyright (C) 1999 Silicon Graphics, Inc.
  *
  * Head.S contains the MIPS exception handler and startup code.
+ *
+ **************************************************************************
+ *  9 Nov, 2000.
+ *  Added Cache Error exception handler and SBDDP EJTAG debug exception.
+ *
+ *  Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ **************************************************************************
  */
 #include <linux/config.h>
 #include <linux/threads.h>
@@ -52,9 +59,19 @@
 	.set	noat
 	LEAF(except_vec0_r4000)
 	.set	mips3
+#ifdef CONFIG_SMP
+	mfc0	k1, CP0_CONTEXT
+	la	k0, current_pgd
+	srl	k1, 23
+	sll	k1, 2
+	addu	k1, k0, k1
+	lw	k1, (k1)
+#else 
+	lw	k1, current_pgd			# get pgd pointer
+#endif	
 	mfc0	k0, CP0_BADVADDR		# Get faulting address
 	srl	k0, k0, 22			# get pgd only bits
-	lw	k1, current_pgd			# get pgd pointer
+
 	sll	k0, k0, 2
 	addu	k1, k1, k0			# add in pgd offset
 	mfc0	k0, CP0_CONTEXT			# get context reg
@@ -69,8 +86,8 @@
 	srl	k1, k1, 6			# convert to entrylo1
 	mtc0	k1, CP0_ENTRYLO1		# load it
 	b	1f
-	 tlbwr					# write random tlb entry
-1:	
+	tlbwr					# write random tlb entry
+1:
 	nop
 	eret					# return from trap
 	END(except_vec0_r4000)
@@ -308,12 +325,26 @@
 
 	/* Cache Error */
 	LEAF(except_vec2_generic)
-	/* Famous last words: unreached */
-	mfc0	a1,CP0_ERROREPC
-	PRINT("Cache error exception: c0_errorepc == %08x\n")
-1:
-	j	1b
-	 nop
+	.set	noat
+	.set    mips0
+	/*
+	 * This is a very bad place to be.  Our cache error
+	 * detection has triggered.  If we have write-back data
+	 * in the cache, we may not be able to recover.  As a
+	 * first-order desperate measure, turn off KSEG0 cacheing.
+	 */
+	mfc0	k0,CP0_CONFIG
+	li	k1,~CONF_CM_CMASK
+	and	k0,k0,k1
+	ori	k0,k0,CONF_CM_UNCACHED
+	mtc0	k0,CP0_CONFIG
+	/* Give it a few cycles to sink in... */
+	nop
+	nop
+	nop
+
+	j	cache_parity_error
+	nop
 	END(except_vec2_generic)
 
 	/* General exception vector R4000 version. */
@@ -338,6 +369,7 @@
  * c0_badvaddr because after return from this exception handler the load /
  * store will be re-executed.
  */
+	.set    mips3
 handle_vced:
 	mfc0	k0, CP0_BADVADDR
  li k1, -4
@@ -393,6 +425,38 @@
 	 nop
 	END(except_vec4)
 
+	/*
+	 * SBDDP EJTAG debug exception handler.
+	 * The EJTAG debug exception entry point is 0xbfc00480, which
+	 * normally is in the boot PROM, so the boot PROM must do a
+	 * unconditional jump to this vector.
+	 */	
+	NESTED(except_vec_ejtag_debug, 0, sp)
+	j	ejtag_debug_handler
+	 nop
+	END(except_vec_ejtag_debug)
+
+	/*
+	 * EJTAG debug exception handler.
+	 */
+	NESTED(ejtag_debug_handler, PT_SIZE, sp)
+	.set	noat
+	.set	noreorder
+	SAVE_ALL
+	PRINT("SDBBP EJTAG debug exception - not handled yet, just ignored!\n");
+	mfc0	k0, $23         # Get EJTAG Debug register.
+	mfc0    k1, $24         # Get DEPC register.
+	bgez	k0, 1f
+	 addiu	k1, k1, 4	# SBDDP inst. in delay slot.
+	addiu	k1, k1, 4
+1:	mtc0	k1, $24
+	RESTORE_ALL
+	.word	0x4200001f      # deret, return EJTAG debug exception.
+	 nop
+	.set	at
+	END(ejtag_debug_handler)
+
+		
 /*
  * Kernel entry point
  */
@@ -407,9 +471,9 @@
 	 */
 	la	$28, init_task_union
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
-	sw	t0, kernelsp
 	subu	sp, t0, 4*SZREG
 
+	sw	t0, kernelsp
 	/* The firmware/bootloader passes argc/argp/envp
 	 * to us as arguments.  But clear bss first because
 	 * the romvec and other important info is stored there
@@ -427,6 +491,30 @@
 	 nop
 	END(kernel_entry)
 
+
+#ifdef CONFIG_SMP
+
+/*
+ * SMP slave cpus entry point.  Board specific code
+ * for bootstrap calls this function after setting up
+ * the stack and gp registers. 
+ */
+	LEAF(smp_bootstrap)
+	.set push
+	.set noreorder
+	mtc0	zero, CP0_WIRED
+	CLI
+	mfc0	t0, CP0_STATUS
+	li	t1, ~(ST0_CU1|ST0_CU2|ST0_CU3|ST0_BEV); 
+	and	t0, t1
+	or	t0, (ST0_CU0|ST0_KX|ST0_SX|ST0_FR);
+	addiu	a0, zero, 0
+	jal	start_secondary
+         mtc0	t0, CP0_STATUS
+	.set pop
+	END(smp_bootstrap)
+#endif
+	
 /*
  * This buffer is reserved for the use of the cache error handler.
  */
@@ -434,12 +522,19 @@
 		EXPORT(cache_error_buffer)
 		.fill	32*4,1,0
 
+#ifndef CONFIG_SMP
 EXPORT(kernelsp)
 		PTR	0
 EXPORT(current_pgd)
-		PTR	0
+		PTR     0
+#else
+		/* There's almost certainly a better way to do this with the macros...*/
+		.globl kernelsp
+		.comm  kernelsp,     NR_CPUS * 8, 8
+		.globl current_pgd
+		.comm	current_pgd, NR_CPUS * 8, 8
+#endif
 		.text
-
 		.org	0x1000
 EXPORT(swapper_pg_dir)
 
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/i8259.c linux/arch/mips/kernel/i8259.c
--- v2.4.5/linux/arch/mips/kernel/i8259.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/i8259.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,308 @@
+/*
+ * 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.
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ */
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+
+void enable_8259A_irq(unsigned int irq);
+void disable_8259A_irq(unsigned int irq);
+
+/*
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ * plus some generic x86 specific things if generic specifics makes
+ * any sense at all.
+ * this file should become arch/i386/kernel/irq.c when the old irq.c
+ * moves to arch independent land
+ */
+
+spinlock_t i8259A_lock = SPIN_LOCK_UNLOCKED;
+
+static void end_8259A_irq (unsigned int irq)
+{
+	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+		enable_8259A_irq(irq);
+}
+
+#define shutdown_8259A_irq	disable_8259A_irq
+
+void mask_and_ack_8259A(unsigned int);
+
+static unsigned int startup_8259A_irq(unsigned int irq)
+{ 
+	enable_8259A_irq(irq);
+
+	return 0; /* never anything pending */
+}
+
+static struct hw_interrupt_type i8259A_irq_type = {
+	"XT-PIC",
+	startup_8259A_irq,
+	shutdown_8259A_irq,
+	enable_8259A_irq,
+	disable_8259A_irq,
+	mask_and_ack_8259A,
+	end_8259A_irq,
+	NULL
+};
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) 	(((unsigned char *)&(y))[x])
+#define cached_21	(__byte(0,cached_irq_mask))
+#define cached_A1	(__byte(1,cached_irq_mask))
+
+void disable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	cached_irq_mask |= mask;
+	if (irq & 8)
+		outb(cached_A1,0xA1);
+	else
+		outb(cached_21,0x21);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+void enable_8259A_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << irq);
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	cached_irq_mask &= mask;
+	if (irq & 8)
+		outb(cached_A1,0xA1);
+	else
+		outb(cached_21,0x21);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+int i8259A_irq_pending(unsigned int irq)
+{
+	unsigned int mask = 1 << irq;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	if (irq < 8)
+		ret = inb(0x20) & mask;
+	else
+		ret = inb(0xA0) & (mask >> 8);
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+
+	return ret;
+}
+
+void make_8259A_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &i8259A_irq_type;
+	enable_irq(irq);
+}
+
+/*
+ * This function assumes to be called rarely. Switching between
+ * 8259A registers is slow.
+ * This has to be protected by the irq controller spinlock
+ * before being called.
+ */
+static inline int i8259A_irq_real(unsigned int irq)
+{
+	int value;
+	int irqmask = 1 << irq;
+
+	if (irq < 8) {
+		outb(0x0B,0x20);		/* ISR register */
+		value = inb(0x20) & irqmask;
+		outb(0x0A,0x20);		/* back to the IRR register */
+		return value;
+	}
+	outb(0x0B,0xA0);		/* ISR register */
+	value = inb(0xA0) & (irqmask >> 8);
+	outb(0x0A,0xA0);		/* back to the IRR register */
+	return value;
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+void mask_and_ack_8259A(unsigned int irq)
+{
+	unsigned int irqmask = 1 << irq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+	/*
+	 * Lightweight spurious IRQ detection. We do not want to overdo
+	 * spurious IRQ handling - it's usually a sign of hardware problems, so
+	 * we only do the checks we can do without slowing down good hardware
+	 * nnecesserily.
+	 *
+	 * Note that IRQ7 and IRQ15 (the two spurious IRQs usually resulting
+	 * rom the 8259A-1|2 PICs) occur even if the IRQ is masked in the 8259A.
+	 * Thus we can check spurious 8259A IRQs without doing the quite slow
+	 * i8259A_irq_real() call for every IRQ.  This does not cover 100% of
+	 * spurious interrupts, but should be enough to warn the user that
+	 * there is something bad going on ...
+	 */
+	if (cached_irq_mask & irqmask)
+		goto spurious_8259A_irq;
+	cached_irq_mask |= irqmask;
+
+handle_real_irq:
+	if (irq & 8) {
+		inb(0xA1);		/* DUMMY - (do we need this?) */
+		outb(cached_A1,0xA1);
+		outb(0x60+(irq&7),0xA0);/* 'Specific EOI' to slave */
+		outb(0x62,0x20);	/* 'Specific EOI' to master-IRQ2 */
+	} else {
+		inb(0x21);		/* DUMMY - (do we need this?) */
+		outb(cached_21,0x21);
+		outb(0x60+irq,0x20);	/* 'Specific EOI' to master */
+	}
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+	return;
+
+spurious_8259A_irq:
+	/*
+	 * this is the slow path - should happen rarely.
+	 */
+	if (i8259A_irq_real(irq))
+		/*
+		 * oops, the IRQ _is_ in service according to the
+		 * 8259A - not spurious, go handle it.
+		 */
+		goto handle_real_irq;
+
+	{
+		static int spurious_irq_mask = 0;
+		/*
+		 * At this point we can be sure the IRQ is spurious,
+		 * lets ACK and report it. [once per IRQ]
+		 */
+		if (!(spurious_irq_mask & irqmask)) {
+			printk("spurious 8259A interrupt: IRQ%d.\n", irq);
+			spurious_irq_mask |= irqmask;
+		}
+		irq_err_count++;
+		/*
+		 * Theoretically we do not have to handle this IRQ,
+		 * but in Linux this does not cause problems and is
+		 * simpler for us.
+		 */
+		goto handle_real_irq;
+	}
+}
+
+void __init init_8259A(int auto_eoi)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&i8259A_lock, flags);
+
+	outb(0xff, 0x21);	/* mask all of 8259A-1 */
+	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
+
+	/*
+	 * outb_p - this has to work on a wide range of PC hardware.
+	 */
+	outb_p(0x11, 0x20);	/* ICW1: select 8259A-1 init */
+	outb_p(0x20 + 0, 0x21);	/* ICW2: 8259A-1 IR0-7 mapped to 0x20-0x27 */
+	outb_p(0x04, 0x21);	/* 8259A-1 (the master) has a slave on IR2 */
+	if (auto_eoi)
+		outb_p(0x03, 0x21);	/* master does Auto EOI */
+	else
+		outb_p(0x01, 0x21);	/* master expects normal EOI */
+
+	outb_p(0x11, 0xA0);	/* ICW1: select 8259A-2 init */
+	outb_p(0x20 + 8, 0xA1);	/* ICW2: 8259A-2 IR0-7 mapped to 0x28-0x2f */
+	outb_p(0x02, 0xA1);	/* 8259A-2 is a slave on master's IR2 */
+	outb_p(0x01, 0xA1);	/* (slave's support for AEOI in flat mode
+				    is to be investigated) */
+
+	if (auto_eoi)
+		/*
+		 * in AEOI mode we just have to mask the interrupt
+		 * when acking.
+		 */
+		i8259A_irq_type.ack = disable_8259A_irq;
+	else
+		i8259A_irq_type.ack = mask_and_ack_8259A;
+
+	udelay(100);		/* wait for 8259A to initialize */
+
+	outb(cached_21, 0x21);	/* restore master IRQ mask */
+	outb(cached_A1, 0xA1);	/* restore slave IRQ mask */
+
+	spin_unlock_irqrestore(&i8259A_lock, flags);
+}
+
+asmlinkage void i8259_do_irq(int irq, struct pt_regs regs)
+{
+	panic("i8259_do_irq: I want to be implemented");
+}
+
+/*
+ * IRQ2 is cascade interrupt to second interrupt controller
+ */
+static struct irqaction irq2 = {
+	no_action, 0, 0, "cascade", NULL, NULL
+};
+
+static struct resource pic1_io_resource = {
+	"pic1", 0x20, 0x3f, IORESOURCE_BUSY
+};
+
+static struct resource pic2_io_resource = {
+	"pic2", 0xa0, 0xbf, IORESOURCE_BUSY
+};
+
+/*
+ * On systems with i8259-style interrupt controllers we assume for
+ * driver compatibility reasons interrupts 0 - 15 to be the i8295
+ * interrupts even if the hardware uses a different interrupt numbering.
+ */
+void __init init_i8259_irqs (void)
+{
+	int i;
+
+	request_resource(&ioport_resource, &pic1_io_resource);
+	request_resource(&ioport_resource, &pic2_io_resource);
+	setup_irq(2, &irq2);
+
+	init_8259A(0);
+
+	for (i = 0; i < 16; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 1;
+		irq_desc[i].handler = &i8259A_irq_type;
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/irixsig.c linux/arch/mips/kernel/irixsig.c
--- v2.4.5/linux/arch/mips/kernel/irixsig.c	Wed Jan 24 15:21:10 2001
+++ linux/arch/mips/kernel/irixsig.c	Mon Jul  2 13:56:40 2001
@@ -714,7 +714,7 @@
 					SET_LINKS(p);
 					notify_parent(p, SIGCHLD);
 				} else
-					release(p);
+					release_task(p);
 				goto end_waitsys;
 			default:
 				continue;
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.4.5/linux/arch/mips/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/mips/kernel/irq.c	Mon Jul  2 13:56:40 2001
@@ -8,289 +8,367 @@
  * Copyright (C) 1992 Linus Torvalds
  * Copyright (C) 1994 - 2000 Ralf Baechle
  */
-#include <linux/config.h>
-#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/irq.h>
 #include <linux/init.h>
-#include <linux/kernel_stat.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/types.h>
 #include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/timex.h>
+#include <linux/kernel_stat.h>
 #include <linux/slab.h>
+#include <linux/mm.h>
 #include <linux/random.h>
+#include <linux/sched.h>
 
-#include <asm/bitops.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/mipsregs.h>
 #include <asm/system.h>
-#include <asm/sni.h>
-#include <asm/nile4.h>
 
 /*
- * Linux has a controller-independent x86 interrupt architecture.
- * every controller has a 'controller-template', that is used
- * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the apropriate
- * controller. Thus drivers need not be aware of the
- * interrupt-controller.
- *
- * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
- * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
- * (IO-APICs assumed to be messaging to Pentium local-APICs)
- *
- * the code is designed to be easily extended with new/different
- * interrupt controllers, without having to do assembly magic.
+ * Controller mappings for all interrupt sources:
  */
+irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
+	{ [0 ... NR_IRQS-1] = { 0, &no_irq_type, NULL, 0, SPIN_LOCK_UNLOCKED}};
 
 /*
- * This contains the irq mask for both 8259A irq controllers, it's an
- * int so we can deal with the third PIC in some systems like the RM300.
- * (XXX This is broken for big endian.)
+ * Special irq handlers.
  */
-static unsigned int cached_irq_mask = 0xffff;
-
-#define __byte(x,y) (((unsigned char *)&(y))[x])
-#define __word(x,y) (((unsigned short *)&(y))[x])
-#define __long(x,y) (((unsigned int *)&(y))[x])
 
-#define cached_21       (__byte(0,cached_irq_mask))
-#define cached_A1       (__byte(1,cached_irq_mask))
-
-unsigned long spurious_count = 0;
+void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
 
 /*
- * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
- * PCI devices.  Other onboard hardware needs specific routines.
+ * Generic no controller code
  */
-static inline void mask_irq(unsigned int irq)
-{
-	cached_irq_mask |= 1 << irq;
-	if (irq & 8) {
-		outb(cached_A1, 0xa1);
-	} else {
-		outb(cached_21, 0x21);
-	}
-}
 
-static inline void unmask_irq(unsigned int irq)
-{
-	cached_irq_mask &= ~(1 << irq);
-	if (irq & 8) {
-		outb(cached_A1, 0xa1);
-	} else {
-		outb(cached_21, 0x21);
-	}
-}
-
-void i8259_disable_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-
-	save_and_cli(flags);
-	mask_irq(irq_nr);
-	restore_flags(flags);
-}
+static void enable_none(unsigned int irq) { }
+static unsigned int startup_none(unsigned int irq) { return 0; }
+static void disable_none(unsigned int irq) { }
+static void ack_none(unsigned int irq)
+{
+	/*
+	 * '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
+	 * a generic callback i think.
+	 */
+	printk("unexpected interrupt %d\n", irq);
+}
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define shutdown_none	disable_none
+#define end_none	enable_none
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	startup_none,
+	shutdown_none,
+	enable_none,
+	disable_none,
+	ack_none,
+	end_none
+};
 
-void i8259_enable_irq(unsigned int irq_nr)
-{
-	unsigned long flags;
-	save_and_cli(flags);
-	unmask_irq(irq_nr);
-	restore_flags(flags);
-}
+volatile unsigned long irq_err_count, spurious_count;
 
-static struct irqaction *irq_action[NR_IRQS] = {
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
-	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
-};
+/*
+ * Generic, controller-independent functions:
+ */
 
 int get_irq_list(char *buf)
 {
-	int i, len = 0;
 	struct irqaction * action;
+	char *p = buf;
+	int i;
+
+	p += sprintf(p, "           ");
+	for (i=0; i < 1 /*smp_num_cpus*/; i++)
+		p += sprintf(p, "CPU%d       ", i);
+	*p++ = '\n';
 
-	for (i = 0 ; i < 32 ; i++) {
-		action = irq_action[i];
+	for (i = 0 ; i < NR_IRQS ; i++) {
+		action = irq_desc[i].action;
 		if (!action) 
 			continue;
-		len += sprintf(buf+len, "%2d: %8d %c %s",
-			i, kstat.irqs[0][i],
-			(action->flags & SA_INTERRUPT) ? '+' : ' ',
-			action->name);
-		for (action=action->next; action; action = action->next) {
-			len += sprintf(buf+len, ",%s %s",
-				(action->flags & SA_INTERRUPT) ? " +" : "",
-				action->name);
-		}
-		len += sprintf(buf+len, "\n");
+		p += sprintf(p, "%3d: ",i);
+		p += sprintf(p, "%10u ", kstat_irqs(i));
+		p += sprintf(p, " %14s", irq_desc[i].handler->typename);
+		p += sprintf(p, "  %s", action->name);
+
+		for (action=action->next; action; action = action->next)
+			p += sprintf(p, ", %s", action->name);
+		*p++ = '\n';
 	}
-	return len;
-}
-
-static inline void i8259_mask_and_ack_irq(int irq)
-{
-	cached_irq_mask |= 1 << irq;
-
-	if (irq & 8) {
-		inb(0xa1);
-		outb(cached_A1, 0xa1);
-		outb(0x62, 0x20);		/* Specific EOI to cascade */
-                outb(0x20, 0xa0);
-        } else {
-		inb(0x21);
-		outb(cached_21, 0x21);
-		outb(0x20, 0x20);
-        }
+	p += sprintf(p, "ERR: %10lu\n", irq_err_count);
+	return p - buf;
 }
 
-asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
+/*
+ * This should really return information about whether
+ * we should do bottom half handling etc. Right now we
+ * end up _always_ checking the bottom half, which is a
+ * waste of time and is not what some drivers would
+ * prefer.
+ */
+int handle_IRQ_event(unsigned int irq, struct pt_regs * regs, struct irqaction * action)
 {
-	struct irqaction *action;
-	int do_random, cpu;
-
-	cpu = smp_processor_id();
-	irq_enter(cpu);
+	int status;
+	int cpu = smp_processor_id();
 
-	if (irq >= 16)
-		goto out;
+	irq_enter(cpu, irq);
 
-	i8259_mask_and_ack_irq(irq);
-
-	kstat.irqs[cpu][irq]++;
-
-	action = *(irq + irq_action);
-	if (!action)
-		goto out;
+	status = 1;	/* Force the "do bottom halves" bit */
 
 	if (!(action->flags & SA_INTERRUPT))
 		__sti();
-	action = *(irq + irq_action);
-	do_random = 0;
-       	do {
-		do_random |= action->flags;
+
+	do {
+		status |= action->flags;
 		action->handler(irq, action->dev_id, regs);
 		action = action->next;
-       	} while (action);
-	if (do_random & SA_SAMPLE_RANDOM)
+	} while (action);
+	if (status & SA_SAMPLE_RANDOM)
 		add_interrupt_randomness(irq);
 	__cli();
-	unmask_irq (irq);
 
-out:
-	irq_exit(cpu);
+	irq_exit(cpu, irq);
+
+	return status;
 }
 
 /*
- * do_IRQ handles IRQ's that have been installed without the
- * SA_INTERRUPT flag: it uses the full signal-handling return
- * and runs with other interrupts enabled. All relatively slow
- * IRQ's should use this format: notably the keyboard/timer
- * routines.
+ * Generic enable/disable code: this just calls
+ * down into the PIC-specific version for the actual
+ * hardware disable after having gotten the irq
+ * controller lock. 
+ */
+ 
+/**
+ *	disable_irq_nosync - disable an irq without waiting
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line. Disables of an interrupt
+ *	stack. Unlike disable_irq(), this function does not ensure existing
+ *	instances of the IRQ handler have completed before returning.
+ *
+ *	This function may be called from IRQ context.
  */
-asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+ 
+void inline disable_irq_nosync(unsigned int irq)
 {
-	struct irqaction *action;
-	int do_random, cpu;
-
-	cpu = smp_processor_id();
-	irq_enter(cpu);
-	kstat.irqs[cpu][irq]++;
+	irq_desc_t *desc = irq_desc + irq;
+	unsigned long flags;
 
-	action = *(irq + irq_action);
-	if (action) {
-		if (!(action->flags & SA_INTERRUPT))
-			__sti();
-		action = *(irq + irq_action);
-		do_random = 0;
-        	do {
-			do_random |= action->flags;
-			action->handler(irq, action->dev_id, regs);
-			action = action->next;
-        	} while (action);
-		if (do_random & SA_SAMPLE_RANDOM)
-			add_interrupt_randomness(irq);
-		__cli();
+	spin_lock_irqsave(&desc->lock, flags);
+	if (!desc->depth++) {
+		desc->status |= IRQ_DISABLED;
+		desc->handler->disable(irq);
 	}
-	irq_exit(cpu);
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
 
-	if (softirq_active(cpu)&softirq_mask(cpu))
-		do_softirq();
+/**
+ *	disable_irq - disable an irq and wait for completion
+ *	@irq: Interrupt to disable
+ *
+ *	Disable the selected interrupt line. Disables of an interrupt
+ *	stack. That is for two disables you need two enables. This
+ *	function waits for any pending IRQ handlers for this interrupt
+ *	to complete before returning. If you use this function while
+ *	holding a resource the IRQ handler may need you will deadlock.
+ *
+ *	This function may be called - with care - from IRQ context.
+ */
+ 
+void disable_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
 
-	/* unmasking and bottom half handling is done magically for us. */
+	if (!local_irq_count(smp_processor_id())) {
+		do {
+			barrier();
+		} while (irq_desc[irq].status & IRQ_INPROGRESS);
+	}
 }
 
-int i8259_setup_irq(int irq, struct irqaction * new)
+/**
+ *	enable_irq - enable interrupt handling on an irq
+ *	@irq: Interrupt to enable
+ *
+ *	Re-enables the processing of interrupts on this IRQ line
+ *	providing no disable_irq calls are now in effect.
+ *
+ *	This function may be called from IRQ context.
+ */
+ 
+void enable_irq(unsigned int irq)
 {
-	int shared = 0;
-	struct irqaction *old, **p;
+	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	p = irq_action + irq;
-	if ((old = *p) != NULL) {
-		/* Can't share interrupts unless both agree to */
-		if (!(old->flags & new->flags & SA_SHIRQ))
-			return -EBUSY;
+	spin_lock_irqsave(&desc->lock, flags);
+	switch (desc->depth) {
+	case 1: {
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+		desc->status = status;
+		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
+			desc->status = status | IRQ_REPLAY;
+			hw_resend_irq(desc->handler,irq);
+		}
+		desc->handler->enable(irq);
+		/* fall-through */
+	}
+	default:
+		desc->depth--;
+		break;
+	case 0:
+		printk("enable_irq(%u) unbalanced from %p\n", irq,
+		       __builtin_return_address(0));
+	}
+	spin_unlock_irqrestore(&desc->lock, flags);
+}
 
-		/* Can't share interrupts unless both are same type */
-		if ((old->flags ^ new->flags) & SA_INTERRUPT)
-			return -EBUSY;
+/*
+ * do_IRQ handles all normal device IRQ's (the special
+ * SMP cross-CPU interrupts have their own specific
+ * handlers).
+ */
+asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs)
+{
+	/* 
+	 * We ack quickly, we don't want the irq controller
+	 * thinking we're snobs just because some other CPU has
+	 * disabled global interrupts (we have already done the
+	 * INT_ACK cycles, it's too late to try to pretend to the
+	 * controller that we aren't taking the interrupt).
+	 *
+	 * 0 return value means that this irq is already being
+	 * handled by some other CPU. (or is disabled)
+	 */
+	int cpu = smp_processor_id();
+	irq_desc_t *desc = irq_desc + irq;
+	struct irqaction * action;
+	unsigned int status;
 
-		/* add new interrupt at end of irq queue */
-		do {
-			p = &old->next;
-			old = *p;
-		} while (old);
-		shared = 1;
+	kstat.irqs[cpu][irq]++;
+	spin_lock(&desc->lock);
+	desc->handler->ack(irq);
+	/*
+	   REPLAY is when Linux resends an IRQ that was dropped earlier
+	   WAITING is used by probe to mark irqs that are being tested
+	   */
+	status = desc->status & ~(IRQ_REPLAY | IRQ_WAITING);
+	status |= IRQ_PENDING; /* we _want_ to handle it */
+
+	/*
+	 * If the IRQ is disabled for whatever reason, we cannot
+	 * use the action we have.
+	 */
+	action = NULL;
+	if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
+		action = desc->action;
+		status &= ~IRQ_PENDING; /* we commit to handling */
+		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
+	desc->status = status;
 
-	if (new->flags & SA_SAMPLE_RANDOM)
-		rand_initialize_irq(irq);
-
-	save_and_cli(flags);
-	*p = new;
+	/*
+	 * If there is no IRQ handler or it was disabled, exit early.
+	   Since we set PENDING, if another processor is handling
+	   a different instance of this same irq, the other processor
+	   will take care of it.
+	 */
+	if (!action)
+		goto out;
 
-	if (!shared) {
-		if (is_i8259_irq(irq))
-		    unmask_irq(irq);
-#if CONFIG_DDB5074 /* This has no business here  */
-		else
-		    nile4_enable_irq(irq_to_nile4(irq));
-#endif
+	/*
+	 * Edge triggered interrupts need to remember
+	 * pending events.
+	 * This applies to any hw interrupts that allow a second
+	 * instance of the same irq to arrive while we are in do_IRQ
+	 * or in the handler. But the code here only handles the _second_
+	 * instance of the irq, not the third or fourth. So it is mostly
+	 * useful for irq hardware that does not mask cleanly in an
+	 * SMP environment.
+	 */
+	for (;;) {
+		spin_unlock(&desc->lock);
+		handle_IRQ_event(irq, regs, action);
+		spin_lock(&desc->lock);
+		
+		if (!(desc->status & IRQ_PENDING))
+			break;
+		desc->status &= ~IRQ_PENDING;
 	}
-	restore_flags(flags);
-	return 0;
+	desc->status &= ~IRQ_INPROGRESS;
+out:
+	/*
+	 * The ->end() handler has to deal with interrupts which got
+	 * disabled while the handler was running.
+	 */
+	desc->handler->end(irq);
+	spin_unlock(&desc->lock);
+
+	if (softirq_active(cpu) & softirq_mask(cpu))
+		do_softirq();
+	return 1;
 }
 
-/*
- * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
- * non i8259 devices.  They will have to be replaced by architecture
- * specific variants.  For now we still use this as broken as it is because
- * it used to work ...
+/**
+ *	request_irq - allocate an interrupt line
+ *	@irq: Interrupt line to allocate
+ *	@handler: Function to be called when the IRQ occurs
+ *	@irqflags: Interrupt type flags
+ *	@devname: An ascii name for the claiming device
+ *	@dev_id: A cookie passed back to the handler function
+ *
+ *	This call allocates interrupt resources and enables the
+ *	interrupt line and IRQ handling. From the point this
+ *	call is made your handler function may be invoked. Since
+ *	your handler function must clear any interrupt the board 
+ *	raises, you must take care both to initialise your hardware
+ *	and to set up the interrupt handler in the right order.
+ *
+ *	Dev_id must be globally unique. Normally the address of the
+ *	device data structure is used as the cookie. Since the handler
+ *	receives this value it makes sense to use it.
+ *
+ *	If your interrupt is shared you must pass a non NULL dev_id
+ *	as this is required when freeing the interrupt.
+ *
+ *	Flags:
+ *
+ *	SA_SHIRQ		Interrupt is shared
+ *
+ *	SA_INTERRUPT		Disable local interrupts while processing
+ *
+ *	SA_SAMPLE_RANDOM	The interrupt can be used for entropy
+ *
  */
+ 
 int request_irq(unsigned int irq, 
 		void (*handler)(int, void *, struct pt_regs *),
-		unsigned long irqflags, const char * devname, void *dev_id)
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
 {
 	int retval;
 	struct irqaction * action;
 
-	if (irq >= 32)
+#if 1
+	/*
+	 * Sanity-check: shared interrupts should REALLY pass in
+	 * a real dev-ID, otherwise we'll have trouble later trying
+	 * to figure out which interrupt is which (messes up the
+	 * interrupt freeing logic etc).
+	 */
+	if (irqflags & SA_SHIRQ) {
+		if (!dev_id)
+			printk("Bad boy: %s (at 0x%x) called us without a dev_id!\n", devname, (&irq)[-1]);
+	}
+#endif
+
+	if (irq >= NR_IRQS)
 		return -EINVAL;
 	if (!handler)
 		return -EINVAL;
 
-	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	action = (struct irqaction *)
+			kmalloc(sizeof(struct irqaction), GFP_KERNEL);
 	if (!action)
 		return -ENOMEM;
 
@@ -301,107 +379,329 @@
 	action->next = NULL;
 	action->dev_id = dev_id;
 
-	retval = i8259_setup_irq(irq, action);
-
+	retval = setup_irq(irq, action);
 	if (retval)
 		kfree(action);
 	return retval;
 }
-		
+
+/**
+ *	free_irq - free an interrupt
+ *	@irq: Interrupt line to free
+ *	@dev_id: Device identity to free
+ *
+ *	Remove an interrupt handler. The handler is removed and if the
+ *	interrupt line is no longer in use by any driver it is disabled.
+ *	On a shared IRQ the caller must ensure the interrupt is disabled
+ *	on the card it drives before calling this function. The function
+ *	does not return until any executing interrupts for this IRQ
+ *	have completed.
+ *
+ *	This function may be called from interrupt context. 
+ *
+ *	Bugs: Attempting to free an irq in a handler for the same irq hangs
+ *	      the machine.
+ */
+ 
 void free_irq(unsigned int irq, void *dev_id)
 {
-	struct irqaction * action, **p;
+	irq_desc_t *desc;
+	struct irqaction **p;
 	unsigned long flags;
 
-	if (irq > 31) {
-		printk("Trying to free IRQ%d\n",irq);
+	if (irq >= NR_IRQS)
 		return;
-	}
-	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
-		if (action->dev_id != dev_id)
-			continue;
 
-		/* Found it - now free it */
-		save_and_cli(flags);
-		*p = action->next;
-		if (!irq[irq_action])
-			mask_irq(irq);
-		restore_flags(flags);
-		kfree(action);
+	desc = irq_desc + irq;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	for (;;) {
+		struct irqaction * action = *p;
+		if (action) {
+			struct irqaction **pp = p;
+			p = &action->next;
+			if (action->dev_id != dev_id)
+				continue;
+
+			/* Found it - now remove it from the list of entries */
+			*pp = action->next;
+			if (!desc->action) {
+				desc->status |= IRQ_DISABLED;
+				desc->handler->shutdown(irq);
+			}
+			spin_unlock_irqrestore(&desc->lock,flags);
+
+#ifdef CONFIG_SMP
+			/* Wait to make sure it's not being used on another CPU */
+			while (desc->status & IRQ_INPROGRESS)
+				barrier();
+#endif
+			kfree(action);
+			return;
+		}
+		printk("Trying to free free IRQ%d\n",irq);
+		spin_unlock_irqrestore(&desc->lock,flags);
 		return;
 	}
-	printk("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.
+ *
+ */
+ 
+unsigned long probe_irq_on(void)
 {
-	unsigned int i, irqs = 0;
+	unsigned int i;
+	irq_desc_t *desc;
+	unsigned long val;
 	unsigned long delay;
 
-	/* first, enable any unassigned (E)ISA irqs */
-	for (i = 15; i > 0; i--) {
-		if (!irq_action[i]) {
-			i8259_enable_irq(i);
-			irqs |= (1 << i);
+	down(&probe_sem);
+	/* 
+	 * something may have generated an irq long ago and we want to
+	 * flush such a longstanding irq before considering it as spurious. 
+	 */
+	for (i = NR_IRQS-1; i > 0; i--)  {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!irq_desc[i].action) 
+			irq_desc[i].handler->startup(i);
+		spin_unlock_irq(&desc->lock);
+	}
+
+	/* Wait for longstanding interrupts to trigger. */
+	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+		/* about 20ms delay */ synchronize_irq();
+
+	/*
+	 * 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 = NR_IRQS-1; i > 0; i--) {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!desc->action) {
+			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+			if (desc->handler->startup(i))
+				desc->status |= IRQ_PENDING;
 		}
+		spin_unlock_irq(&desc->lock);
 	}
 
-	/* wait for spurious interrupts to mask themselves out again */
-	for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
-		/* about 100ms delay */;
+	/*
+	 * 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 < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			/* It triggered already - consider it spurious. */
+			if (!(status & IRQ_WAITING)) {
+				desc->status = status & ~IRQ_AUTODETECT;
+				desc->handler->shutdown(i);
+			} else
+				if (i < 32)
+					val |= 1 << i;
+		}
+		spin_unlock_irq(&desc->lock);
+	}
 
-	/* now filter out any obviously spurious interrupts */
-	return irqs & ~cached_irq_mask;
+	return val;
 }
 
-int probe_irq_off (unsigned long irqs)
+/*
+ * Return a mask of triggered interrupts (this
+ * can handle only legacy ISA interrupts).
+ */
+ 
+/**
+ *	probe_irq_mask - scan a bitmap of interrupt lines
+ *	@val:	mask of interrupts to consider
+ *
+ *	Scan the ISA bus interrupt lines and return a bitmap of
+ *	active interrupts. The interrupt probe logic state is then
+ *	returned to its previous value.
+ *
+ *	Note: we need to scan all the irq's even though we will
+ *	only return ISA irq numbers - just so that we reset them
+ *	all to a known state.
+ */
+unsigned int probe_irq_mask(unsigned long val)
 {
-	unsigned int i;
+	int i;
+	unsigned int mask;
 
-#ifdef DEBUG
-	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
-#endif
-	irqs &= cached_irq_mask;
-	if (!irqs)
-		return 0;
-	i = ffz(~irqs);
-	if (irqs != (irqs & (1 << i)))
-		i = -i;
-	return i;
+	mask = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (i < 16 && !(status & IRQ_WAITING))
+				mask |= 1 << i;
+
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+	up(&probe_sem);
+
+	return mask & val;
 }
 
-int (*irq_cannonicalize)(int irq);
+/*
+ * Return the one interrupt that triggered (this can
+ * handle any interrupt source).
+ */
 
-static int i8259_irq_cannonicalize(int irq)
+/**
+ *	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 ((irq == 2) ? 9 : irq);
+	int i, irq_found, nr_irqs;
+
+	nr_irqs = 0;
+	irq_found = 0;
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
+
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
+
+		if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING)) {
+				if (!nr_irqs)
+					irq_found = i;
+				nr_irqs++;
+			}
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
+		}
+		spin_unlock_irq(&desc->lock);
+	}
+	up(&probe_sem);
+
+	if (nr_irqs > 1)
+		irq_found = -irq_found;
+	return irq_found;
 }
 
-void __init i8259_init(void)
+/* this was setup_x86_irq but it seems pretty generic */
+int setup_irq(unsigned int irq, struct irqaction * new)
 {
-	/* Init master interrupt controller */
-	outb(0x11, 0x20); /* Start init sequence */
-	outb(0x00, 0x21); /* Vector base */
-	outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
-	outb(0x01, 0x21); /* Select 8086 mode */
-	outb(0xff, 0x21); /* Mask all */
-        
-	/* Init slave interrupt controller */
-	outb(0x11, 0xa0); /* Start init sequence */
-	outb(0x08, 0xa1); /* Vector base */
-	outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
-	outb(0x01, 0xa1); /* Select 8086 mode */
-	outb(0xff, 0xa1); /* Mask all */
+	int shared = 0;
+	unsigned long flags;
+	struct irqaction *old, **p;
+	irq_desc_t *desc = irq_desc + irq;
+
+	/*
+	 * Some drivers like serial.c use request_irq() heavily,
+	 * so we have to be careful not to interfere with a
+	 * running system.
+	 */
+	if (new->flags & SA_SAMPLE_RANDOM) {
+		/*
+		 * This function might sleep, we want to call it first,
+		 * outside of the atomic block.
+		 * Yes, this might clear the entropy pool if the wrong
+		 * driver is attempted to be loaded, without actually
+		 * installing a new handler, but is this really a problem,
+		 * only the sysadmin is able to do this.
+		 */
+		rand_initialize_irq(irq);
+	}
 
-	outb(cached_A1, 0xa1);
-	outb(cached_21, 0x21);
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ)) {
+			spin_unlock_irqrestore(&desc->lock,flags);
+			return -EBUSY;
+		}
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	*p = new;
+
+	if (!shared) {
+		desc->depth = 0;
+		desc->status &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING);
+		desc->handler->startup(irq);
+	}
+	spin_unlock_irqrestore(&desc->lock,flags);
+
+	/* register_irq_proc(irq); */
+	return 0;
 }
 
-void __init init_IRQ(void)
+void __init init_generic_irq(void)
 {
-	irq_cannonicalize = i8259_irq_cannonicalize;
-	/* i8259_init(); */
-	irq_setup();
-}
+	int i;
 
-EXPORT_SYMBOL(irq_cannonicalize);
+	for (i = 0; i < NR_IRQS; i++) {
+		irq_desc[i].status  = IRQ_DISABLED;
+		irq_desc[i].action  = NULL;
+		irq_desc[i].depth   = 1;
+		irq_desc[i].handler = &no_irq_type;
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/mips_ksyms.c linux/arch/mips/kernel/mips_ksyms.c
--- v2.4.5/linux/arch/mips/kernel/mips_ksyms.c	Fri Mar  2 11:15:47 2001
+++ linux/arch/mips/kernel/mips_ksyms.c	Mon Jul  2 13:56:40 2001
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 1997, 1998, 2000 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 2000, 2001 by Ralf Baechle
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -94,9 +94,10 @@
 /*
  * Semaphore stuff
  */
-EXPORT_SYMBOL(__down_read);
-EXPORT_SYMBOL(__down_write);
-EXPORT_SYMBOL(__rwsem_wake);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
+EXPORT_SYMBOL(__up);
 
 /*
  * Base address of ports for Intel style I/O.
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/old-irq.c linux/arch/mips/kernel/old-irq.c
--- v2.4.5/linux/arch/mips/kernel/old-irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/old-irq.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,405 @@
+/*
+ * 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.
+ *
+ * Code to handle x86 style IRQs plus some generic interrupt stuff.
+ *
+ * Copyright (C) 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2001 Ralf Baechle
+ *
+ * Old rotten IRQ code.  To be killed as soon as everybody had converted or
+ * in 2.5.0, whatever comes first.
+ */
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/kernel_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/timex.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+#include <asm/bitops.h>
+#include <asm/bootinfo.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/nile4.h>
+
+/*
+ * The board specific setup routine sets irq_setup to point to a board
+ * specific setup routine.
+ */
+void (*irq_setup)(void);
+
+/*
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers, it's an
+ * int so we can deal with the third PIC in some systems like the RM300.
+ * (XXX This is broken for big endian.)
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) (((unsigned char *)&(y))[x])
+#define __word(x,y) (((unsigned short *)&(y))[x])
+#define __long(x,y) (((unsigned int *)&(y))[x])
+
+#define cached_21       (__byte(0,cached_irq_mask))
+#define cached_A1       (__byte(1,cached_irq_mask))
+
+unsigned long spurious_count = 0;
+
+/*
+ * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
+ * PCI devices.  Other onboard hardware needs specific routines.
+ */
+static inline void mask_irq(unsigned int irq)
+{
+	cached_irq_mask |= 1 << irq;
+	if (irq & 8) {
+		outb(cached_A1, 0xa1);
+	} else {
+		outb(cached_21, 0x21);
+	}
+}
+
+static inline void unmask_irq(unsigned int irq)
+{
+	cached_irq_mask &= ~(1 << irq);
+	if (irq & 8) {
+		outb(cached_A1, 0xa1);
+	} else {
+		outb(cached_21, 0x21);
+	}
+}
+
+void i8259_disable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+
+	save_and_cli(flags);
+	mask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+void i8259_enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	save_and_cli(flags);
+	unmask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+static struct irqaction *irq_action[NR_IRQS] = {
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	struct irqaction * action;
+
+	for (i = 0 ; i < 32 ; i++) {
+		action = irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %8d %c %s",
+			i, kstat.irqs[0][i],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action=action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, "\n");
+	}
+	return len;
+}
+
+static inline void i8259_mask_and_ack_irq(int irq)
+{
+	cached_irq_mask |= 1 << irq;
+
+	if (irq & 8) {
+		inb(0xa1);
+		outb(cached_A1, 0xa1);
+		outb(0x62, 0x20);		/* Specific EOI to cascade */
+                outb(0x20, 0xa0);
+        } else {
+		inb(0x21);
+		outb(cached_21, 0x21);
+		outb(0x20, 0x20);
+        }
+}
+
+asmlinkage void i8259_do_irq(int irq, struct pt_regs *regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+	cpu = smp_processor_id();
+	irq_enter(cpu, irq);
+
+	if (irq >= 16)
+		goto out;
+
+	i8259_mask_and_ack_irq(irq);
+
+	kstat.irqs[cpu][irq]++;
+
+	action = *(irq + irq_action);
+	if (!action)
+		goto out;
+
+	if (!(action->flags & SA_INTERRUPT))
+		__sti();
+	action = *(irq + irq_action);
+	do_random = 0;
+       	do {
+		do_random |= action->flags;
+		action->handler(irq, action->dev_id, regs);
+		action = action->next;
+       	} while (action);
+	if (do_random & SA_SAMPLE_RANDOM)
+		add_interrupt_randomness(irq);
+	__cli();
+	unmask_irq (irq);
+
+out:
+	irq_exit(cpu, irq);
+}
+
+/*
+ * do_IRQ handles IRQ's that have been installed without the
+ * SA_INTERRUPT flag: it uses the full signal-handling return
+ * and runs with other interrupts enabled. All relatively slow
+ * IRQ's should use this format: notably the keyboard/timer
+ * routines.
+ */
+asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+	cpu = smp_processor_id();
+	irq_enter(cpu, irq);
+	kstat.irqs[cpu][irq]++;
+
+	action = *(irq + irq_action);
+	if (action) {
+		if (!(action->flags & SA_INTERRUPT))
+			__sti();
+		action = *(irq + irq_action);
+		do_random = 0;
+        	do {
+			do_random |= action->flags;
+			action->handler(irq, action->dev_id, regs);
+			action = action->next;
+        	} while (action);
+		if (do_random & SA_SAMPLE_RANDOM)
+			add_interrupt_randomness(irq);
+		__cli();
+	}
+	irq_exit(cpu, irq);
+
+	if (softirq_active(cpu)&softirq_mask(cpu))
+		do_softirq();
+
+	/* unmasking and bottom half handling is done magically for us. */
+}
+
+int i8259_setup_irq(int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	p = irq_action + irq;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	save_and_cli(flags);
+	*p = new;
+
+	if (!shared) {
+		if (is_i8259_irq(irq))
+		    unmask_irq(irq);
+#if (defined(CONFIG_DDB5074) || defined(CONFIG_DDB5476))
+		else
+		    nile4_enable_irq(irq_to_nile4(irq));
+#endif
+	}
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * Request_interrupt and free_interrupt ``sort of'' handle interrupts of
+ * non i8259 devices.  They will have to be replaced by architecture
+ * specific variants.  For now we still use this as broken as it is because
+ * it used to work ...
+ */
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, const char * devname, void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+	if (irq >= 32)
+		return -EINVAL;
+	if (!handler)
+		return -EINVAL;
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = i8259_setup_irq(irq, action);
+
+	if (retval)
+		kfree(action);
+	return retval;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction * action, **p;
+	unsigned long flags;
+
+	if (irq > 31) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		save_and_cli(flags);
+		*p = action->next;
+		if (!irq[irq_action])
+			mask_irq(irq);
+		restore_flags(flags);
+		kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n",irq);
+}
+
+unsigned long probe_irq_on (void)
+{
+	unsigned int i, irqs = 0;
+	unsigned long delay;
+
+	/* first, enable any unassigned (E)ISA irqs */
+	for (i = 15; i > 0; i--) {
+		if (!irq_action[i]) {
+			i8259_enable_irq(i);
+			irqs |= (1 << i);
+		}
+	}
+
+	/* wait for spurious interrupts to mask themselves out again */
+	for (delay = jiffies + HZ/10; time_before(jiffies, delay); )
+		/* about 100ms delay */;
+
+	/* now filter out any obviously spurious interrupts */
+	return irqs & ~cached_irq_mask;
+}
+
+int probe_irq_off (unsigned long irqs)
+{
+	unsigned int i;
+
+#ifdef DEBUG
+	printk("probe_irq_off: irqs=0x%04x irqmask=0x%04x\n", irqs, irqmask);
+#endif
+	irqs &= cached_irq_mask;
+	if (!irqs)
+		return 0;
+	i = ffz(~irqs);
+	if (irqs != (irqs & (1 << i)))
+		i = -i;
+	return i;
+}
+
+void __init i8259_init(void)
+{
+	/* Init master interrupt controller */
+	outb(0x11, 0x20); /* Start init sequence */
+	outb(0x00, 0x21); /* Vector base */
+	outb(0x04, 0x21); /* edge tiggered, Cascade (slave) on IRQ2 */
+	outb(0x01, 0x21); /* Select 8086 mode */
+	outb(0xff, 0x21); /* Mask all */
+        
+	/* Init slave interrupt controller */
+	outb(0x11, 0xa0); /* Start init sequence */
+	outb(0x08, 0xa1); /* Vector base */
+	outb(0x02, 0xa1); /* edge triggered, Cascade (slave) on IRQ2 */
+	outb(0x01, 0xa1); /* Select 8086 mode */
+	outb(0xff, 0xa1); /* Mask all */
+
+	outb(cached_A1, 0xa1);
+	outb(cached_21, 0x21);
+}
+
+void __init init_IRQ(void)
+{
+	/* i8259_init(); */
+	irq_setup();
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/old-time.c linux/arch/mips/kernel/old-time.c
--- v2.4.5/linux/arch/mips/kernel/old-time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/old-time.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,519 @@
+/*
+ * Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ * Copyright (C) 1996 - 2000  Ralf Baechle
+ *
+ * This file contains the time handling details for PC-style clocks as
+ * found in some MIPS systems.
+ */
+/**************************************************************************
+ *  9 Nov, 2000.
+ *  Changed init_cycle_counter() routine, use the mips_cpu structure.
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/bootinfo.h>
+#include <asm/cpu.h>
+#include <asm/mipsregs.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/ddb5074.h>
+
+#include <linux/mc146818rtc.h>
+#include <linux/timex.h>
+
+extern volatile unsigned long wall_jiffies;
+unsigned long r4k_interval;
+extern rwlock_t xtime_lock;
+
+/*
+ * Change this if you have some constant time drift
+ */
+/* This is the value for the PC-style PICs. */
+/* #define USECS_PER_JIFFY (1000020/HZ) */
+
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
+
+/* Cycle counter value at the previous timer interrupt.. */
+
+static unsigned int timerhi, timerlo;
+
+/*
+ * On MIPS only R4000 and better have a cycle counter.
+ *
+ * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ */
+static unsigned long do_fast_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res, tmp;
+
+	/* Last jiffy when do_fast_gettimeoffset() was called. */
+	static unsigned long last_jiffies;
+	unsigned long quotient;
+
+	/*
+	 * Cached "1/(clocks per usec)*2^32" value.
+	 * It has to be recalculated once each jiffy.
+	 */
+	static unsigned long cached_quotient;
+
+	tmp = jiffies;
+
+	quotient = cached_quotient;
+
+	if (tmp && last_jiffies != tmp) {
+		last_jiffies = tmp;
+		__asm__(".set\tnoreorder\n\t"
+			".set\tnoat\n\t"
+			".set\tmips3\n\t"
+			"lwu\t%0,%2\n\t"
+			"dsll32\t$1,%1,0\n\t"
+			"or\t$1,$1,%0\n\t"
+			"ddivu\t$0,$1,%3\n\t"
+			"mflo\t$1\n\t"
+			"dsll32\t%0,%4,0\n\t"
+			"nop\n\t"
+			"ddivu\t$0,%0,$1\n\t"
+			"mflo\t%0\n\t"
+			".set\tmips0\n\t"
+			".set\tat\n\t"
+			".set\treorder"
+			:"=&r" (quotient)
+			:"r" (timerhi),
+			 "m" (timerlo),
+			 "r" (tmp),
+			 "r" (USECS_PER_JIFFY)
+			:"$1");
+		cached_quotient = quotient;
+	}
+
+	/* Get last timer tick in absolute kernel time */
+	count = read_32bit_cp0_register(CP0_COUNT);
+
+	/* .. relative to previous jiffy (32 bits is enough) */
+	count -= timerlo;
+
+	__asm__("multu\t%1,%2\n\t"
+		"mfhi\t%0"
+		:"=r" (res)
+		:"r" (count),
+		 "r" (quotient));
+
+	/*
+ 	 * Due to possible jiffies inconsistencies, we need to check 
+	 * the result so that we'll get a timer that is monotonic.
+	 */
+	if (res >= USECS_PER_JIFFY)
+		res = USECS_PER_JIFFY-1;
+
+	return res;
+}
+
+/* This function must be called with interrupts disabled 
+ * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
+ * 
+ * However, the pc-audio speaker driver changes the divisor so that
+ * it gets interrupted rather more often - it loads 64 into the
+ * counter rather than 11932! This has an adverse impact on
+ * do_gettimeoffset() -- it stops working! What is also not
+ * good is that the interval that our timer function gets called
+ * is no longer 10.0002 ms, but 9.9767 ms. To get around this
+ * would require using a different timing source. Maybe someone
+ * could use the RTC - I know that this can interrupt at frequencies
+ * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
+ * it so that at startup, the timer code in sched.c would select
+ * using either the RTC or the 8253 timer. The decision would be
+ * based on whether there was any other device around that needed
+ * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
+ * and then do some jiggery to have a version of do_timer that 
+ * advanced the clock by 1/1024 s. Every time that reached over 1/100
+ * of a second, then do all the old code. If the time was kept correct
+ * then do_gettimeoffset could just return 0 - there is no low order
+ * divider that can be accessed.
+ *
+ * Ideally, you would be able to use the RTC for the speaker driver,
+ * but it appears that the speaker driver really needs interrupt more
+ * often than every 120 us or so.
+ *
+ * Anyway, this needs more thought....		pjsg (1993-08-28)
+ * 
+ * If you are really that interested, you should be reading
+ * comp.protocols.time.ntp!
+ */
+
+#define TICK_SIZE tick
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+	int count;
+
+	static int count_p = LATCH;    /* for the first call after boot */
+	static unsigned long jiffies_p;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
+
+	/* timer count may underflow right here */
+	outb_p(0x00, 0x43);	/* latch the count ASAP */
+
+	count = inb_p(0x40);	/* read the latched count */
+
+	/*
+	 * We do this guaranteed double memory access instead of a _p 
+	 * postfix in the previous port access. Wheee, hackady hack
+	 */
+	jiffies_t = jiffies;
+
+	count |= inb_p(0x40) << 8;
+
+	/*
+	 * avoiding timer inconsistencies (they are rare, but they happen)...
+	 * there are two kinds of problems that must be avoided here:
+	 *  1. the timer counter underflows
+	 *  2. hardware problem with the timer, not giving us continuous time,
+	 *     the counter does small "jumps" upwards on some Pentium systems,
+	 *     (see c't 95/10 page 335 for Neptun bug.)
+	 */
+
+	if( jiffies_t == jiffies_p ) {
+		if( count > count_p ) {
+			/* the nutcase */
+
+			outb_p(0x0A, 0x20);
+
+			/* assumption about timer being IRQ1 */
+			if (inb(0x20) & 0x01) {
+				/*
+				 * We cannot detect lost timer interrupts ... 
+				 * well, that's why we call them lost, don't we? :)
+				 * [hmm, on the Pentium and Alpha we can ... sort of]
+				 */
+				count -= LATCH;
+			} else {
+				printk("do_slow_gettimeoffset(): hardware timer problem?\n");
+			}
+		}
+	} else
+		jiffies_p = jiffies_t;
+
+	count_p = count;
+
+	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = (count + LATCH/2) / LATCH;
+
+	return count;
+}
+
+static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+
+	read_lock_irqsave (&xtime_lock, flags);
+	*tv = xtime;
+	tv->tv_usec += do_gettimeoffset();
+
+	/*
+	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+	 * is nonzero if the timer bottom half hasnt executed yet.
+	 */
+	if (jiffies - wall_jiffies)
+		tv->tv_usec += USECS_PER_JIFFY;
+
+	read_unlock_irqrestore (&xtime_lock, flags);
+
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	write_lock_irq (&xtime_lock);
+
+	/* This is revolting. We need to set the xtime.tv_usec
+	 * correctly. However, the value in this location is
+	 * is value at the last tick.
+	 * Discover what correction gettimeofday
+	 * would have done, and then undo it!
+	 */
+	tv->tv_usec -= do_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+
+	write_unlock_irq (&xtime_lock);
+}
+
+/*
+ * In order to set the CMOS clock precisely, set_rtc_mmss has to be
+ * called 500 ms after the second nowtime has started, because when
+ * nowtime is written into the registers of the CMOS clock, it will
+ * jump to the next second precisely 500 ms later. Check the Motorola
+ * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+ 		retval = -1;
+	}
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+static void inline
+timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+#ifdef CONFIG_DDB5074
+	static unsigned cnt, period, dist;
+
+	if (cnt == 0 || cnt == dist)
+	    ddb5074_led_d2(1);
+	else if (cnt == 7 || cnt == dist+7)
+	    ddb5074_led_d2(0);
+	
+	if (++cnt > period) {
+	    cnt = 0;
+	    /* The hyperbolic function below modifies the heartbeat period
+	     * length in dependency of the current (5min) load. It goes
+	     * through the points f(0)=126, f(1)=86, f(5)=51,
+	     * f(inf)->30. */
+	     period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+	     dist = period / 4;
+	}
+#endif
+	if(!user_mode(regs)) {
+		if (prof_buffer && current->pid) {
+			extern int _stext;
+			unsigned long pc = regs->cp0_epc;
+
+			pc -= (unsigned long) &_stext;
+			pc >>= prof_shift;
+			/*
+			 * Dont ignore out-of-bounds pc values silently,
+			 * put them into the last histogram slot, so if
+			 * present, they will show up as a sharp peak.
+			 */
+			if (pc > prof_len-1)
+				pc = prof_len-1;
+			atomic_inc((atomic_t *)&prof_buffer[pc]);
+		}
+	}
+	do_timer(regs);
+
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	read_lock (&xtime_lock); 
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
+	  if (set_rtc_mmss(xtime.tv_sec) == 0)
+	    last_rtc_update = xtime.tv_sec;
+	  else
+	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+	}
+	/* As we return to user mode fire off the other CPU schedulers.. this is 
+	   basically because we don't yet share IRQ's around. This message is
+	   rigged to be safe on the 386 - basically it's a hack, so don't look
+	   closely for now.. */
+	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
+	read_unlock (&xtime_lock); 
+}
+
+static inline void 
+r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	unsigned int count;
+
+	/*
+	 * The cycle counter is only 32 bit which is good for about
+	 * a minute at current count rates of upto 150MHz or so.
+	 */
+	count = read_32bit_cp0_register(CP0_COUNT);
+	timerhi += (count < timerlo);	/* Wrap around */
+	timerlo = count;
+
+#ifdef CONFIG_SGI_IP22
+	/* Since we don't get anything but r4k timer interrupts, we need to
+	 * set this up so that we'll get one next time. Fortunately since we
+	 * have timerhi/timerlo, we don't care so much if we miss one. So
+	 * we need only ask for the next in r4k_interval counts. On other
+	 * archs we have a real timer, so we don't want this.
+	 */
+	write_32bit_cp0_register (CP0_COMPARE, 
+				  (unsigned long) (count + r4k_interval));
+        kstat.irqs[0][irq]++;
+#endif
+
+	timer_interrupt(irq, dev_id, regs);
+
+	if (!jiffies)
+	{
+		/*
+		 * If jiffies has overflowed in this timer_interrupt we must
+		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
+		 * quotient calc still valid. -arca
+		 */
+		timerhi = timerlo = 0;
+	}
+}
+
+void indy_r4k_timer_interrupt (struct pt_regs *regs)
+{
+	static const int INDY_R4K_TIMER_IRQ = 7;
+	r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs);
+}
+
+struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0,
+                                  "timer", NULL, NULL};
+
+
+void (*board_time_init)(struct irqaction *irq);
+
+void __init time_init(void)
+{
+	unsigned int epoch = 0, year, mon, day, hour, min, sec;
+	int i;
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+	  {
+	    BCD_TO_BIN(sec);
+	    BCD_TO_BIN(min);
+	    BCD_TO_BIN(hour);
+	    BCD_TO_BIN(day);
+	    BCD_TO_BIN(mon);
+	    BCD_TO_BIN(year);
+	  }
+
+	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c so
+	   no stupid things will happen to timekeeping.  Who knows, maybe Ultrix
+  	   also uses 1952 as epoch ...  */
+	if (year > 10 && year < 44) {
+		epoch = 1980;
+	} else if (year < 96) {
+		epoch = 1952;
+	}
+	year += epoch;
+
+	write_lock_irq (&xtime_lock);
+	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	xtime.tv_usec = 0;
+	write_unlock_irq (&xtime_lock);
+
+	if (mips_cpu.options & MIPS_CPU_COUNTER) {
+		write_32bit_cp0_register(CP0_COUNT, 0);
+		do_gettimeoffset = do_fast_gettimeoffset;
+		irq0.handler = r4k_timer_interrupt;
+	}
+
+	board_time_init(&irq0);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/pci-dma.c linux/arch/mips/kernel/pci-dma.c
--- v2.4.5/linux/arch/mips/kernel/pci-dma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/pci-dma.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,41 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000  Ralf Baechle <ralf@gnu.org>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t * dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	if (hwdev == NULL || hwdev->dma_mask != 0xffffffff)
+		gfp |= GFP_DMA;
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		dma_cache_wback_inv((unsigned long) ret, size);
+		*dma_handle = virt_to_bus(ret);
+		ret = KSEG1ADDR(ret);
+	}
+
+	return ret;
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long) KSEG0ADDR(vaddr), get_order(size));
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/proc.c linux/arch/mips/kernel/proc.c
--- v2.4.5/linux/arch/mips/kernel/proc.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/proc.c	Mon Jul  2 13:56:40 2001
@@ -7,12 +7,16 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <asm/bootinfo.h>
+#include <asm/cpu.h>
 #include <asm/mipsregs.h>
 #include <asm/processor.h>
 #include <asm/watch.h>
 
 unsigned long unaligned_instructions;
 unsigned int vced_count, vcei_count;
+#if !defined(CONFIG_CPU_HAS_LLSC)
+unsigned long ll_ops, sc_ops;
+#endif
 
 /*
  * BUFFER is PAGE_SIZE bytes long.
@@ -35,32 +39,37 @@
 	const char *mach_cobalt_names[] = GROUP_COBALT_NAMES;
 	const char *mach_nec_ddb_names[] = GROUP_NEC_DDB_NAMES;
 	const char *mach_baget_names[] = GROUP_BAGET_NAMES;
+	const char *mach_cosine_names[] = GROUP_COSINE_NAMES;
+	const char *mach_galileo_names[] = GROUP_GALILEO_NAMES;
+	const char *mach_momenco_names[] = GROUP_MOMENCO_NAMES;
+ 	const char *mach_ite_names[] = GROUP_ITE_NAMES;
+	const char *mach_philips_names[] = GROUP_PHILIPS_NAMES;
+ 	const char *mach_globespan_names[] = GROUP_GLOBESPAN_NAMES;
+	const char *mach_sibyte_names[] = GROUP_SIBYTE_NAMES;
+	const char *mach_toshiba_names[] = GROUP_TOSHIBA_NAMES;
+	const char *mach_alchemy_names[] = GROUP_ALCHEMY_NAMES;
 	const char **mach_group_to_name[] = { mach_unknown_names,
-	                                      mach_jazz_names,
-	                                      mach_dec_names,
-	                                      mach_arc_names,
-	                                      mach_sni_rm_names,
-	                                      mach_acn_names,
-	                                      mach_sgi_names,
-					      mach_cobalt_names,
-					      mach_nec_ddb_names,
-					      mach_baget_names };
+		mach_jazz_names, mach_dec_names, mach_arc_names,
+		mach_sni_rm_names, mach_acn_names, mach_sgi_names,
+		mach_cobalt_names, mach_nec_ddb_names, mach_baget_names,
+		mach_cosine_names, mach_galileo_names, mach_momenco_names, 
+		mach_ite_names, mach_philips_names, mach_globespan_names,
+		mach_sibyte_names, mach_toshiba_names, mach_alchemy_names};
 	unsigned int version = read_32bit_cp0_register(CP0_PRID);
 	int len;
 
 	len = sprintf(buffer, "cpu\t\t\t: MIPS\n");
 	len += sprintf(buffer + len, "cpu model\t\t: %s V%d.%d\n",
-	               cpu_name[mips_cputype <= CPU_LAST ?
-	                        mips_cputype :
-	                        CPU_UNKNOWN],
-	               (version >> 4) & 0x0f,
-	               version & 0x0f);
+	               cpu_name[mips_cpu.cputype <= CPU_LAST ?
+	                        mips_cpu.cputype : CPU_UNKNOWN],
+	               (version >> 4) & 0x0f, version & 0x0f);
 	len += sprintf(buffer + len, "system type\t\t: %s %s\n",
 		       mach_group_names[mips_machgroup],
 		       mach_group_to_name[mips_machgroup][mips_machtype]);
 	len += sprintf(buffer + len, "BogoMIPS\t\t: %lu.%02lu\n",
-		       (loops_per_sec + 2500) / 500000,
-	               ((loops_per_sec + 2500) / 5000) % 100);
+		       loops_per_jiffy/(500000/HZ),
+		       (loops_per_jiffy/(5000/HZ)) % 100);
+
 #if defined (__MIPSEB__)
 	len += sprintf(buffer + len, "byteorder\t\t: big endian\n");
 #endif
@@ -72,17 +81,23 @@
 	len += sprintf(buffer + len, "wait instruction\t: %s\n",
 	               cpu_wait ? "yes" : "no");
 	len += sprintf(buffer + len, "microsecond timers\t: %s\n",
-	               cyclecounter_available ? "yes" : "no");
+	               (mips_cpu.options & MIPS_CPU_COUNTER) ? "yes" : "no");
 	len += sprintf(buffer + len, "extra interrupt vector\t: %s\n",
 	               dedicated_iv_available ? "yes" : "no");
 	len += sprintf(buffer + len, "hardware watchpoint\t: %s\n",
 	               watch_available ? "yes" : "no");
 
 	sprintf(fmt, "VCE%%c exceptions\t\t: %s\n",
-	        vce_available ? "%d" : "not available");
+	        (mips_cpu.options & MIPS_CPU_VCE) ? "%d" : "not available");
 	len += sprintf(buffer + len, fmt, 'D', vced_count);
 	len += sprintf(buffer + len, fmt, 'I', vcei_count);
 
+#if !defined(CONFIG_CPU_HAS_LLSC)
+	len += sprintf(buffer + len, "ll emulations\t\t: %lu\n",
+		       ll_ops);
+	len += sprintf(buffer + len, "sc emulations\t\t: %lu\n",
+		       sc_ops);
+#endif
 	return len;
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v2.4.5/linux/arch/mips/kernel/process.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/process.c	Mon Jul  2 13:56:40 2001
@@ -162,21 +162,21 @@
 	long retval;
 
 	__asm__ __volatile__(
-		".set\tnoreorder\n\t"
-		"move\t$6,$sp\n\t"
-		"move\t$4,%5\n\t"
-		"li\t$2,%1\n\t"
-		"syscall\n\t"
-		"beq\t$6,$sp,1f\n\t"
-		"subu\t$sp,32\n\t"	/* delay slot */
-		"jalr\t%4\n\t"
-		"move\t$4,%3\n\t"	/* delay slot */
-		"move\t$4,$2\n\t"
-		"li\t$2,%2\n\t"
-		"syscall\n"
-		"1:\taddiu\t$sp,32\n\t"
-		"move\t%0,$2\n\t"
-		".set\treorder"
+		".set noreorder               \n"
+		"    move    $6,$sp           \n"
+		"    move    $4,%5            \n"
+		"    li      $2,%1            \n"
+		"    syscall                  \n"
+		"    beq     $6,$sp,1f        \n"
+		"    subu    $sp,32           \n"	/* delay slot */
+		"    jalr    %4               \n"
+		"    move    $4,%3            \n"	/* delay slot */
+		"    move    $4,$2            \n"
+		"    li      $2,%2            \n"
+		"    syscall                  \n"
+		"1:  addiu   $sp,32           \n"
+		"    move    %0,$2            \n"
+		".set reorder"
 		:"=r" (retval)
 		:"i" (__NR_clone), "i" (__NR_exit),
 		 "r" (arg), "r" (fn),
@@ -199,27 +199,47 @@
 #define first_sched	((unsigned long) scheduling_functions_start_here)
 #define last_sched	((unsigned long) scheduling_functions_end_here)
 
+/* get_wchan - a maintenance nightmare ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
-	unsigned long schedule_frame;
-	unsigned long pc;
+	unsigned long frame, pc;
 
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 
 	pc = thread_saved_pc(&p->thread);
-	if (pc == (unsigned long) interruptible_sleep_on
-	    || pc == (unsigned long) sleep_on) {
-		schedule_frame = ((unsigned long *)p->thread.reg30)[9];
-		return ((unsigned long *)schedule_frame)[15];
-	}
-	if (pc == (unsigned long) interruptible_sleep_on_timeout
-	    || pc == (unsigned long) sleep_on_timeout) {
-		schedule_frame = ((unsigned long *)p->thread.reg30)[9];
-		return ((unsigned long *)schedule_frame)[16];
+	if (pc < first_sched || pc >= last_sched) {
+		return pc;
 	}
+
+	if (pc >= (unsigned long) sleep_on_timeout)
+		goto schedule_timeout_caller;
+	if (pc >= (unsigned long) sleep_on)
+		goto schedule_caller;
+	if (pc >= (unsigned long) interruptible_sleep_on_timeout)
+		goto schedule_timeout_caller;
+	if (pc >= (unsigned long)interruptible_sleep_on)
+		goto schedule_caller;
+	goto schedule_timeout_caller;
+
+schedule_caller:
+	frame = ((unsigned long *)p->thread.reg30)[9];
+	pc    = ((unsigned long *)frame)[11];
+	return pc;
+
+schedule_timeout_caller:
+	/* Must be schedule_timeout ...  */
+	pc    = ((unsigned long *)p->thread.reg30)[10];
+	frame = ((unsigned long *)p->thread.reg30)[9];
+
+	/* The schedule_timeout frame ...  */
+	pc    = ((unsigned long *)frame)[14];
+	frame = ((unsigned long *)frame)[13];
+
 	if (pc >= first_sched && pc < last_sched) {
-		printk(KERN_DEBUG "Bug in %s\n", __FUNCTION__);
+		/* schedule_timeout called by interruptible_sleep_on_timeout */
+		pc    = ((unsigned long *)frame)[11];
+		frame = ((unsigned long *)frame)[10];
 	}
 
 	return pc;
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/ptrace.c linux/arch/mips/kernel/ptrace.c
--- v2.4.5/linux/arch/mips/kernel/ptrace.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/ptrace.c	Mon Jul  2 13:56:40 2001
@@ -207,7 +207,7 @@
 
 	case PTRACE_POKEUSR: {
 		struct pt_regs *regs;
-		int res = 0;
+		res = 0;
 		regs = (struct pt_regs *) ((unsigned long) child +
 		       KERNEL_STACK_SIZE - 32 - sizeof(struct pt_regs));
 
@@ -289,7 +289,7 @@
 	 */
 	case PTRACE_KILL:
 		res = 0;
-		if (child->state != TASK_ZOMBIE)	/* already dead */
+		if (child->state == TASK_ZOMBIE)	/* already dead */
 			break;
 		child->exit_code = SIGKILL;
 		wake_up_process(child);
@@ -299,7 +299,7 @@
 		res = -EIO;
 		if ((unsigned long) data > _NSIG)
 			break;
-		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
+		child->ptrace = 0;
 		child->exit_code = data;
 		write_lock_irq(&tasklist_lock);
 		REMOVE_LINKS(child);
@@ -310,6 +310,14 @@
 		res = 0;
 		break;
 
+	case PTRACE_SETOPTIONS:
+		if (data & PTRACE_O_TRACESYSGOOD)
+			child->ptrace |= PT_TRACESYSGOOD;
+		else
+			child->ptrace &= ~PT_TRACESYSGOOD;
+		res = 0;
+		break;
+
 	default:
 		res = -EIO;
 		goto out;
@@ -326,7 +334,10 @@
 	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
 			!= (PT_PTRACED|PT_TRACESYS))
 		return;
-	current->exit_code = SIGTRAP;
+	/* The 0x80 provides a way for the tracing parent to distinguish
+	   between a syscall stop and SIGTRAP delivery */
+	current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+	                                ? 0x80 : 0);
 	current->state = TASK_STOPPED;
 	notify_parent(current, SIGCHLD);
 	schedule();
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r2300_fpu.S linux/arch/mips/kernel/r2300_fpu.S
--- v2.4.5/linux/arch/mips/kernel/r2300_fpu.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r2300_fpu.S	Mon Jul  2 13:56:40 2001
@@ -117,6 +117,7 @@
 	jr	ra
 	 ctc1	t0,fcr31
 	END(_restore_fp_context)
+	.set	reorder
 
 	.type	fault@function
 	.ent	fault
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r2300_switch.S linux/arch/mips/kernel/r2300_switch.S
--- v2.4.5/linux/arch/mips/kernel/r2300_switch.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r2300_switch.S	Mon Jul  2 13:56:40 2001
@@ -34,6 +34,9 @@
  *                     task_struct *next)
  */
 LEAF(resume)
+#ifndef CONFIG_CPU_HAS_LLSC
+	sw      zero, ll_bit
+#endif
 	mfc0	t1, CP0_STATUS
 	sw	t1, THREAD_STATUS(a0)
 	CPU_SAVE_NONSCRATCH(a0)
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r4k_fpu.S linux/arch/mips/kernel/r4k_fpu.S
--- v2.4.5/linux/arch/mips/kernel/r4k_fpu.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r4k_fpu.S	Mon Jul  2 13:56:40 2001
@@ -93,6 +93,7 @@
 	jr	ra
 	 ctc1	t0,fcr31
 	END(_restore_fp_context)
+	.set	reorder
 
 	.type	fault@function
 	.ent	fault
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r4k_misc.S linux/arch/mips/kernel/r4k_misc.S
--- v2.4.5/linux/arch/mips/kernel/r4k_misc.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r4k_misc.S	Mon Jul  2 13:56:40 2001
@@ -35,10 +35,25 @@
 	 * in register PTE, a ptr into the table in which
 	 * the pte belongs is in PTR.
 	 */
+
+#ifdef CONFIG_SMP
+#define GET_PGD(scratch, ptr)        \
+	mfc0    ptr, CP0_CONTEXT;    \
+	la      scratch, current_pgd;\
+	srl     ptr, 23;             \
+	sll     ptr, 2;              \
+	addu    ptr, scratch, ptr;   \
+	lw      ptr, (ptr);          
+#else
+#define GET_PGD(scratch, ptr)    \
+	lw	ptr, current_pgd;
+#endif
+	
+	
 #define LOAD_PTE(pte, ptr) \
+	GET_PGD(pte, ptr)          \
 	mfc0	pte, CP0_BADVADDR; \
 	srl	pte, pte, 22; \
-	lw	ptr, current_pgd; \
 	sll	pte, pte, 2; \
 	addu	ptr, ptr, pte; \
 	mfc0	pte, CP0_BADVADDR; \
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/r4k_switch.S linux/arch/mips/kernel/r4k_switch.S
--- v2.4.5/linux/arch/mips/kernel/r4k_switch.S	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/r4k_switch.S	Mon Jul  2 13:56:40 2001
@@ -1,5 +1,4 @@
-/* $Id: r4k_switch.S,v 1.9 1999/08/18 23:37:44 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
@@ -38,6 +37,9 @@
 	.set	noreorder
 	.align	5
 	LEAF(resume)
+#ifndef CONFIG_CPU_HAS_LLSC
+	sw      zero, ll_bit
+#endif
 	mfc0	t1, CP0_STATUS
 	sw	t1, THREAD_STATUS(a0)
 	CPU_SAVE_NONSCRATCH(a0)
@@ -50,7 +52,16 @@
 	move	$28, a1
 	CPU_RESTORE_NONSCRATCH($28)
 	addiu	t0, $28, KERNEL_STACK_SIZE-32
+#ifdef CONFIG_SMP	 
+	mfc0	a3, CP0_CONTEXT
+	la	t1, kernelsp
+	srl	a3, 23
+	sll	a3, 2
+	addu	t1, a3, t1
+	sw	t0, (t1)	
+#else
 	sw	t0, kernelsp
+#endif 
 	mfc0	t1, CP0_STATUS		/* Do we really need this? */
 	li	a3, 0xff00
 	and	t1, a3
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/scall_o32.S linux/arch/mips/kernel/scall_o32.S
--- v2.4.5/linux/arch/mips/kernel/scall_o32.S	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/kernel/scall_o32.S	Mon Jul  2 13:56:40 2001
@@ -65,8 +65,14 @@
 1:	sw	v0, PT_R2(sp)		# result
 
 EXPORT(o32_ret_from_sys_call)
-	lw	t0, irq_stat		# softirq_active
-	lw	t1, irq_stat+4		# softirq_mask.  unused delay slot
+	la	t1, irq_stat		# softirq_active
+#ifdef CONFIG_SMP
+	lw	t0, TASK_PROCESSOR($28)
+        sll	t0, t0, 5
+	addu	t1, t0
+#endif
+	lw	t0, 0(t1)		# softirq_active
+	lw	t1, 4(t1)		# softirq_mask.  unused delay slot
 	and	t0, t1
 	bnez	t0, o32_handle_softirq
 
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v2.4.5/linux/arch/mips/kernel/setup.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/setup.c	Mon Jul  2 13:56:40 2001
@@ -26,13 +26,9 @@
 #include <linux/a.out.h>
 #include <linux/tty.h>
 #include <linux/bootmem.h>
-#ifdef CONFIG_BLK_DEV_RAM
 #include <linux/blk.h>
-#endif
 #include <linux/ide.h>
-#ifdef CONFIG_RTC
 #include <linux/timex.h>
-#endif
 
 #include <asm/asm.h>
 #include <asm/bootinfo.h>
@@ -45,7 +41,8 @@
 #include <asm/sgialib.h>
 #endif
 
-struct mips_cpuinfo boot_cpu_data = { NULL, NULL, 0 };
+
+struct mips_cpuinfo boot_cpu_data = { 0, NULL, NULL, 0 };
 
 /*
  * Not all of the MIPS CPUs have the "wait" instruction available. Moreover,
@@ -57,11 +54,6 @@
 void (*cpu_wait)(void) = NULL;
 
 /*
- * Do we have a cyclecounter available?
- */
-char cyclecounter_available;
-
-/*
  * There are several bus types available for MIPS machines.  "RISC PC"
  * type machines have ISA, EISA, VLB or PCI available, DECstations
  * have Turbochannel or Q-Bus, SGI has GIO, there are lots of VME
@@ -72,16 +64,16 @@
 
 struct screen_info screen_info;
 
-#ifdef CONFIG_BLK_DEV_FD
 extern struct fd_ops no_fd_ops;
 struct fd_ops *fd_ops;
-#endif
 
 #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 extern struct ide_ops no_ide_ops;
 struct ide_ops *ide_ops;
 #endif
 
+extern void * __rd_start, * __rd_end;
+
 extern struct rtc_ops no_rtc_ops;
 struct rtc_ops *rtc_ops;
 
@@ -95,23 +87,17 @@
  *
  * These are initialized so they are in the .data section
  */
-unsigned long mips_memory_upper = KSEG0; /* this is set by kernel_entry() */
-unsigned long mips_cputype = CPU_UNKNOWN;
 unsigned long mips_machtype = MACH_UNKNOWN;
 unsigned long mips_machgroup = MACH_GROUP_UNKNOWN;
 
+struct boot_mem_map boot_mem_map;
+
 unsigned char aux_device_present;
-extern int _end;
+extern char _ftext, _etext, _fdata, _edata, _end;
 
-static char command_line[CL_SIZE] = { 0, };
-       char saved_command_line[CL_SIZE];
-extern char arcs_cmdline[CL_SIZE];
-
-/*
- * The board specific setup routine sets irq_setup to point to a board
- * specific setup routine.
- */
-void (*irq_setup)(void);
+static char command_line[COMMAND_LINE_SIZE];
+       char saved_command_line[COMMAND_LINE_SIZE];
+extern char arcs_cmdline[COMMAND_LINE_SIZE];
 
 /*
  * mips_io_port_base is the begin of the address space to which x86 style
@@ -129,7 +115,10 @@
 extern void SetUpBootInfo(void);
 extern void loadmmu(void);
 extern asmlinkage void start_kernel(void);
-extern int prom_init(int, char **, char **, int *);
+extern void prom_init(int, char **, char **, int *);
+
+static struct resource code_resource = { "Kernel code" };
+static struct resource data_resource = { "Kernel data" };
 
 /*
  * Probe whether cpu has config register by trying to play with
@@ -143,9 +132,9 @@
 	unsigned long size1, size2; 
 	unsigned long cfg = read_32bit_cp0_register(CP0_CONF);
 
-	size1 = r3k_cache_size(ST0_DE);
+	size1 = r3k_cache_size(ST0_ISC);
 	write_32bit_cp0_register(CP0_CONF, cfg^CONF_AC);
-	size2 = r3k_cache_size(ST0_DE);
+	size2 = r3k_cache_size(ST0_ISC);
 	write_32bit_cp0_register(CP0_CONF, cfg);
 	return size1 != size2;
 #else
@@ -165,152 +154,230 @@
 
 static inline void cpu_probe(void)
 {
+
+#ifdef CONFIG_CPU_MIPS32
 	unsigned long config1;
+#endif
 
 	mips_cpu.processor_id = read_32bit_cp0_register(CP0_PRID);
-	switch (mips_cpu.processor_id & 0xff00) {
-	case PRID_IMP_R2000:
-		mips_cpu.cputype = CPU_R2000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
-		mips_cpu.tlbsize = 64;
-		break;
-	case PRID_IMP_R3000:
-		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
-			if (cpu_has_confreg())
-				mips_cpu.cputype = CPU_R3081E;
+	switch (mips_cpu.processor_id & 0xff0000) {
+	case PRID_COMP_LEGACY:
+		switch (mips_cpu.processor_id & 0xff00) {
+		case PRID_IMP_R2000:
+			mips_cpu.cputype = CPU_R2000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_I;
+			mips_cpu.options = MIPS_CPU_TLB;
+			mips_cpu.tlbsize = 64;
+			break;
+		case PRID_IMP_R3000:
+			if ((mips_cpu.processor_id & 0xff) == PRID_REV_R3000A)
+				if (cpu_has_confreg())
+					mips_cpu.cputype = CPU_R3081E;
+				else
+					mips_cpu.cputype = CPU_R3000A;
 			else
-				mips_cpu.cputype = CPU_R3000A;
-		else
-			 mips_cpu.cputype = CPU_R3000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
-		mips_cpu.tlbsize = 64;
-		break;
-	case PRID_IMP_R4000:
-		if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
-			mips_cpu.cputype = CPU_R4400SC;
-		else
-			mips_cpu.cputype = CPU_R4000SC;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
-		                   MIPS_CPU_WATCH | MIPS_CPU_VCE;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_R4600:
-		mips_cpu.cputype = CPU_R4600;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 48;
-		break;
+				mips_cpu.cputype = CPU_R3000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_I;
+			mips_cpu.options = MIPS_CPU_TLB;
+			mips_cpu.tlbsize = 64;
+			break;
+		case PRID_IMP_R4000:
+			if ((mips_cpu.processor_id & 0xff) == PRID_REV_R4400)
+				mips_cpu.cputype = CPU_R4400SC;
+			else
+				mips_cpu.cputype = CPU_R4000SC;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR |
+				           MIPS_CPU_WATCH | MIPS_CPU_VCE;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R4600:
+			mips_cpu.cputype = CPU_R4600;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+			mips_cpu.tlbsize = 48;
+			break;
 /*
  * This processor doesn't have an MMU, so it's not "real easy" to
  * run Linux on it. It is left purely for documentation.
- *
-	case PRID_IMP_R4650:
-		mips_cpu.cputype = CPU_R4650;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 48;
-		break;
- */
-	case PRID_IMP_R3912:
-		mips_cpu.cputype = CPU_R3912;
-		mips_cpu.isa_level = MIPS_CPU_ISA_I;
-		mips_cpu.options = MIPS_CPU_TLB;
-		mips_cpu.tlbsize = 32;
-		break;
-	case PRID_IMP_R4700:
-		mips_cpu.cputype = CPU_R4700;
-		mips_cpu.isa_level = MIPS_CPU_ISA_III;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_R5000:
-		mips_cpu.cputype = CPU_R5000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_R5432:
-	        mips_cpu.cputype = CPU_R5432;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 48;
-		break;
-	case PRID_IMP_NEVADA:
-		mips_cpu.cputype = CPU_NEVADA;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 
-		                   MIPS_CPU_DIVEC;
-		mips_cpu.tlbsize = 48;
-		mips_cpu.icache.ways = 2;
-		mips_cpu.dcache.ways = 2;
-		break;
-	case PRID_IMP_R6000:
-		mips_cpu.cputype = CPU_R6000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_II;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 32;
-		break;
-	case PRID_IMP_R6000A:
-		mips_cpu.cputype = CPU_R6000A;
-		mips_cpu.isa_level = MIPS_CPU_ISA_II;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
-		mips_cpu.tlbsize = 32;
-		break;
-	case PRID_IMP_RM7000:
-		mips_cpu.cputype = CPU_RM7000;
-	        mips_cpu.isa_level = MIPS_CPU_ISA_IV;
-		mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		break;
-	case PRID_IMP_R8000:
-		mips_cpu.cputype = CPU_R8000;
-	        mips_cpu.isa_level = MIPS_CPU_ISA_IV;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
-		                   MIPS_CPU_FPU | MIPS_CPU_32FPR;
-		mips_cpu.tlbsize = 384;      /* has wierd TLB: 3-way x 128 */
-		break;
-	case PRID_IMP_R10000:
-		mips_cpu.cputype = CPU_R10000;
-		mips_cpu.isa_level = MIPS_CPU_ISA_IV;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-		                   MIPS_CPU_FPU | MIPS_CPU_32FPR | 
-		                   MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
-		mips_cpu.tlbsize = 64;
+ *		case PRID_IMP_R4650:
+	 		mips_cpu.cputype = CPU_R4650;
+		 	mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU;
+		        mips_cpu.tlbsize = 48;
+			break;
+*/
+		case PRID_IMP_TX39:
+			mips_cpu.isa_level = MIPS_CPU_ISA_I;
+			mips_cpu.options = MIPS_CPU_TLB;
+
+			switch (mips_cpu.processor_id & 0xff) {
+			case PRID_REV_TX3912:
+				mips_cpu.cputype = CPU_TX3912;
+				mips_cpu.tlbsize = 32;
+				break;
+			case PRID_REV_TX3922:
+				mips_cpu.cputype = CPU_TX3922;
+				mips_cpu.tlbsize = 64;
+				break;
+			case PRID_REV_TX3927:
+				mips_cpu.cputype = CPU_TX3927;
+				mips_cpu.tlbsize = 64;
+				break;
+			default:
+				mips_cpu.cputype = CPU_UNKNOWN;
+				break;
+			}
+			break;
+		case PRID_IMP_R4700:
+			mips_cpu.cputype = CPU_R4700;
+			mips_cpu.isa_level = MIPS_CPU_ISA_III;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R5000:
+			mips_cpu.cputype = CPU_R5000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_R5432:
+			mips_cpu.cputype = CPU_R5432;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 48;
+			break;
+		case PRID_IMP_NEVADA:
+			mips_cpu.cputype = CPU_NEVADA;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV; 
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+				           MIPS_CPU_DIVEC;
+			mips_cpu.tlbsize = 48;
+			mips_cpu.icache.ways = 2;
+			mips_cpu.dcache.ways = 2;
+			break;
+		case PRID_IMP_R6000:
+			mips_cpu.cputype = CPU_R6000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_II;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+			mips_cpu.tlbsize = 32;
+			break;
+		case PRID_IMP_R6000A:
+			mips_cpu.cputype = CPU_R6000A;
+			mips_cpu.isa_level = MIPS_CPU_ISA_II;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_FPU;
+			mips_cpu.tlbsize = 32;
+			break;
+		case PRID_IMP_RM7000:
+			mips_cpu.cputype = CPU_RM7000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+			mips_cpu.options = R4K_OPTS | MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			break;
+		case PRID_IMP_R8000:
+			mips_cpu.cputype = CPU_R8000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_IV;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX |
+				           MIPS_CPU_FPU | MIPS_CPU_32FPR;
+			mips_cpu.tlbsize = 384;      /* has wierd TLB: 3-way x 128 */
+			break;
+		case PRID_IMP_R10000:
+			mips_cpu.cputype = CPU_R10000;
+			mips_cpu.cputype = MIPS_CPU_ISA_IV;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_FPU | MIPS_CPU_32FPR | 
+				           MIPS_CPU_COUNTER | MIPS_CPU_WATCH;
+			mips_cpu.tlbsize = 64;
+			break;
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}
 		break;
 #ifdef CONFIG_CPU_MIPS32
-	case PRID_IMP_4KC:
-		mips_cpu.cputype = CPU_4KC;
-		mips_cpu.isa_level = MIPS_CPU_ISA_M32;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-		                   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
-		                   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
-		config1 = read_mips32_cp0_config1();
-		if (config1 & (1 << 3))
-		        mips_cpu.options |= MIPS_CPU_WATCH;
-		if (config1 & (1 << 2))
-		        mips_cpu.options |= MIPS_CPU_MIPS16;
-		if (config1 & 1)
-		        mips_cpu.options |= MIPS_CPU_FPU;
-		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
-		break;
-	case PRID_IMP_5KC:
-		mips_cpu.cputype = CPU_5KC;
-		mips_cpu.isa_level = MIPS_CPU_ISA_M64;
-		mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
-		                   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
-		                   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
-		config1 = read_mips32_cp0_config1();
-		if (config1 & (1 << 3))
-		        mips_cpu.options |= MIPS_CPU_WATCH;
-		if (config1 & (1 << 2))
-		        mips_cpu.options |= MIPS_CPU_MIPS16;
-		if (config1 & 1)
-		        mips_cpu.options |= MIPS_CPU_FPU;
-		mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+	case PRID_COMP_MIPS:
+		switch (mips_cpu.processor_id & 0xff00) {
+		case PRID_IMP_4KC:
+			mips_cpu.cputype = CPU_4KC;
+			goto cpu_4kc;
+		case PRID_IMP_4KEC:
+			mips_cpu.cputype = CPU_4KEC;
+			goto cpu_4kc;
+		case PRID_IMP_4KSC:
+			mips_cpu.cputype = CPU_4KSC;
+cpu_4kc:
+			/* Why do we set all these options by default, THEN query them?? */
+			mips_cpu.cputype = MIPS_CPU_ISA_M32;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+				           MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+			config1 = read_mips32_cp0_config1();
+			if (config1 & (1 << 3))
+				mips_cpu.options |= MIPS_CPU_WATCH;
+			if (config1 & (1 << 2))
+				mips_cpu.options |= MIPS_CPU_MIPS16;
+			if (config1 & 1)
+				mips_cpu.options |= MIPS_CPU_FPU;
+			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+			break;
+		case PRID_IMP_5KC:
+			mips_cpu.cputype = CPU_5KC;
+			mips_cpu.cputype = MIPS_CPU_ISA_M64;
+			/* See comment above about querying options */
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+				           MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+			config1 = read_mips32_cp0_config1();
+			if (config1 & (1 << 3))
+				mips_cpu.options |= MIPS_CPU_WATCH;
+			if (config1 & (1 << 2))
+				mips_cpu.options |= MIPS_CPU_MIPS16;
+			if (config1 & 1)
+				mips_cpu.options |= MIPS_CPU_FPU;
+			break;
+			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}		
 		break;
 #endif
+	case PRID_COMP_ALCHEMY:
+		switch (mips_cpu.processor_id & 0xff00) {
+#ifdef CONFIG_CPU_MIPS32
+		case PRID_IMP_AU1000:
+			mips_cpu.cputype = CPU_AU1000;
+			mips_cpu.isa_level = MIPS_CPU_ISA_M32;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+					   MIPS_CPU_4KTLB | MIPS_CPU_COUNTER | 
+					   MIPS_CPU_DIVEC | MIPS_CPU_WATCH;
+			config1 = read_mips32_cp0_config1();
+			if (config1 & (1 << 3))
+				mips_cpu.options |= MIPS_CPU_WATCH;
+			if (config1 & (1 << 2))
+				mips_cpu.options |= MIPS_CPU_MIPS16;
+			if (config1 & 1)
+				mips_cpu.options |= MIPS_CPU_FPU;
+			mips_cpu.scache.flags = MIPS_CACHE_NOT_PRESENT;
+			break;
+#endif
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}
+		break;
+	case PRID_COMP_SIBYTE:
+		switch (mips_cpu.processor_id & 0xff00) {
+		case PRID_IMP_SB1:
+			mips_cpu.cputype = CPU_SB1;
+			mips_cpu.options = MIPS_CPU_TLB | MIPS_CPU_4KEX | 
+				           MIPS_CPU_COUNTER | MIPS_CPU_DIVEC | MIPS_CPU_FPU |
+		      	           MIPS_CPU_VCE;
+			break;
+		default:
+			mips_cpu.cputype = CPU_UNKNOWN;
+			break;
+		}
+		break;
 	default:
 		mips_cpu.cputype = CPU_UNKNOWN;
 	}
@@ -329,9 +396,6 @@
 #ifdef CONFIG_SGI_IP22
 	sgi_sysinit();
 #endif
-#ifdef CONFIG_COBALT_MICRO_SERVER
-	SetUpBootInfo();
-#endif
 
 	/*
 	 * Determine the mmu/cache attached to this machine,
@@ -349,25 +413,116 @@
 	start_kernel();
 }
 
-static void __init default_irq_setup(void)
+void __init add_memory_region(unsigned long start, unsigned long size,
+			      long type)
 {
-	panic("Unknown machtype in init_IRQ");
+	int x = boot_mem_map.nr_map;
+
+	if (x == BOOT_MEM_MAP_MAX) {
+		printk("Ooops! Too many entries in the memory map!\n");
+		return;
+	}
+
+	boot_mem_map.map[x].addr = start;
+	boot_mem_map.map[x].size = size;
+	boot_mem_map.map[x].type = type;
+	boot_mem_map.nr_map++;
+}
+
+static void __init print_memory_map(void)
+{
+	int i;
+
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		printk(" memory: %08lx @ %08lx ",
+			boot_mem_map.map[i].size, boot_mem_map.map[i].addr);
+		switch (boot_mem_map.map[i].type) {
+		case BOOT_MEM_RAM:
+			printk("(usable)\n");
+			break;
+		case BOOT_MEM_ROM_DATA:
+			printk("(ROM data)\n");
+			break;
+		case BOOT_MEM_RESERVED:
+			printk("(reserved)\n");
+			break;
+		default:
+			printk("type %lu\n", boot_mem_map.map[i].type);
+			break;
+		}
+	}
+}
+
+static inline void parse_mem_cmdline(void)
+{
+	char c = ' ', *to = command_line, *from = saved_command_line;
+	unsigned long start_at, mem_size;
+	int len = 0;
+	int usermem = 0;
+
+	printk("Determined physical RAM map:\n");
+	print_memory_map();
+
+	for (;;) {
+		/*
+		 * "mem=XXX[kKmM]" defines a memory region from
+		 * 0 to <XXX>, overriding the determined size.
+		 * "mem=XXX[KkmM]@YYY[KkmM]" defines a memory region from
+		 * <YYY> to <YYY>+<XXX>, overriding the determined size.
+		 */
+		if (c == ' ' && !memcmp(from, "mem=", 4)) {
+			if (to != command_line)
+				to--;
+			/*
+			 * If a user specifies memory size, we
+			 * blow away any automatically generated
+			 * size.
+			 */
+			if (usermem == 0) {
+				boot_mem_map.nr_map = 0;
+				usermem = 1;
+			}
+			mem_size = memparse(from + 4, &from);
+			if (*from == '@')
+				start_at = memparse(from + 1, &from);
+			else
+				start_at = 0;
+			add_memory_region(start_at, mem_size, BOOT_MEM_RAM);
+		}
+		c = *(from++);
+		if (!c)
+			break;
+		if (COMMAND_LINE_SIZE <= ++len)
+			break;
+		*(to++) = c;
+	}
+	*to = '\0';
+
+	if (usermem) {
+		printk("User-defined physical RAM map:\n");
+		print_memory_map();
+	}
 }
 
 void __init setup_arch(char **cmdline_p)
 {
+	void atlas_setup(void);
 	void baget_setup(void);
-	void cobalt_setup(void);
+	void ddb_setup(void);
 	void decstation_setup(void);
 	void deskstation_setup(void);
 	void jazz_setup(void);
 	void sni_rm200_pci_setup(void);
 	void sgi_setup(void);
-	void ddb_setup(void);
-	void orion_setup(void);
+        void ev96100_setup(void);
+	void malta_setup(void);
+	void momenco_ocelot_setup(void);
+	void nino_setup(void);
 
-	/* Save defaults for configuration-dependent routines.  */
-	irq_setup = default_irq_setup;
+	unsigned long bootmap_size;
+	unsigned long start_pfn, max_pfn, first_usable_pfn;
+
+	int i;
 
 #ifdef CONFIG_BLK_DEV_FD
 	fd_ops = &no_fd_ops;
@@ -390,21 +545,31 @@
 		baget_setup();
 		break;
 #endif
-#ifdef CONFIG_COBALT_MICRO_SERVER
-	case MACH_GROUP_COBALT:
-		cobalt_setup();
-		break;
-#endif
 #ifdef CONFIG_DECSTATION
 	case MACH_GROUP_DEC:
 		decstation_setup();
 		break;
 #endif
+#ifdef CONFIG_MIPS_ATLAS
+	case MACH_GROUP_UNKNOWN:
+		atlas_setup();
+		break;
+#endif
 #ifdef CONFIG_MIPS_JAZZ
 	case MACH_GROUP_JAZZ:
 		jazz_setup();
 		break;
 #endif
+#ifdef CONFIG_MIPS_MALTA
+	case MACH_GROUP_UNKNOWN:
+		malta_setup();
+		break;
+#endif
+#ifdef CONFIG_MOMENCO_OCELOT
+	case MACH_GROUP_MOMENCO:
+		momenco_ocelot_setup();
+		break;
+#endif
 #ifdef CONFIG_SGI_IP22
 	/* As of now this is only IP22.  */
 	case MACH_GROUP_SGI:
@@ -421,42 +586,193 @@
 		ddb_setup();
 		break;
 #endif
-#ifdef CONFIG_ORION
-	case MACH_GROUP_ORION:
-		orion_setup();
+#ifdef CONFIG_DDB5476
+       case MACH_GROUP_NEC_DDB:
+               ddb_setup();
+               break;
+#endif
+#ifdef CONFIG_DDB5477
+       case MACH_GROUP_NEC_DDB:
+               ddb_setup();
+               break;
+#endif
+#ifdef CONFIG_MIPS_EV96100
+	case MACH_GROUP_GALILEO:
+		ev96100_setup();
+		break;
+#endif
+#ifdef CONFIG_MIPS_EV64120
+	case MACH_GROUP_GALILEO:
+		ev64120_setup();
+		break;
+#endif
+#if defined(CONFIG_MIPS_IVR) || defined(CONFIG_MIPS_ITE8172)
+	case  MACH_GROUP_ITE:
+	case  MACH_GROUP_GLOBESPAN:
+		it8172_setup();
+		break;
+#endif  
+#ifdef CONFIG_NINO
+	case MACH_GROUP_PHILIPS:
+		nino_setup();
+		break;
+#endif
+#ifdef CONFIG_MIPS_PB1000
+	case MACH_GROUP_ALCHEMY:
+		au1000_setup();
 		break;
 #endif
 	default:
 		panic("Unsupported architecture");
 	}
 
-        strncpy (command_line, arcs_cmdline, CL_SIZE);
-	memcpy(saved_command_line, command_line, CL_SIZE);
-	saved_command_line[CL_SIZE-1] = '\0';
-
+	strncpy(command_line, arcs_cmdline, sizeof command_line);
+	command_line[sizeof command_line - 1] = 0;
+	strcpy(saved_command_line, command_line);
 	*cmdline_p = command_line;
 
+	parse_mem_cmdline();
+
+#define PFN_UP(x)	(((x) + PAGE_SIZE - 1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)	((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)	((x) << PAGE_SHIFT)
+
+	/*
+	 * Partially used pages are not usable - thus
+	 * we are rounding upwards.
+	 */
+	start_pfn = PFN_UP(__pa(&_end));
+
+	/* Find the highest page frame number we have available.  */
+	max_pfn = 0;
+	first_usable_pfn = -1UL;
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		unsigned long start, end;
+
+		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+			continue;
+
+		start = PFN_UP(boot_mem_map.map[i].addr);
+		end = PFN_DOWN(boot_mem_map.map[i].addr
+		      + boot_mem_map.map[i].size);
+
+		if (start >= end)
+			continue;
+		if (end > max_pfn)
+			max_pfn = end;
+		if (start < first_usable_pfn) {
+			if (start > start_pfn) {
+				first_usable_pfn = start;
+			} else if (end > start_pfn) {
+				first_usable_pfn = start_pfn;
+			}
+		}
+	}
+	
+	/* Initialize the boot-time allocator.  */
+	bootmap_size = init_bootmem(first_usable_pfn, max_pfn);
+
+	/*
+	 * Register fully available low RAM pages with the bootmem allocator.
+	 */
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		unsigned long curr_pfn, last_pfn, size;
+
+		/*
+		 * Reserve usable memory.
+		 */
+		if (boot_mem_map.map[i].type != BOOT_MEM_RAM)
+			continue;
+
+		/*
+		 * We are rounding up the start address of usable memory:
+		 */
+		curr_pfn = PFN_UP(boot_mem_map.map[i].addr);
+		if (curr_pfn >= max_pfn)
+			continue;
+		if (curr_pfn < start_pfn)
+			curr_pfn = start_pfn;
+
+		/*
+		 * ... and at the end of the usable range downwards:
+		 */
+		last_pfn = PFN_DOWN(boot_mem_map.map[i].addr
+				    + boot_mem_map.map[i].size);
+
+		if (last_pfn > max_pfn)
+			last_pfn = max_pfn;
+
+		/*
+		 * ... finally, did all the rounding and playing
+		 * around just make the area go away?
+		 */
+		if (last_pfn <= curr_pfn)
+			continue;
+
+		size = last_pfn - curr_pfn;
+		free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
+	}
+
+	/* Reserve the bootmap memory.  */
+	reserve_bootmem(PFN_PHYS(first_usable_pfn), bootmap_size);
+
 #ifdef CONFIG_BLK_DEV_INITRD
-#error "Fixme, I'm broken."
-	tmp = (((unsigned long)&_end + PAGE_SIZE-1) & PAGE_MASK) - 8;
-	if (tmp < (unsigned long)&_end)
-		tmp += PAGE_SIZE;
-	initrd_header = (unsigned long *)tmp;
-	if (initrd_header[0] == 0x494E5244) {
-		initrd_start = (unsigned long)&initrd_header[2];
-		initrd_end = initrd_start + initrd_header[1];
-		initrd_below_start_ok = 1;
-		if (initrd_end > memory_end) {
+	/* Board specific code should have set up initrd_start and initrd_end */
+	ROOT_DEV = MKDEV(RAMDISK_MAJOR, 0);
+	initrd_start = (unsigned long)&__rd_start;
+	initrd_end = (unsigned long)&__rd_end;
+	initrd_below_start_ok = 1;
+	if (initrd_start) {
+		unsigned long initrd_size = ((unsigned char *)initrd_end) - ((unsigned char *)initrd_start); 
+		printk("Initial ramdisk at: 0x%p (%lu bytes)\n",
+		       (void *)initrd_start, 
+		       initrd_size);
+		if ((void *)initrd_end > phys_to_virt(PFN_PHYS(max_low_pfn))) {
 			printk("initrd extends beyond end of memory "
-			       "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
-			       initrd_end,memory_end);
-			initrd_start = 0;
-		} else
-			*memory_start_p = initrd_end;
+			       "(0x%lx > 0x%p)\ndisabling initrd\n",
+			       initrd_end,
+			       phys_to_virt(PFN_PHYS(max_low_pfn)));
+			initrd_start = initrd_end = 0;
+		} 
 	}
-#endif
+#endif /* CONFIG_BLK_DEV_INITRD  */
 
 	paging_init();
+
+	code_resource.start = virt_to_bus(&_ftext);
+	code_resource.end = virt_to_bus(&_etext) - 1;
+	data_resource.start = virt_to_bus(&_fdata);
+	data_resource.end = virt_to_bus(&_edata) - 1;
+
+	/*
+	 * Request address space for all standard RAM.
+	 */
+	for (i = 0; i < boot_mem_map.nr_map; i++) {
+		struct resource *res;
+
+		res = alloc_bootmem(sizeof(struct resource));
+		switch (boot_mem_map.map[i].type) {
+		case BOOT_MEM_RAM:
+		case BOOT_MEM_ROM_DATA:
+			res->name = "System RAM";
+			break;
+		case BOOT_MEM_RESERVED:
+		default:
+			res->name = "reserved";
+		}
+		res->start = boot_mem_map.map[i].addr;
+		res->end = res->start + boot_mem_map.map[i].size - 1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+		request_resource(&iomem_resource, res);
+
+		/*
+		 *  We dont't know which RAM region contains kernel data,
+		 *  so we try it repeatedly and let the resource manager
+		 *  test it.
+		 */
+		request_resource(res, &code_resource);
+		request_resource(res, &data_resource);
+	}
 }
 
 void r3081_wait(void) 
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/smp.c linux/arch/mips/kernel/smp.c
--- v2.4.5/linux/arch/mips/kernel/smp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/kernel/smp.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,402 @@
+/*
+ *
+ *  arch/mips/kernel/smp.c
+ *
+ *  Copyright (C) 2000 Sibyte
+ * 
+ *  Written by Justin Carlson (carlson@sibyte.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */ 
+
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/threads.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/atomic.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/hardirq.h>
+#include <asm/softirq.h>
+#include <asm/mmu_context.h>
+#include <asm/delay.h>
+#include <asm/smp.h>
+
+/*
+ * This was written with the BRCM12500 MP SOC in mind, but tries to
+ * be generic.  It's modelled on the mips64 smp.c code, which is
+ * derived from Sparc, I'm guessing, which is derived from...
+ * 
+ * It's probably horribly designed for very large ccNUMA systems
+ * as it doesn't take any node clustering into account.  
+*/
+
+
+/* Ze Big Kernel Lock! */
+spinlock_t kernel_flag = SPIN_LOCK_UNLOCKED;
+int smp_threads_ready;  /* Not used */
+int smp_num_cpus;    
+int global_irq_holder = NO_PROC_ID;
+spinlock_t global_irq_lock = SPIN_LOCK_UNLOCKED;
+struct mips_cpuinfo cpu_data[NR_CPUS];
+
+struct smp_fn_call_struct smp_fn_call = 
+{ SPIN_LOCK_UNLOCKED, ATOMIC_INIT(0), NULL, NULL};
+
+static atomic_t cpus_booted = ATOMIC_INIT(0);
+
+
+/* These are defined by the board-specific code. */
+
+/* Cause the function described by smp_fn_call 
+   to be executed on the passed cpu.  When the function
+   has finished, increment the finished field of
+   smp_fn_call. */
+
+void core_call_function(int cpu);
+
+/*
+ * Clear all undefined state in the cpu, set up sp and gp to the passed
+ * values, and kick the cpu into smp_bootstrap(); 
+ */
+void prom_boot_secondary(int cpu, unsigned long sp, unsigned long gp);
+
+/*
+ *  After we've done initial boot, this function is called to allow the
+ *  board code to clean up state, if needed 
+ */
+
+void prom_init_secondary(void);
+
+
+void cpu_idle(void);
+
+/* Do whatever setup needs to be done for SMP at the board level.  Return
+   the number of cpus in the system, including this one */
+int prom_setup_smp(void);
+
+int start_secondary(void *unused)
+{
+	prom_init_secondary();
+	write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
+	current_pgd[smp_processor_id()] = init_mm.pgd;
+	printk("Slave cpu booted successfully\n");
+	atomic_inc(&cpus_booted);
+	cpu_idle();
+	return 0;
+}
+
+void __init smp_boot_cpus(void)
+{
+	int i;
+
+	smp_num_cpus = prom_setup_smp();
+	init_new_context(current, &init_mm);
+	current->processor = 0;
+	atomic_set(&cpus_booted, 1);  /* Master CPU is already booted... */
+	init_idle();
+	for (i = 1; i < smp_num_cpus; i++) {
+		struct task_struct *p;
+		struct pt_regs regs;
+		printk("Starting CPU %d... ", i);
+
+		/* Spawn a new process normally.  Grab a pointer to
+		   its task struct so we can mess with it */
+		do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+		p = init_task.prev_task;
+
+		/* Schedule the first task manually */
+		p->processor = i;
+		p->has_cpu = 1;
+
+		/* Attach to the address space of init_task. */
+		atomic_inc(&init_mm.mm_count);
+		p->active_mm = &init_mm;
+		init_tasks[i] = p;
+
+		del_from_runqueue(p);
+		unhash_process(p);
+
+		prom_boot_secondary(i,
+				    (unsigned long)p + KERNEL_STACK_SIZE - 32,
+				    (unsigned long)p);
+
+#if 0
+
+		/* This is copied from the ip-27 code in the mips64 tree */
+
+		struct task_struct *p;
+
+		/*
+		 * The following code is purely to make sure
+		 * Linux can schedule processes on this slave.
+		 */
+		kernel_thread(0, NULL, CLONE_PID);
+		p = init_task.prev_task;
+		sprintf(p->comm, "%s%d", "Idle", i);
+		init_tasks[i] = p;
+		p->processor = i;
+		p->has_cpu = 1; /* we schedule the first task manually */
+		del_from_runqueue(p);
+		unhash_process(p);
+		/* Attach to the address space of init_task. */
+		atomic_inc(&init_mm.mm_count);
+		p->active_mm = &init_mm;
+		prom_boot_secondary(i, 
+				    (unsigned long)p + KERNEL_STACK_SIZE - 32,
+				    (unsigned long)p);
+#endif
+	}
+
+	/* Wait for everyone to come up */
+	while (atomic_read(&cpus_booted) != smp_num_cpus);
+}
+
+void __init smp_commence(void)
+{
+	/* Not sure what to do here yet */
+}
+
+static void reschedule_this_cpu(void *dummy)
+{
+	current->need_resched = 1;
+}
+
+void FASTCALL(smp_send_reschedule(int cpu))
+{
+	smp_call_function(reschedule_this_cpu, NULL, 0, 0);
+}
+
+
+/*
+ * The caller of this wants the passed function to run on every cpu.  If wait
+ * is set, wait until all cpus have finished the function before returning.
+ * The lock is here to protect the call structure.
+ */
+int smp_call_function (void (*func) (void *info), void *info, int retry, 
+								int wait)
+{
+	int cpus = smp_num_cpus - 1;
+	int i;
+
+	if (smp_num_cpus < 2) {
+		return 0;
+	}
+
+	spin_lock_bh(&smp_fn_call.lock);
+
+	atomic_set(&smp_fn_call.finished, 0);
+	smp_fn_call.fn = func;
+	smp_fn_call.data = info;
+
+	for (i = 0; i < smp_num_cpus; i++) {
+		if (i != smp_processor_id()) {
+			/* Call the board specific routine */
+			core_call_function(i);
+		}
+	}
+
+	if (wait) {
+		while(atomic_read(&smp_fn_call.finished) != cpus) {}
+	}
+
+	spin_unlock_bh(&smp_fn_call.lock);
+	return 0;
+}
+
+void synchronize_irq(void)
+{
+	panic("synchronize_irq");
+}
+
+static void stop_this_cpu(void *dummy)
+{
+	printk("Cpu stopping\n");
+	for (;;);
+}
+
+void smp_send_stop(void)
+{
+	smp_call_function(stop_this_cpu, NULL, 1, 0);
+	smp_num_cpus = 1;
+}
+
+/* Not really SMP stuff ... */
+int setup_profiling_timer(unsigned int multiplier)
+{
+	return 0;
+}
+
+
+/*
+ * Most of this code is take from the mips64 tree (ip27-irq.c).  It's virtually
+ * identical to the i386 implentation in arh/i386/irq.c, with translations for
+ * the interrupt enable bit
+ */
+
+#define MAXCOUNT 		100000000
+#define SYNC_OTHER_CORES(x)	udelay(x+1)
+
+static inline void wait_on_irq(int cpu)
+{
+	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) {
+				printk("Count spun out.  Huh?\n");
+				count = ~0;
+			}
+			__sti();
+			SYNC_OTHER_CORES(cpu);
+			__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)
+{
+	if (!spin_trylock(&global_irq_lock)) {
+		/* do we already hold the lock? */
+		if ((unsigned char) cpu == global_irq_holder)
+			return;
+		/* Uhhuh.. Somebody else got it. Wait.. */
+		spin_lock(&global_irq_lock);
+	}
+	/*
+	 * We also to make sure that nobody else is running
+	 * in an interrupt context.
+	 */
+	wait_on_irq(cpu);
+
+	/*
+	 * Ok, finally..
+	 */
+	global_irq_holder = cpu;
+}
+
+
+/*
+ * 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 & ST0_IE) {
+		int cpu = smp_processor_id();
+		__cli();
+		if (!local_irq_count(cpu))
+			get_irqlock(cpu);
+	}
+}
+
+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 & ST0_IE);
+	/* 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("global_restore_flags: %08lx\n", flags);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/syscall.c linux/arch/mips/kernel/syscall.c
--- v2.4.5/linux/arch/mips/kernel/syscall.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/mips/kernel/syscall.c	Mon Jul  2 13:56:40 2001
@@ -92,22 +92,23 @@
 	return do_mmap2(addr, len, prot, flags, fd, pgoff);
 }
 
-asmlinkage int sys_fork(struct pt_regs regs)
+save_static_function(sys_fork);
+static_unused int _sys_fork(struct pt_regs regs)
 {
 	int res;
 
-	save_static(&regs);
 	res = do_fork(SIGCHLD, regs.regs[29], &regs, 0);
 	return res;
 }
 
-asmlinkage int sys_clone(struct pt_regs regs)
+
+save_static_function(sys_clone);
+static_unused int _sys_clone(struct pt_regs regs)
 {
 	unsigned long clone_flags;
 	unsigned long newsp;
 	int res;
 
-	save_static(&regs);
 	clone_flags = regs.regs[4];
 	newsp = regs.regs[5];
 	if (!newsp)
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/syscalls.h linux/arch/mips/kernel/syscalls.h
--- v2.4.5/linux/arch/mips/kernel/syscalls.h	Fri Aug 11 14:29:04 2000
+++ linux/arch/mips/kernel/syscalls.h	Mon Jul  2 13:56:40 2001
@@ -1,10 +1,9 @@
-/* $Id: syscalls.h,v 1.22 2000/02/18 00:24:30 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1995, 1996, 1997, 1998 by Ralf Baechle
+ * Copyright (C) 1995, 96, 97, 98, 99, 2000 by Ralf Baechle
  */
 
 /*
@@ -228,10 +227,11 @@
 SYS(sys_mmap2, 6)				/* 4210 */
 SYS(sys_truncate64, 2)
 SYS(sys_ftruncate64, 2)
-SYS(sys_stat64, 3)
-SYS(sys_lstat64, 3)
-SYS(sys_fstat64, 3)				/* 4215 */
+SYS(sys_stat64, 2)
+SYS(sys_lstat64, 2)
+SYS(sys_fstat64, 2)				/* 4215 */
 SYS(sys_pivot_root, 2)
 SYS(sys_mincore, 3)
 SYS(sys_madvise, 3)
 SYS(sys_getdents64, 3)
+SYS(sys_fcntl64, 3)				/* 4220 */
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.4.5/linux/arch/mips/kernel/sysirix.c	Mon Mar 19 12:35:09 2001
+++ linux/arch/mips/kernel/sysirix.c	Mon Jul  2 13:56:40 2001
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 1996 David S. Miller
  * Copyright (C) 1997 Miguel de Icaza
- * Copyright (C) 1997, 1998 Ralf Baechle
+ * Copyright (C) 1997, 1998, 1999, 2000 Ralf Baechle
  */
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -27,7 +27,6 @@
 #include <asm/page.h>
 #include <asm/pgalloc.h>
 #include <asm/uaccess.h>
-#include <asm/sgialib.h>
 #include <asm/inventory.h>
 
 /* 2,191 lines of complete and utter shit coming up... */
@@ -1249,9 +1248,9 @@
 
 	ks.st_blksize = (s32) sb->st_blksize;
 	ks.st_blocks = (long long) sb->st_blocks;
-	memcpy(&ks.st_fstype[0], &sb->st_fstype[0], 16);
-	ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] =
-		ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
+	memset(ks.st_fstype, 0, 16);
+	ks.st_pad4[0] = ks.st_pad4[1] = ks.st_pad4[2] = ks.st_pad4[3] = 0;
+	ks.st_pad4[4] = ks.st_pad4[5] = ks.st_pad4[6] = ks.st_pad4[7] = 0;
 
 	/* Now write it all back. */
 	copy_to_user(sb, &ks, sizeof(struct xstat64));
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/sysmips.c linux/arch/mips/kernel/sysmips.c
--- v2.4.5/linux/arch/mips/kernel/sysmips.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/kernel/sysmips.c	Mon Jul  2 13:56:40 2001
@@ -7,6 +7,7 @@
  *
  * Copyright (C) 1995, 1996, 1997, 2000 by Ralf Baechle
  */
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/linkage.h>
 #include <linux/mm.h>
@@ -21,6 +22,8 @@
 #include <asm/sysmips.h>
 #include <asm/uaccess.h>
 
+extern asmlinkage void syscall_trace(void);
+
 /*
  * How long a hostname can we get from user space?
  *  -EFAULT if invalid area or too long
@@ -49,7 +52,7 @@
 {
 	int	*p;
 	char	*name;
-	int	flags, tmp, len, retval, errno;
+	int	tmp, len, retval, errno;
 
 	switch(cmd) {
 	case SETNAME: {
@@ -72,8 +75,7 @@
 	}
 
 	case MIPS_ATOMIC_SET: {
-		/* This is broken in case of page faults and SMP ...
-		    Risc/OS faults after maximum 20 tries with EAGAIN.  */
+#ifdef CONFIG_CPU_HAS_LLSC
 		unsigned int tmp;
 
 		p = (int *) arg1;
@@ -81,16 +83,46 @@
 		if (errno)
 			return errno;
 		errno = 0;
-		save_and_cli(flags);
-		errno |= __get_user(tmp, p);
-		errno |= __put_user(arg2, p);
-		restore_flags(flags);
+
+		__asm__(".set\tpush\t\t\t# sysmips(MIPS_ATOMIC, ...)\n\t"
+			".set\tmips2\n\t"
+			".set\tnoat\n\t"
+			"1:\tll\t%0, %4\n\t"
+			"move\t$1, %3\n\t"
+			"2:\tsc\t$1, %1\n\t"
+			"beqz\t$1, 1b\n\t"
+			".set\tpop\n\t"
+			".section\t.fixup,\"ax\"\n"
+			"3:\tli\t%2, 1\t\t\t# error\n\t"
+			".previous\n\t"
+			".section\t__ex_table,\"a\"\n\t"
+			".word\t1b, 3b\n\t"
+			".word\t2b, 3b\n\t"
+			".previous\n\t"
+			: "=&r" (tmp), "=o" (* (u32 *) p), "=r" (errno)
+			: "r" (arg2), "o" (* (u32 *) p), "2" (errno)
+			: "$1");
 
 		if (errno)
-			return tmp;
+			return -EFAULT;
 
-		return tmp;             /* This is broken ...  */ 
-        }
+		/* We're skipping error handling etc.  */
+		if (current->ptrace & PT_TRACESYS)
+			syscall_trace();
+
+		((struct pt_regs *)&cmd)->regs[2] = tmp;
+		((struct pt_regs *)&cmd)->regs[7] = 0;
+
+		__asm__ __volatile__(
+			"move\t$29, %0\n\t"
+			"j\to32_ret_from_sys_call"
+			: /* No outputs */
+			: "r" (&cmd));
+		/* Unreached */
+#else
+	printk("sys_sysmips(MIPS_ATOMIC_SET, ...) not ready for !CONFIG_CPU_HAS_LLSC\n");
+#endif
+	}
 
 	case MIPS_FIXADE:
 		tmp = current->thread.mflags & ~3;
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v2.4.5/linux/arch/mips/kernel/time.c	Mon Oct 16 12:58:51 2000
+++ linux/arch/mips/kernel/time.c	Mon Jul  2 13:56:40 2001
@@ -1,551 +1,542 @@
-/*
- * Copyright (C) 1991, 1992, 1995  Linus Torvalds
- * Copyright (C) 1996 - 2000  Ralf Baechle
+/***********************************************************************
+ * Copyright 2001 MontaVista Software Inc.
+ * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
+ *
+ * arch/mips/kernel/time.c
+ *     Common time service routines for MIPS machines.  See 
+ *     Documents/MIPS/time.txt. 
  *
- * This file contains the time handling details for PC-style clocks as
- * found in some MIPS systems.
+ * 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/errno.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/kernel.h>
 #include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/smp.h>
 #include <linux/kernel_stat.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
 
 #include <asm/bootinfo.h>
-#include <asm/mipsregs.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/ddb5074.h>
-
-#include <linux/mc146818rtc.h>
-#include <linux/timex.h>
-
-extern volatile unsigned long wall_jiffies;
-unsigned long r4k_interval;
-extern rwlock_t xtime_lock;
-
-/*
- * Change this if you have some constant time drift
+#include <asm/cpu.h>
+#include <asm/time.h>
+#include <asm/hardirq.h>
+
+/* 
+ * macro for catching spurious errors.  Eable to LL_DEBUG in kernel hacking
+ * config menu.
  */
-/* This is the value for the PC-style PICs. */
-/* #define USECS_PER_JIFFY (1000020/HZ) */
+#ifdef CONFIG_LL_DEBUG
+#define	MIPS_ASSERT(x)	if (!(x)) { panic("MIPS_ASSERT failed at %s:%d\n", __FILE__, __LINE__); }
+#define MIPS_DEBUG(x)  do { x; } while (0)
+#else
+#define MIPS_ASSERT(x)
+#define MIPS_DEBUG(x)
+#endif
 
 /* This is for machines which generate the exact clock. */
 #define USECS_PER_JIFFY (1000000/HZ)
+#define USECS_PER_JIFFY_FRAC (0x100000000*1000000/HZ&0xffffffff)
 
-/* Cycle counter value at the previous timer interrupt.. */
-
-static unsigned int timerhi, timerlo;
+/*
+ * forward reference
+ */
+extern rwlock_t xtime_lock;
+extern volatile unsigned long wall_jiffies;
 
 /*
- * On MIPS only R4000 and better have a cycle counter.
- *
- * FIXME: Does playing with the RP bit in c0_status interfere with this code?
+ * By default we provide the null RTC ops
  */
-static unsigned long do_fast_gettimeoffset(void)
+static unsigned long null_rtc_get_time(void)
 {
-	u32 count;
-	unsigned long res, tmp;
-
-	/* Last jiffy when do_fast_gettimeoffset() was called. */
-	static unsigned long last_jiffies;
-	unsigned long quotient;
+	return mktime(2000, 1, 1, 0, 0, 0);
+}
 
-	/*
-	 * Cached "1/(clocks per usec)*2^32" value.
-	 * It has to be recalculated once each jiffy.
-	 */
-	static unsigned long cached_quotient;
+static int null_rtc_set_time(unsigned long sec)
+{
+	return 0;
+}
 
-	tmp = jiffies;
+unsigned long (*rtc_get_time)(void) = null_rtc_get_time;
+int (*rtc_set_time)(unsigned long) = null_rtc_set_time;
 
-	quotient = cached_quotient;
 
-	if (tmp && last_jiffies != tmp) {
-		last_jiffies = tmp;
-		__asm__(".set\tnoreorder\n\t"
-			".set\tnoat\n\t"
-			".set\tmips3\n\t"
-			"lwu\t%0,%2\n\t"
-			"dsll32\t$1,%1,0\n\t"
-			"or\t$1,$1,%0\n\t"
-			"ddivu\t$0,$1,%3\n\t"
-			"mflo\t$1\n\t"
-			"dsll32\t%0,%4,0\n\t"
-			"nop\n\t"
-			"ddivu\t$0,%0,$1\n\t"
-			"mflo\t%0\n\t"
-			".set\tmips0\n\t"
-			".set\tat\n\t"
-			".set\treorder"
-			:"=&r" (quotient)
-			:"r" (timerhi),
-			 "m" (timerlo),
-			 "r" (tmp),
-			 "r" (USECS_PER_JIFFY)
-			:"$1");
-		cached_quotient = quotient;
-	}
+/*
+ * timeofday services, for syscalls.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+        unsigned long flags;
 
-	/* Get last timer tick in absolute kernel time */
-	count = read_32bit_cp0_register(CP0_COUNT);
+        read_lock_irqsave (&xtime_lock, flags);
+        *tv = xtime;
+        tv->tv_usec += do_gettimeoffset();
+
+        /*
+         * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
+         * is nonzero if the timer bottom half hasnt executed yet.
+         */
+        if (jiffies - wall_jiffies)
+                tv->tv_usec += USECS_PER_JIFFY;
+
+        read_unlock_irqrestore (&xtime_lock, flags);
+
+        if (tv->tv_usec >= 1000000) {
+                tv->tv_usec -= 1000000;
+                tv->tv_sec++;
+        }
+}
 
-	/* .. relative to previous jiffy (32 bits is enough) */
-	count -= timerlo;
-//printk("count: %08lx, %08lx:%08lx\n", count, timerhi, timerlo);
-
-	__asm__("multu\t%1,%2\n\t"
-		"mfhi\t%0"
-		:"=r" (res)
-		:"r" (count),
-		 "r" (quotient));
+void do_settimeofday(struct timeval *tv)
+{
+        write_lock_irq (&xtime_lock);
 
-	/*
- 	 * Due to possible jiffies inconsistencies, we need to check 
-	 * the result so that we'll get a timer that is monotonic.
-	 */
-	if (res >= USECS_PER_JIFFY)
-		res = USECS_PER_JIFFY-1;
+        /* This is revolting. We need to set the xtime.tv_usec
+         * correctly. However, the value in this location is
+         * is value at the last tick.
+         * Discover what correction gettimeofday
+         * would have done, and then undo it!
+         */
+        tv->tv_usec -= do_gettimeoffset();
+
+        if (tv->tv_usec < 0) {
+                tv->tv_usec += 1000000;
+                tv->tv_sec--;
+        }
+        xtime = *tv;
+        time_adjust = 0;                /* stop active adjtime() */
+        time_status |= STA_UNSYNC;
+        time_maxerror = NTP_PHASE_LIMIT;
+        time_esterror = NTP_PHASE_LIMIT;
 
-	return res;
+        write_unlock_irq (&xtime_lock);
 }
 
-/* This function must be called with interrupts disabled 
- * It was inspired by Steve McCanne's microtime-i386 for BSD.  -- jrs
- * 
- * However, the pc-audio speaker driver changes the divisor so that
- * it gets interrupted rather more often - it loads 64 into the
- * counter rather than 11932! This has an adverse impact on
- * do_gettimeoffset() -- it stops working! What is also not
- * good is that the interval that our timer function gets called
- * is no longer 10.0002 ms, but 9.9767 ms. To get around this
- * would require using a different timing source. Maybe someone
- * could use the RTC - I know that this can interrupt at frequencies
- * ranging from 8192Hz to 2Hz. If I had the energy, I'd somehow fix
- * it so that at startup, the timer code in sched.c would select
- * using either the RTC or the 8253 timer. The decision would be
- * based on whether there was any other device around that needed
- * to trample on the 8253. I'd set up the RTC to interrupt at 1024 Hz,
- * and then do some jiggery to have a version of do_timer that 
- * advanced the clock by 1/1024 s. Every time that reached over 1/100
- * of a second, then do all the old code. If the time was kept correct
- * then do_gettimeoffset could just return 0 - there is no low order
- * divider that can be accessed.
+
+/*
+ * Gettimeoffset routines.  These routines returns the time duration
+ * since last timer interrupt in usecs.
  *
- * Ideally, you would be able to use the RTC for the speaker driver,
- * but it appears that the speaker driver really needs interrupt more
- * often than every 120 us or so.
+ * If the exact CPU counter frequency is known, use fixed_rate_gettimeoffset.
+ * Otherwise use calibrate_gettimeoffset()
  *
- * Anyway, this needs more thought....		pjsg (1993-08-28)
- * 
- * If you are really that interested, you should be reading
- * comp.protocols.time.ntp!
+ * If the CPU does not have counter register all, you can either supply
+ * your own gettimeoffset() routine, or use null_gettimeoffset() routines,
+ * which gives the same resolution as HZ.
  */
 
-#define TICK_SIZE tick
 
-static unsigned long do_slow_gettimeoffset(void)
-{
-	int count;
+/* This is for machines which generate the exact clock. */
+#define USECS_PER_JIFFY (1000000/HZ)
 
-	static int count_p = LATCH;    /* for the first call after boot */
-	static unsigned long jiffies_p;
+/* usecs per counter cycle, shifted to left by 32 bits */
+static unsigned int sll32_usecs_per_cycle=0;
 
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off. 
-	 */
-	unsigned long jiffies_t;
+/* how many counter cycles in a jiffy */
+static unsigned long cycles_per_jiffy=0;
+
+/* Cycle counter value at the previous timer interrupt.. */
+static unsigned int timerhi, timerlo;
 
-	/* timer count may underflow right here */
-	outb_p(0x00, 0x43);	/* latch the count ASAP */
+/* last time when xtime and rtc are sync'ed up */
+static long last_rtc_update;
 
-	count = inb_p(0x40);	/* read the latched count */
+/* the function pointer to one of the gettimeoffset funcs*/
+unsigned long (*do_gettimeoffset)(void) = null_gettimeoffset;
 
-	/*
-	 * We do this guaranteed double memory access instead of a _p 
-	 * postfix in the previous port access. Wheee, hackady hack
-	 */
-	jiffies_t = jiffies;
+unsigned long null_gettimeoffset(void)
+{
+	return 0;
+}
 
-	count |= inb_p(0x40) << 8;
+unsigned long fixed_rate_gettimeoffset(void)
+{
+	u32 count;
+	unsigned long res;
 
-	/*
-	 * avoiding timer inconsistencies (they are rare, but they happen)...
-	 * there are two kinds of problems that must be avoided here:
-	 *  1. the timer counter underflows
-	 *  2. hardware problem with the timer, not giving us continuous time,
-	 *     the counter does small "jumps" upwards on some Pentium systems,
-	 *     (see c't 95/10 page 335 for Neptun bug.)
-	 */
+	MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER);
+	MIPS_ASSERT(mips_counter_frequency != 0);
+	MIPS_ASSERT(sll32_usecs_per_cycle != 0);
 
-	if( jiffies_t == jiffies_p ) {
-		if( count > count_p ) {
-			/* the nutcase */
-
-			outb_p(0x0A, 0x20);
-
-			/* assumption about timer being IRQ1 */
-			if (inb(0x20) & 0x01) {
-				/*
-				 * We cannot detect lost timer interrupts ... 
-				 * well, that's why we call them lost, don't we? :)
-				 * [hmm, on the Pentium and Alpha we can ... sort of]
-				 */
-				count -= LATCH;
-			} else {
-				printk("do_slow_gettimeoffset(): hardware timer problem?\n");
-			}
-		}
-	} else
-		jiffies_p = jiffies_t;
+	/* Get last timer tick in absolute kernel time */
+        count = read_32bit_cp0_register(CP0_COUNT);
 
-	count_p = count;
+        /* .. relative to previous jiffy (32 bits is enough) */
+        count -= timerlo;
 
-	count = ((LATCH-1) - count) * TICK_SIZE;
-	count = (count + LATCH/2) / LATCH;
+        __asm__("multu\t%1,%2\n\t"
+                "mfhi\t%0"
+                :"=r" (res)
+                :"r" (count),
+                 "r" (sll32_usecs_per_cycle));
+
+        /*
+         * Due to possible jiffies inconsistencies, we need to check
+         * the result so that we'll get a timer that is monotonic.
+         */
+        if (res >= USECS_PER_JIFFY)
+                res = USECS_PER_JIFFY-1;
 
-	return count;
+        return res;
 }
 
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-
 /*
- * This version of gettimeofday has near microsecond resolution.
+ * Cached "1/(clocks per usec)*2^32" value.
+ * It has to be recalculated once each jiffy.
  */
-void do_gettimeofday(struct timeval *tv)
-{
-	unsigned long flags;
+static unsigned long cached_quotient;
 
-	read_lock_irqsave (&xtime_lock, flags);
-	*tv = xtime;
-	tv->tv_usec += do_gettimeoffset();
+/* Last jiffy when calibrate_divXX_gettimeoffset() was called. */
+static unsigned long last_jiffies = 0;
 
-	/*
-	 * xtime is atomically updated in timer_bh. jiffies - wall_jiffies
-	 * is nonzero if the timer bottom half hasnt executed yet.
-	 */
-	if (jiffies - wall_jiffies)
-		tv->tv_usec += USECS_PER_JIFFY;
+/* 
+ * copied from include/asm/div64.  
+ * We do the copy instead of include the header file because we don't
+ * want to reply on _MIPS_ISA value.
+ */
+#define do_div64_32(res, high, low, base) ({ \
+        unsigned long __quot, __mod; \
+        unsigned long __cf, __tmp, __i; \
+        \
+        __asm__(".set   push\n\t" \
+                ".set   noat\n\t" \
+                ".set   noreorder\n\t" \
+                "b      1f\n\t" \
+                " li    %4,0x21\n" \
+                "0:\n\t" \
+                "sll    $1,%0,0x1\n\t" \
+                "srl    %3,%0,0x1f\n\t" \
+                "or     %0,$1,$2\n\t" \
+                "sll    %1,%1,0x1\n\t" \
+                "sll    %2,%2,0x1\n" \
+                "1:\n\t" \
+                "bnez   %3,2f\n\t" \
+                "sltu   $2,%0,%z5\n\t" \
+                "bnez   $2,3f\n\t" \
+                "2:\n\t" \
+                " addiu %4,%4,-1\n\t" \
+                "subu   %0,%0,%z5\n\t" \
+                "addiu  %2,%2,1\n" \
+                "3:\n\t" \
+                "bnez   %4,0b\n\t" \
+                " srl   $2,%1,0x1f\n\t" \
+                ".set   pop" \
+                : "=&r" (__mod), "=&r" (__tmp), "=&r" (__quot), "=&r" (__cf), \
+                  "=&r" (__i) \
+                : "Jr" (base), "0" (high), "1" (low), "2" (0), "3" (0) \
+                /* Aarrgh!  Ran out of gcc's limit on constraints... */ \
+                : "$1", "$2"); \
+        \
+        (res) = __quot; \
+        __mod; })
 
-	read_unlock_irqrestore (&xtime_lock, flags);
+/*
+ * This is copied from dec/time.c:do_ioasic_gettimeoffset() by Mercij.
+ */
+unsigned long calibrate_div32_gettimeoffset(void)
+{
+        u32 count;
+        unsigned long res, tmp;
+        unsigned long quotient;
+
+	MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER);
+
+        tmp = jiffies;
+
+        quotient = cached_quotient;
+
+        if (last_jiffies != tmp) {
+                last_jiffies = tmp;
+                if (last_jiffies != 0) {
+                        unsigned long r0;
+                        do_div64_32(r0, timerhi, timerlo, tmp);
+                        do_div64_32(quotient, USECS_PER_JIFFY,
+                                    USECS_PER_JIFFY_FRAC, r0);
+                        cached_quotient = quotient;
+                }
+        }
+
+        /* Get last timer tick in absolute kernel time */
+        count = read_32bit_cp0_register(CP0_COUNT);
+
+        /* .. relative to previous jiffy (32 bits is enough) */
+        count -= timerlo;
+
+        __asm__("multu  %2,%3"
+                : "=l" (tmp), "=h" (res)
+                : "r" (count), "r" (quotient));
+
+        /*
+         * Due to possible jiffies inconsistencies, we need to check
+         * the result so that we'll get a timer that is monotonic.
+         */
+        if (res >= USECS_PER_JIFFY)
+                res = USECS_PER_JIFFY - 1;
 
-	if (tv->tv_usec >= 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
-	}
+        return res;
 }
 
-void do_settimeofday(struct timeval *tv)
+unsigned long calibrate_div64_gettimeoffset(void)
 {
-	write_lock_irq (&xtime_lock);
-	/* This is revolting. We need to set the xtime.tv_usec
-	 * correctly. However, the value in this location is
-	 * is value at the last tick.
-	 * Discover what correction gettimeofday
-	 * would have done, and then undo it!
-	 */
-	tv->tv_usec -= do_gettimeoffset();
-
-	if (tv->tv_usec < 0) {
-		tv->tv_usec += 1000000;
-		tv->tv_sec--;
-	}
+        u32 count;
+        unsigned long res, tmp;
+        unsigned long quotient;
+
+
+	MIPS_ASSERT(mips_cpu.options & MIPS_CPU_COUNTER);
+	MIPS_ASSERT((mips_cpu.isa_level != MIPS_CPU_ISA_I) &&
+		    (mips_cpu.isa_level != MIPS_CPU_ISA_II) &&
+		    (mips_cpu.isa_level != MIPS_CPU_ISA_M32));
+
+
+        tmp = jiffies;
+
+        quotient = cached_quotient;
+
+        if (tmp && last_jiffies != tmp) {
+                last_jiffies = tmp;
+                __asm__(".set\tnoreorder\n\t"
+                        ".set\tnoat\n\t"
+                        ".set\tmips3\n\t"
+                        "lwu\t%0,%2\n\t"
+                        "dsll32\t$1,%1,0\n\t"
+                        "or\t$1,$1,%0\n\t"
+                        "ddivu\t$0,$1,%3\n\t"
+                        "mflo\t$1\n\t"
+                        "dsll32\t%0,%4,0\n\t"
+                        "nop\n\t"
+                        "ddivu\t$0,%0,$1\n\t"
+                        "mflo\t%0\n\t"
+                        ".set\tmips0\n\t"
+                        ".set\tat\n\t"
+                        ".set\treorder"
+                        :"=&r" (quotient)
+                        :"r" (timerhi),
+                         "m" (timerlo),
+                         "r" (tmp),
+                         "r" (USECS_PER_JIFFY)
+                        :"$1");
+                cached_quotient = quotient;
+        }
+
+        /* Get last timer tick in absolute kernel time */
+        count = read_32bit_cp0_register(CP0_COUNT);
+
+        /* .. relative to previous jiffy (32 bits is enough) */
+        count -= timerlo;
+
+        __asm__("multu\t%1,%2\n\t"
+                "mfhi\t%0"
+                :"=r" (res)
+                :"r" (count),
+                 "r" (quotient));
+
+        /*
+         * Due to possible jiffies inconsistencies, we need to check
+         * the result so that we'll get a timer that is monotonic.
+         */
+        if (res >= USECS_PER_JIFFY)
+                res = USECS_PER_JIFFY-1;
 
-	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);
+        return res;
 }
 
+
 /*
- * In order to set the CMOS clock precisely, set_rtc_mmss has to be
- * called 500 ms after the second nowtime has started, because when
- * nowtime is written into the registers of the CMOS clock, it will
- * jump to the next second precisely 500 ms later. Check the Motorola
- * MC146818A or Dallas DS12887 data sheet for details.
- *
- * BUG: This routine does not handle hour overflow properly; it just
- *      sets the minutes. Usually you won't notice until after reboot!
+ * high-level timer interrupt service routines.  This function
+ * is set as irqaction->handler and is invoked through do_IRQ.
  */
-static int set_rtc_mmss(unsigned long nowtime)
+void timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	int retval = 0;
-	int real_seconds, real_minutes, cmos_minutes;
-	unsigned char save_control, save_freq_select;
-
-	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
-	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+	if (mips_cpu.options & MIPS_CPU_COUNTER) {
+		unsigned int count;
 
-	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
-	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+		/*
+		 * The cycle counter is only 32 bit which is good for about
+		 * a minute at current count rates of upto 150MHz or so.
+		 */
+		count = read_32bit_cp0_register(CP0_COUNT);
+		timerhi += (count < timerlo);   /* Wrap around */
+		timerlo = count;
 
-	cmos_minutes = CMOS_READ(RTC_MINUTES);
-	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-		BCD_TO_BIN(cmos_minutes);
+		/*
+		 * set up for next timer interrupt - no harm if the machine
+		 * is using another timer interrupt source.
+		 * Note that writing to COMPARE register clears the interrupt
+		 */
+		write_32bit_cp0_register (CP0_COMPARE,
+					  count + cycles_per_jiffy);
 
-	/*
-	 * since we're only adjusting minutes and seconds,
-	 * don't interfere with hour overflow. This avoids
-	 * messing with unknown time zones but requires your
-	 * RTC not to be off by more than 15 minutes
-	 */
-	real_seconds = nowtime % 60;
-	real_minutes = nowtime / 60;
-	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
-		real_minutes += 30;		/* correct for half hour time zone */
-	real_minutes %= 60;
-
-	if (abs(real_minutes - cmos_minutes) < 30) {
-		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
-			BIN_TO_BCD(real_seconds);
-			BIN_TO_BCD(real_minutes);
-		}
-		CMOS_WRITE(real_seconds,RTC_SECONDS);
-		CMOS_WRITE(real_minutes,RTC_MINUTES);
-	} else {
-		printk(KERN_WARNING
-		       "set_rtc_mmss: can't update from %d to %d\n",
-		       cmos_minutes, real_minutes);
- 		retval = -1;
 	}
 
-	/* The following flags have to be released exactly in this order,
-	 * otherwise the DS12887 (popular MC146818A clone with integrated
-	 * battery and quartz) will not reset the oscillator and will not
-	 * update precisely 500 ms later. You won't find this mentioned in
-	 * the Dallas Semiconductor data sheets, but who believes data
-	 * sheets anyway ...                           -- Markus Kuhn
-	 */
-	CMOS_WRITE(save_control, RTC_CONTROL);
-	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
-
-	return retval;
-}
-
-/* last time the cmos clock got updated */
-static long last_rtc_update;
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static void inline
-timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-#ifdef CONFIG_DDB5074
-	static unsigned cnt, period, dist;
-
-	if (cnt == 0 || cnt == dist)
-	    ddb5074_led_d2(1);
-	else if (cnt == 7 || cnt == dist+7)
-	    ddb5074_led_d2(0);
-	
-	if (++cnt > period) {
-	    cnt = 0;
-	    /* The hyperbolic function below modifies the heartbeat period
-	     * length in dependency of the current (5min) load. It goes
-	     * through the points f(0)=126, f(1)=86, f(5)=51,
-	     * f(inf)->30. */
-	     period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-	     dist = period / 4;
-	}
-#endif
-	if(!user_mode(regs)) {
+        if(!user_mode(regs)) {
 		if (prof_buffer && current->pid) {
-			extern int _stext;
-			unsigned long pc = regs->cp0_epc;
+                        extern int _stext;
+                        unsigned long pc = regs->cp0_epc;
 
-			pc -= (unsigned long) &_stext;
-			pc >>= prof_shift;
-			/*
-			 * Dont ignore out-of-bounds pc values silently,
-			 * put them into the last histogram slot, so if
-			 * present, they will show up as a sharp peak.
-			 */
-			if (pc > prof_len-1)
-				pc = prof_len-1;
-			atomic_inc((atomic_t *)&prof_buffer[pc]);
-		}
-	}
-	do_timer(regs);
+                        pc -= (unsigned long) &_stext;
+                        pc >>= prof_shift;
+                        /*
+                         * Dont ignore out-of-bounds pc values silently,
+                         * put them into the last histogram slot, so if
+                         * present, they will show up as a sharp peak.
+                         */
+                        if (pc > prof_len-1)
+                                pc = prof_len-1;
+                        atomic_inc((atomic_t *)&prof_buffer[pc]);
+                }
+        }
 
 	/*
-	 * If we have an externally synchronized Linux clock, then update
-	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
-	 * called as close as possible to 500 ms before the new second starts.
+	 * call the generic timer interrupt handling
 	 */
-	read_lock (&xtime_lock); 
-	if ((time_status & STA_UNSYNC) == 0 &&
-	    xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
-	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
-	  if (set_rtc_mmss(xtime.tv_sec) == 0)
-	    last_rtc_update = xtime.tv_sec;
-	  else
-	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
-	}
-	/* As we return to user mode fire off the other CPU schedulers.. this is 
-	   basically because we don't yet share IRQ's around. This message is
-	   rigged to be safe on the 386 - basically it's a hack, so don't look
-	   closely for now.. */
-	/*smp_message_pass(MSG_ALL_BUT_SELF, MSG_RESCHEDULE, 0L, 0); */
-	read_unlock (&xtime_lock); 
-}
+        do_timer(regs);
 
-static inline void 
-r4k_timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
-	unsigned int count;
+        /*
+         * If we have an externally synchronized Linux clock, then update
+         * CMOS clock accordingly every ~11 minutes. rtc_set_time() has to be
+         * called as close as possible to 500 ms before the new second starts.
+         */
+        read_lock (&xtime_lock);
+        if ((time_status & STA_UNSYNC) == 0 &&
+            xtime.tv_sec > last_rtc_update + 660 &&
+            xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+            xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
+
+		if (rtc_set_time(xtime.tv_sec) == 0) {
+			last_rtc_update = xtime.tv_sec;
+		} else {
+			last_rtc_update = xtime.tv_sec - 600; 
+			/* do it again in 60 s */
+		}
+        }
+        read_unlock (&xtime_lock);
 
 	/*
-	 * The cycle counter is only 32 bit which is good for about
-	 * a minute at current count rates of upto 150MHz or so.
-	 */
-	count = read_32bit_cp0_register(CP0_COUNT);
-	timerhi += (count < timerlo);	/* Wrap around */
-	timerlo = count;
-
-#ifdef CONFIG_SGI_IP22
-	/* Since we don't get anything but r4k timer interrupts, we need to
-	 * set this up so that we'll get one next time. Fortunately since we
-	 * have timerhi/timerlo, we don't care so much if we miss one. So
-	 * we need only ask for the next in r4k_interval counts. On other
-	 * archs we have a real timer, so we don't want this.
-	 */
-	write_32bit_cp0_register (CP0_COMPARE, 
-				  (unsigned long) (count + r4k_interval));
-        kstat.irqs[0][irq]++;
-#endif
-
-	timer_interrupt(irq, dev_id, regs);
-
-	if (!jiffies)
-	{
-		/*
-		 * If jiffies has overflowed in this timer_interrupt we must
-		 * update the timer[hi]/[lo] to make do_fast_gettimeoffset()
-		 * quotient calc still valid. -arca
-		 */
-		timerhi = timerlo = 0;
-	}
+	 * If jiffies has overflowed in this timer_interrupt we must
+	 * update the timer[hi]/[lo] to make fast gettimeoffset funcs
+	 * quotient calc still valid. -arca
+	 */
+        if (!jiffies) {
+                timerhi = timerlo = 0;
+        }
 }
 
-void indy_r4k_timer_interrupt (struct pt_regs *regs)
+asmlinkage void ll_timer_interrupt(int irq, struct pt_regs *regs)
 {
-	static const int INDY_R4K_TIMER_IRQ = 7;
-	r4k_timer_interrupt (INDY_R4K_TIMER_IRQ, NULL, regs);
-}
+	int cpu = smp_processor_id();
 
-char cyclecounter_available;
+	irq_enter(cpu, irq);
+	kstat.irqs[cpu][irq]++;
 
-static inline void init_cycle_counter(void)
-{
-	switch(mips_cputype) {
-	case CPU_UNKNOWN:
-	case CPU_R2000:
-	case CPU_R3000:
-	case CPU_R3000A:
-	case CPU_R3041:
-	case CPU_R3051:
-	case CPU_R3052:
-	case CPU_R3081:
-	case CPU_R3081E:
-	case CPU_R6000:
-	case CPU_R6000A:
-	case CPU_R8000:		/* Not shure about that one, play safe */
-		cyclecounter_available = 0;
-		break;
-	case CPU_R4000PC:
-	case CPU_R4000SC:
-	case CPU_R4000MC:
-	case CPU_R4200:
-	case CPU_R4400PC:
-	case CPU_R4400SC:
-	case CPU_R4400MC:
-	case CPU_R4600:
-	case CPU_R10000:
-	case CPU_R4300:
-	case CPU_R4650:
-	case CPU_R4700:
-	case CPU_R5000:
-	case CPU_R5000A:
-	case CPU_R4640:
-	case CPU_NEVADA:
-		cyclecounter_available = 1;
-		break;
-	}
-}
+	/* we keep interrupt disabled all the time */
+	timer_interrupt(irq, NULL, regs);
+	
+	irq_exit(cpu, irq);
 
-struct irqaction irq0  = { timer_interrupt, SA_INTERRUPT, 0,
-                                  "timer", NULL, NULL};
+	/* check for bottom half */
+        if (softirq_active(cpu)&softirq_mask(cpu))
+                do_softirq();
+}
 
 
-void (*board_time_init)(struct irqaction *irq);
+/*
+ * time_init() - it does the following things.
+ *
+ * 1) board_time_init() - 
+ * 	a) (optional) set up RTC routines, 
+ *      b) (optional) calibrate and set the mips_counter_frequency
+ *	    (only needed if you intended to use fixed_rate_gettimeoffset
+ *	     or use cpu counter as timer interrupt source)
+ * 2) setup xtime based on rtc_get_time().
+ * 3) choose a appropriate gettimeoffset routine.
+ * 4) calculate a couple of cached variables for later usage
+ * 5) board_timer_setup() - 
+ *	a) (optional) over-write any choices made above by time_init().
+ *	b) machine specific code should setup the timer irqaction.
+ *	c) enable the timer interrupt
+ */ 
+
+void (*board_time_init)(void) = NULL;
+void (*board_timer_setup)(struct irqaction *irq) = NULL;
+
+unsigned int mips_counter_frequency = 0;
+
+static struct irqaction timer_irqaction = {
+	timer_interrupt,
+	SA_INTERRUPT,
+	0,
+	"timer",
+	NULL,
+	NULL};
 
 void __init time_init(void)
 {
-	unsigned int epoch = 0, year, mon, day, hour, min, sec;
-	int i;
+	printk("New MIPS time_init() invoked.\n");
 
-	/* The Linux interpretation of the CMOS clock register contents:
-	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
-	 * RTC registers show the second which has precisely just started.
-	 * Let's hope other operating systems interpret the RTC the same way.
-	 */
-	/* read RTC exactly on falling edge of update flag */
-	for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
-		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
-			break;
-	for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
-		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
-			break;
-	do { /* Isn't this overkill ? UIP above should guarantee consistency */
-		sec = CMOS_READ(RTC_SECONDS);
-		min = CMOS_READ(RTC_MINUTES);
-		hour = CMOS_READ(RTC_HOURS);
-		day = CMOS_READ(RTC_DAY_OF_MONTH);
-		mon = CMOS_READ(RTC_MONTH);
-		year = CMOS_READ(RTC_YEAR);
-	} while (sec != CMOS_READ(RTC_SECONDS));
-	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
-	  {
-	    BCD_TO_BIN(sec);
-	    BCD_TO_BIN(min);
-	    BCD_TO_BIN(hour);
-	    BCD_TO_BIN(day);
-	    BCD_TO_BIN(mon);
-	    BCD_TO_BIN(year);
-	  }
-
-	/* Attempt to guess the epoch.  This is the same heuristic as in rtc.c so
-	   no stupid things will happen to timekeeping.  Who knows, maybe Ultrix
-  	   also uses 1952 as epoch ...  */
-	if (year > 10 && year < 44) {
-		epoch = 1980;
-	} else if (year < 96) {
-		epoch = 1952;
-	}
-	year += epoch;
+	if (board_time_init)
+		board_time_init();
 
-	write_lock_irq (&xtime_lock);
-	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
+	/* setup xtime */
+	write_lock_irq(&xtime_lock);
+	xtime.tv_sec = rtc_get_time();
 	xtime.tv_usec = 0;
-	write_unlock_irq (&xtime_lock);
-
-	init_cycle_counter();
+	write_unlock_irq(&xtime_lock);
 
-	if (cyclecounter_available) {
-		write_32bit_cp0_register(CP0_COUNT, 0);
-		do_gettimeoffset = do_fast_gettimeoffset;
-		irq0.handler = r4k_timer_interrupt;
-	}
-
-	board_time_init(&irq0);
+	/* choose appropriate gettimeoffset routine */
+	if ( ! (mips_cpu.options & MIPS_CPU_COUNTER) ) {
+		/* no cpu counter - sorry */
+		do_gettimeoffset = null_gettimeoffset;
+	} else if (mips_counter_frequency != 0) {
+		/* we have cpu counter and know counter frequency! */
+		do_gettimeoffset = fixed_rate_gettimeoffset;
+	} else if ((mips_cpu.isa_level == MIPS_CPU_ISA_M32) ||
+		   (mips_cpu.isa_level == MIPS_CPU_ISA_I) ||
+		   (mips_cpu.isa_level == MIPS_CPU_ISA_II) ) {
+		/* we need to calibrate the counter but we don't have
+		 * 64-bit division. */
+		do_gettimeoffset = calibrate_div32_gettimeoffset;
+	} else {
+		/* we need to calibrate the counter but we *do* have
+		 * 64-bit division. */
+		do_gettimeoffset = calibrate_div64_gettimeoffset;
+	}	
+
+	/* caclulate cache parameters */
+	if (mips_counter_frequency) {
+		cycles_per_jiffy = mips_counter_frequency / HZ;
+
+		/* sll32_usecs_per_cycle = 10^6 * 2^32 / mips_counter_freq */
+		/* any better way to do this? */
+		sll32_usecs_per_cycle = mips_counter_frequency / 100000;
+		sll32_usecs_per_cycle = 0xffffffff / sll32_usecs_per_cycle;
+		sll32_usecs_per_cycle *= 10;
+
+		MIPS_DEBUG(printk("cycles_per_jiffy = %d\n", 
+				  cycles_per_jiffy));
+		MIPS_DEBUG(printk("sll32_usecs_per_cycle = %d \n",
+				  sll32_usecs_per_cycle));
+	}
+
+	/* 
+	 * Call board specific timer interrupt setup.
+	 *
+	 * this pointer must be setup in machine setup routine. 
+	 *
+	 * Even if the machine choose to use low-level timer interrupt,
+	 * it still needs to setup the timer_irqaction.
+	 * In that case, it might be better to set timer_irqaction.handler 
+	 * to be NULL function so that we are sure the high-level code
+	 * is not invoked accidentally.
+	 */
+	MIPS_ASSERT(board_timer_setup != NULL);
+	board_timer_setup(&timer_irqaction);
 }
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/traps.c linux/arch/mips/kernel/traps.c
--- v2.4.5/linux/arch/mips/kernel/traps.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/kernel/traps.c	Mon Jul  2 13:56:40 2001
@@ -32,6 +32,9 @@
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
+#ifndef CONFIG_MIPS_FPU_EMULATOR 
+#include <asm/inst.h>
+#endif
 
 /*
  * Machine specific interrupt handlers
@@ -90,9 +93,9 @@
 #define RT     0x001f0000
 #define OFFSET 0x0000ffff
 #define LL     0xc0000000
-#define SC     0xd0000000
+#define SC     0xe0000000
 
-#define DEBUG_LLSC
+#undef DEBUG_LLSC
 #endif
 
 /*
@@ -268,9 +271,6 @@
 	/*
 	 * Assume it would be too dangerous to continue ...
 	 */
-/* XXX */
-printk("Got Bus Error at %08x\n", (unsigned int)regs->cp0_epc);
-show_regs(regs); while(1);
 	force_sig(SIGBUS, current);
 }
 
@@ -410,7 +410,7 @@
 
 	epc = (unsigned int *) (unsigned long) regs->cp0_epc;
 	if (regs->cp0_cause & CAUSEF_BD)
-		epc += 4;
+		epc++;
 
 	if (verify_area(VERIFY_READ, epc, 4)) {
 		force_sig(SIGSEGV, current);
@@ -423,6 +423,7 @@
 
 void do_bp(struct pt_regs *regs)
 {
+	siginfo_t info;
 	unsigned int opcode, bcode;
 
 	/*
@@ -491,48 +492,69 @@
 
 #if !defined(CONFIG_CPU_HAS_LLSC)
 
+#ifdef CONFIG_SMP
+#error "ll/sc emulation is not SMP safe"
+#endif
+
 /*
  * userland emulation for R2300 CPUs
  * needed for the multithreading part of glibc
+ *
+ * this implementation can handle only sychronization between 2 or more
+ * user contexts and is not SMP safe.
  */
 void do_ri(struct pt_regs *regs)
 {
 	unsigned int opcode;
 
+	if (!user_mode(regs))
+		BUG();
+
 	if (!get_insn_opcode(regs, &opcode)) {
-		if ((opcode & OPCODE) == LL)
+		if ((opcode & OPCODE) == LL) {
 			simulate_ll(regs, opcode);
-		if ((opcode & OPCODE) == SC)
+			return;
+		}
+		if ((opcode & OPCODE) == SC) {
 			simulate_sc(regs, opcode);
-	} else {
-	printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
-	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+			return;
+		}
 	}
+	printk("[%s:%d] Illegal instruction %08lx at %08lx, ra=%08lx, CP0_STATUS=%08lx\n",
+	       current->comm, current->pid, *((unsigned long*)regs->cp0_epc), regs->cp0_epc,
+		regs->regs[31], regs->cp0_status);
 	if (compute_return_epc(regs))
 		return;
 	force_sig(SIGILL, current);
 }
 
 /*
- * the ll_bit will be cleared by r2300_switch.S
+ * The ll_bit is cleared by r*_switch.S
  */
-unsigned long ll_bit, *lladdr;
- 
+
+unsigned long ll_bit;
+#ifdef CONFIG_PROC_FS
+extern unsigned long ll_ops;
+extern unsigned long sc_ops;
+#endif
+
+static struct task_struct *ll_task = NULL;
+
 void simulate_ll(struct pt_regs *regp, unsigned int opcode)
 {
-	unsigned long *addr, *vaddr;
+	unsigned long value, *vaddr;
 	long offset;
- 
+	int signal = 0;
+
 	/*
 	 * analyse the ll instruction that just caused a ri exception
 	 * and put the referenced address to addr.
 	 */
+
 	/* sign extend offset */
 	offset = opcode & OFFSET;
-	if (offset & 0x00008000)
-		offset = -(offset & 0x00007fff);
-	else
-		offset = (offset & 0x00007fff);
+	offset <<= 16;
+	offset >>= 16;
 
 	vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
 
@@ -540,31 +562,44 @@
 	printk("ll: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (opcode & RT) >> 16);
 #endif
 
-	/*
-	 * TODO: compute physical address from vaddr
-	 */
-	panic("ll: emulation not yet finished!");
+#ifdef CONFIG_PROC_FS
+	ll_ops++;
+#endif
 
-	lladdr = addr;
-	ll_bit = 1;
-	regp->regs[(opcode & RT) >> 16] = *addr;
+	if ((unsigned long)vaddr & 3)
+		signal = SIGBUS;
+	else if (get_user(value, vaddr))
+		signal = SIGSEGV;
+	else {
+		if (ll_task == NULL || ll_task == current) {
+			ll_bit = 1;
+		} else {
+			ll_bit = 0;
+		}
+		ll_task = current;
+		regp->regs[(opcode & RT) >> 16] = value;
+	}
+	if (compute_return_epc(regp))
+		return;
+	if (signal)
+		send_sig(signal, current, 1);
 }
- 
+
 void simulate_sc(struct pt_regs *regp, unsigned int opcode)
 {
-	unsigned long *addr, *vaddr, reg;
+	unsigned long *vaddr, reg;
 	long offset;
+	int signal = 0;
 
 	/*
 	 * analyse the sc instruction that just caused a ri exception
 	 * and put the referenced address to addr.
 	 */
+
 	/* sign extend offset */
 	offset = opcode & OFFSET;
-	if (offset & 0x00008000)
-		offset = -(offset & 0x00007fff);
-	else
-		offset = (offset & 0x00007fff);
+	offset <<= 16;
+	offset >>= 16;
 
 	vaddr = (unsigned long *)((long)(regp->regs[(opcode & BASE) >> 21]) + offset);
 	reg = (opcode & RT) >> 16;
@@ -573,28 +608,34 @@
 	printk("sc: vaddr = 0x%08x, reg = %d\n", (unsigned int)vaddr, (unsigned int)reg);
 #endif
 
-	/*
-	 * TODO: compute physical address from vaddr
-	 */
-	panic("sc: emulation not yet finished!");
-
-	lladdr = addr;
+#ifdef CONFIG_PROC_FS
+	sc_ops++;
+#endif
 
-	if (ll_bit == 0) {
+	if ((unsigned long)vaddr & 3)
+		signal = SIGBUS;
+	else if (ll_bit == 0 || ll_task != current)
 		regp->regs[reg] = 0;
+	else if (put_user(regp->regs[reg], vaddr))
+		signal = SIGSEGV;
+	else
+		regp->regs[reg] = 1;
+	if (compute_return_epc(regp))
 		return;
-	}
-
-	*addr = regp->regs[reg];
-	regp->regs[reg] = 1;
+	if (signal)
+		send_sig(signal, current, 1);
 }
 
 #else /* MIPS 2 or higher */
 
 void do_ri(struct pt_regs *regs)
 {
-	printk("[%s:%d] Illegal instruction at %08lx ra=%08lx\n",
-	       current->comm, current->pid, regs->cp0_epc, regs->regs[31]);
+	unsigned int opcode;
+
+        get_insn_opcode(regs, &opcode);
+	printk("[%s:%ld] Illegal instruction %08x at %08lx ra=%08lx\n",
+	       current->comm, (unsigned long)current->pid, opcode,
+	       regs->cp0_epc, regs->regs[31]);
 	if (compute_return_epc(regs))
 		return;
 	force_sig(SIGILL, current);
@@ -662,50 +703,101 @@
 	panic("Caught WATCH exception - probably caused by stack overflow.");
 }
 
+void do_mcheck(struct pt_regs *regs)
+{
+	show_regs(regs);
+	panic("Caught Machine Check exception - probably caused by multiple "
+	      "matching entries in the TLB.");
+}
+
 void do_reserved(struct pt_regs *regs)
 {
 	/*
-	 * Game over - no way to handle this if it ever occurs.
-	 * Most probably caused by a new unknown cpu type or
-	 * after another deadly hard/software error.
+	 * Game over - no way to handle this if it ever occurs.  Most probably
+	 * caused by a new unknown cpu type or after another deadly
+	 * hard/software error.
 	 */
+	show_regs(regs);
 	panic("Caught reserved exception - should not happen.");
 }
 
-static inline void watch_init(unsigned long cputype)
+static inline void watch_init(void)
 {
-	switch(cputype) {
-	case CPU_R10000:
-	case CPU_R4000MC:
-	case CPU_R4400MC:
-	case CPU_R4000SC:
-	case CPU_R4400SC:
-	case CPU_R4000PC:
-	case CPU_R4400PC:
-	case CPU_R4200:
-	case CPU_R4300:
-		set_except_vector(23, handle_watch);
-		watch_available = 1;
-		break;
-	}
+        if(mips_cpu.options & MIPS_CPU_WATCH ) {
+		(void)set_except_vector(23, handle_watch);
+ 		watch_available = 1;
+ 	}
 }
 
 /*
  * Some MIPS CPUs have a dedicated interrupt vector which reduces the
  * interrupt processing overhead.  Use it where available.
- * FIXME: more CPUs than just the Nevada have this feature.
  */
 static inline void setup_dedicated_int(void)
 {
 	extern void except_vec4(void);
-	switch(mips_cputype) {
-	case CPU_NEVADA:
+
+	if(mips_cpu.options & MIPS_CPU_DIVEC) {
 		memcpy((void *)(KSEG0 + 0x200), except_vec4, 8);
-		set_cp0_cause(CAUSEF_IV, CAUSEF_IV);
+		set_cp0_cause(CAUSEF_IV);
 		dedicated_iv_available = 1;
 	}
 }
 
+/*
+ * Some MIPS CPUs can enable/disable for cache parity detection, but does
+ * it different ways.
+ */
+static inline void parity_protection_init(void)
+{
+	switch(mips_cpu.cputype) {
+	case CPU_5KC:
+		/* Set the PE bit (bit 31) in the CP0_ECC register. */
+		printk(KERN_INFO "Enable the cache parity protection for "
+		       "MIPS 5KC CPUs.\n");
+		write_32bit_cp0_register(CP0_ECC,
+		                         read_32bit_cp0_register(CP0_ECC)
+		                         | 0x80000000); 
+		break;
+	default:
+		break;
+	}
+}
+
+void cache_parity_error(void)
+{
+        unsigned int reg_val;
+
+        /* For the moment, report the problem and hang. */
+        reg_val = read_32bit_cp0_register(CP0_ERROREPC);
+	printk("Cache error exception:\n");
+	printk("cp0_errorepc == %08x\n", reg_val);
+	reg_val = read_32bit_cp0_register(CP0_CACHEERR);
+	printk("cp0_cacheerr == %08x\n", reg_val);
+
+	printk("Decoded CP0_CACHEERR: %s cache fault in %s reference.\n",
+	       reg_val&(1<<30)?"secondary":"primary",
+	       reg_val&(1<<31)?"data":"insn");
+	printk("Error bits: %s%s%s%s%s%s%s\n",
+	       reg_val&(1<<29)?"ED ":"",
+	       reg_val&(1<<28)?"ET ":"",
+	       reg_val&(1<<26)?"EE ":"",
+	       reg_val&(1<<25)?"EB ":"",
+	       reg_val&(1<<24)?"EI ":"",
+	       reg_val&(1<<23)?"E1 ":"",
+	       reg_val&(1<<22)?"E0 ":"");
+	printk("IDX: 0x%08x\n", reg_val&((1<<22)-1));
+
+	if (reg_val&(1<<22))
+		printk("DErrAddr0: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR0));
+
+	if (reg_val&(1<<23))
+		printk("DErrAddr1: 0x%08x\n", read_32bit_cp0_set1_register(CP0_S1_DERRADDR1));
+
+
+	panic("Can't handle the cache error - panic!");
+}
+
 unsigned long exception_handlers[32];
 
 /*
@@ -713,23 +805,36 @@
  * to interrupt handlers in the address range from
  * KSEG0 <= x < KSEG0 + 256mb on the Nevada.  Oh well ...
  */
-void set_except_vector(int n, void *addr)
+void *set_except_vector(int n, void *addr)
 {
 	unsigned handler = (unsigned long) addr;
+	unsigned old_handler = exception_handlers[n];
 	exception_handlers[n] = handler;
 	if (n == 0 && dedicated_iv_available) {
 		*(volatile u32 *)(KSEG0+0x200) = 0x08000000 |
 		                                 (0x03ffffff & (handler >> 2));
 		flush_icache_range(KSEG0+0x200, KSEG0 + 0x204);
 	}
+	return (void *)old_handler;
 }
 
+asmlinkage int (*save_fp_context)(struct sigcontext *sc);
+asmlinkage int (*restore_fp_context)(struct sigcontext *sc);
+extern asmlinkage int _save_fp_context(struct sigcontext *sc);
+extern asmlinkage int _restore_fp_context(struct sigcontext *sc);
+
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+extern asmlinkage int fpu_emulator_save_context(struct sigcontext *sc);
+extern asmlinkage int fpu_emulator_restore_context(struct sigcontext *sc);
+#endif
+
 void __init trap_init(void)
 {
 	extern char except_vec0_nevada, except_vec0_r4000;
 	extern char except_vec0_r4600, except_vec0_r2300;
 	extern char except_vec1_generic, except_vec2_generic;
 	extern char except_vec3_generic, except_vec3_r4000;
+	extern char except_vec_ejtag_debug;
 	unsigned long i;
 
 	if(mips_machtype == MACH_MIPS_MAGNUM_4000 ||
@@ -737,101 +842,121 @@
 		EISA_bus = 1;
 
 	/* Some firmware leaves the BEV flag set, clear it.  */
-	set_cp0_status(ST0_BEV, 0);
+	clear_cp0_status(ST0_BEV);
 
 	/* Copy the generic exception handler code to it's final destination. */
 	memcpy((void *)(KSEG0 + 0x80), &except_vec1_generic, 0x80);
 	memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic, 0x80);
 	memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic, 0x80);
-
+	flush_icache_range(KSEG0 + 0x80, KSEG0 + 0x200);
 	/*
 	 * Setup default vectors
 	 */
 	for(i = 0; i <= 31; i++)
-		set_except_vector(i, handle_reserved);
+		(void)set_except_vector(i, handle_reserved);
+
+	/* 
+	 * Copy the EJTAG debug exception vector handler code to it's final 
+	 * destination.
+	 */
+	memcpy((void *)(KSEG0 + 0x300), &except_vec_ejtag_debug, 0x80);
 
 	/*
 	 * Only some CPUs have the watch exceptions or a dedicated
 	 * interrupt vector.
 	 */
-	watch_init(mips_cputype);
+	watch_init();
 	setup_dedicated_int();
 
-	set_except_vector(1, handle_mod);
-	set_except_vector(2, handle_tlbl);
-	set_except_vector(3, handle_tlbs);
-	set_except_vector(4, handle_adel);
-	set_except_vector(5, handle_ades);
+	/*
+	 * Some CPUs can enable/disable for cache parity detection, but does
+	 * it different ways.
+	 */
+	parity_protection_init();
+
+	(void)set_except_vector(1, handle_mod);
+	(void)set_except_vector(2, handle_tlbl);
+	(void)set_except_vector(3, handle_tlbs);
+	(void)set_except_vector(4, handle_adel);
+	(void)set_except_vector(5, handle_ades);
 	/*
 	 * The Data Bus Error/ Instruction Bus Errors are signaled
 	 * by external hardware.  Therefore these two expection have
 	 * board specific handlers.
 	 */
-	set_except_vector(6, handle_ibe);
-	set_except_vector(7, handle_dbe);
+	(void)set_except_vector(6, handle_ibe);
+	(void)set_except_vector(7, handle_dbe);
 	ibe_board_handler = default_be_board_handler;
 	dbe_board_handler = default_be_board_handler;
 
-	set_except_vector(8, handle_sys);
-	set_except_vector(9, handle_bp);
-	set_except_vector(10, handle_ri);
-	set_except_vector(11, handle_cpu);
-	set_except_vector(12, handle_ov);
-	set_except_vector(13, handle_tr);
-	set_except_vector(15, handle_fpe);
-
+	(void)set_except_vector(8, handle_sys);
+	(void)set_except_vector(9, handle_bp);
+	(void)set_except_vector(10, handle_ri);
+	(void)set_except_vector(11, handle_cpu);
+	(void)set_except_vector(12, handle_ov);
+	(void)set_except_vector(13, handle_tr);
+	(void)set_except_vector(15, handle_fpe);
+	
 	/*
 	 * Handling the following exceptions depends mostly of the cpu type
 	 */
-	switch(mips_cputype) {
-	case CPU_R10000:
-		/*
-		 * The R10000 is in most aspects similar to the R4400.  It
-		 * should get some special optimizations.
-		 */
-		write_32bit_cp0_register(CP0_FRAMEMASK, 0);
-		set_cp0_status(ST0_XX, ST0_XX);
-		/*
-		 * The R10k might even work for Linux/MIPS - but we're paranoid
-		 * and refuse to run until this is tested on real silicon
-		 */
-		panic("CPU too expensive - making holiday in the ANDES!");
-		break;
-	case CPU_R4000MC:
-	case CPU_R4400MC:
-	case CPU_R4000SC:
-	case CPU_R4400SC:
-		vce_available = 1;
-		/* Fall through ...  */
-	case CPU_R4000PC:
-	case CPU_R4400PC:
-	case CPU_R4200:
-	case CPU_R4300:
-     /* case CPU_R4640: */
-	case CPU_R4600:
-        case CPU_R5000:
-        case CPU_NEVADA:
-		if(mips_cputype == CPU_NEVADA) {
+	if ((mips_cpu.options & MIPS_CPU_4KEX)
+	    && (mips_cpu.options & MIPS_CPU_4KTLB)) {
+		if(mips_cpu.cputype == CPU_NEVADA) {
 			memcpy((void *)KSEG0, &except_vec0_nevada, 0x80);
-		} else if (mips_cputype == CPU_R4600)
+		} else if (mips_cpu.cputype == CPU_R4600)
 			memcpy((void *)KSEG0, &except_vec0_r4600, 0x80);
 		else
 			memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
 
 		/* Cache error vector already set above.  */
 
-		if (vce_available) {
+		if (mips_cpu.options & MIPS_CPU_VCE) {
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000,
 			       0x80);
 		} else {
 			memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
 			       0x80);
 		}
-		break;
 
+		if(mips_cpu.options & MIPS_CPU_FPU) {
+		        save_fp_context = _save_fp_context;
+			restore_fp_context = _restore_fp_context;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+		} else {
+		        save_fp_context = fpu_emulator_save_context;
+			restore_fp_context = fpu_emulator_restore_context;
+#endif
+		}
+	} else switch(mips_cpu.cputype) {
+	case CPU_R10000:
+		/*
+		 * The R10000 is in most aspects similar to the R4400.  It
+		 * should get some special optimizations.
+		 */
+		write_32bit_cp0_register(CP0_FRAMEMASK, 0);
+		set_cp0_status(ST0_XX);
+		/*
+		 * The R10k might even work for Linux/MIPS - but we're paranoid
+		 * and refuse to run until this is tested on real silicon
+		 */
+		panic("CPU too expensive - making holiday in the ANDES!");
+		break;
+	case CPU_SB1:
+		/* XXX - This should be folded in to the "cleaner" handling, above */
+		memcpy((void *)KSEG0, &except_vec0_r4000, 0x80);
+		memcpy((void *)(KSEG0 + 0x180), &except_vec3_r4000, 0x80);
+		save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
+		/* Enable timer interrupt and scd mapped interrupt in status register */
+		clear_cp0_status(0xf000);
+		set_cp0_status(0xc00);
+		break;
 	case CPU_R6000:
 	case CPU_R6000A:
-#if 0
+	        save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
+		
 		/*
 		 * The R6000 is the only R-series CPU that features a machine
 		 * check exception (similar to the R4000 cache error) and
@@ -840,9 +965,8 @@
 		 * current list of targets for Linux/MIPS.
 		 * (Duh, crap, there is someone with a tripple R6k machine)
 		 */
-		set_except_vector(14, handle_mc);
-		set_except_vector(15, handle_ndc);
-#endif
+		//set_except_vector(14, handle_mc);
+		//set_except_vector(15, handle_ndc);
 	case CPU_R2000:
 	case CPU_R3000:
 	case CPU_R3000A:
@@ -851,12 +975,17 @@
 	case CPU_R3052:
 	case CPU_R3081:
 	case CPU_R3081E:
+	case CPU_TX3912:
+	case CPU_TX3922:
+	case CPU_TX3927:
+	        save_fp_context = _save_fp_context;
+		restore_fp_context = _restore_fp_context;
 		memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);
 		memcpy((void *)(KSEG0 + 0x80), &except_vec3_generic, 0x80);
 		break;
 	case CPU_R8000:
 		printk("Detected unsupported CPU type %s.\n",
-			cpu_names[mips_cputype]);
+			cpu_names[mips_cpu.cputype]);
 		panic("Can't handle CPU");
 		break;
 
@@ -868,5 +997,6 @@
 
 	atomic_inc(&init_mm.mm_count);	/* XXX  UP?  */
 	current->active_mm = &init_mm;
-	current_pgd = init_mm.pgd;
+	write_32bit_cp0_register(CP0_CONTEXT, smp_processor_id()<<23);
+	current_pgd[0] = init_mm.pgd;
 }
diff -u --recursive --new-file v2.4.5/linux/arch/mips/kernel/unaligned.c linux/arch/mips/kernel/unaligned.c
--- v2.4.5/linux/arch/mips/kernel/unaligned.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/kernel/unaligned.c	Mon Jul  2 13:56:40 2001
@@ -1,5 +1,4 @@
-/* $Id: unaligned.c,v 1.7 1999/12/04 03:59:00 ralf Exp $
- *
+/*
  * Handle unaligned accesses by emulation.
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -83,6 +82,7 @@
 #include <asm/byteorder.h>
 #include <asm/inst.h>
 #include <asm/uaccess.h>
+#include <asm/system.h>
 
 #define STR(x)  __STR(x)
 #define __STR(x)  #x
@@ -91,8 +91,8 @@
  * User code may only access USEG; kernel code may access the
  * entire address space.
  */
-#define check_axs(p,a,s)                                \
-	if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0)      \
+#define check_axs(pc,a,s)				\
+	if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0)	\
 		goto sigbus;
 
 static inline void
@@ -365,12 +365,15 @@
 		return;
 	}
 
+	die_if_kernel ("Unhandled kernel unaligned access", regs);
 	send_sig(SIGSEGV, current, 1);
 	return;
 sigbus:
+	die_if_kernel ("Unhandled kernel unaligned access", regs);
 	send_sig(SIGBUS, current, 1);
 	return;
 sigill:
+	die_if_kernel ("Unhandled kernel unaligned access or invalid instruction", regs);
 	send_sig(SIGILL, current, 1);
 	return;
 }
@@ -380,6 +383,21 @@
 asmlinkage void do_ade(struct pt_regs *regs)
 {
 	unsigned long pc;
+#ifdef CONFIG_MIPS_FPU_EMULATOR
+        extern int do_dsemulret(struct pt_regs *);
+
+        /* 
+         * Address errors may be deliberately induced
+         * by the FPU emulator to take retake control
+         * of the CPU after executing the instruction
+         * in the delay slot of an emulated branch.
+         */
+
+        if((unsigned long)regs->cp0_epc == current->thread.dsemul_aerpc) {
+                (void)do_dsemulret(regs);
+                return;
+        }
+#endif /* CONFIG_MIPS_FPU_EMULATOR */
 
 	/*
 	 * Did we catch a fault trying to load an instruction?
@@ -401,6 +419,7 @@
 	return;
 
 sigbus:
+	die_if_kernel ("Kernel unaligned instruction access", regs);
 	force_sig(SIGBUS, current);
 
 	return;
diff -u --recursive --new-file v2.4.5/linux/arch/mips/ld.script.big linux/arch/mips/ld.script.big
--- v2.4.5/linux/arch/mips/ld.script.big	Wed Jul 12 15:14:41 2000
+++ linux/arch/mips/ld.script.big	Wed Dec 31 16:00:00 1969
@@ -1,120 +0,0 @@
-OUTPUT_FORMAT("elf32-bigmips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
-  .init          : { *(.init)		} =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-
-  /* Startup code */
-  . = ALIGN(4096);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);	/* Align double page for init_task_union */
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  __bss_start = .;
-  _fbss = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-  }
-
-  /* Sections to be discarded */
-  /DISCARD/ :
-  {
-        *(.text.exit)
-        *(.data.exit)
-        *(.exitcall.exit)
-  }
-
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/ld.script.in linux/arch/mips/ld.script.in
--- v2.4.5/linux/arch/mips/ld.script.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips/ld.script.in	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,147 @@
+OUTPUT_ARCH(mips)
+ENTRY(kernel_entry)
+SECTIONS
+{
+  /* Read-only sections, merged into text segment: */
+  . = @@LOADADDR@@;
+  .init          : { *(.init)		} =0
+  .text      :
+  {
+    _ftext = . ;
+    *(.text)
+    *(.rodata)
+    *(.rodata1)
+    /* .gnu.warning sections are handled specially by elf32.em.  */
+    *(.gnu.warning)
+  } =0
+  .kstrtab : { *(.kstrtab) }
+
+  . = ALIGN(16);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  __start___dbe_table = .;	/* Exception table for data bus errors */
+  __dbe_table : { *(__dbe_table) }
+  __stop___dbe_table = .;
+
+  __start___ksymtab = .;	/* Kernel symbol table */
+  __ksymtab : { *(__ksymtab) }
+  __stop___ksymtab = .;
+
+  _etext = .;
+
+  . = ALIGN(8192);
+  .data.init_task : { *(.data.init_task) }
+
+  /* Startup code */
+  . = ALIGN(4096);
+  __init_begin = .;
+  .text.init : { *(.text.init) }
+  .data.init : { *(.data.init) }
+  . = ALIGN(16);
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);	/* Align double page for init_task_union */
+  __init_end = .;
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  .fini      : { *(.fini)    } =0
+  .reginfo : { *(.reginfo) }
+  /* Adjust the address for the data segment.  We want to adjust up to
+     the same address within the page on the next page up.  It would
+     be more correct to do this:
+       . = .;
+     The current expression does not correctly handle the case of a
+     text segment ending precisely at the end of a page; it causes the
+     data segment to skip a page.  The above expression does not have
+     this problem, but it will currently (2/95) cause BFD to allocate
+     a single segment, combining both text and data, for this case.
+     This will prevent the text segment from being shared among
+     multiple executions of the program; I think that is more
+     important than losing a page of the virtual address space (note
+     that no actual memory is lost; the page which is skipped can not
+     be referenced).  */
+  . = .;
+  .data    :
+  {
+    _fdata = . ;
+    *(.data)
+
+   /* Align the initial ramdisk image (INITRD) on page boundaries. */
+   . = ALIGN(4096);
+   __rd_start = .;
+   *(.initrd)
+   __rd_end = .;
+   . = ALIGN(4096);
+
+    CONSTRUCTORS
+  }
+  .data1   : { *(.data1) }
+  _gp = . + 0x8000;
+  .lit8 : { *(.lit8) }
+  .lit4 : { *(.lit4) }
+  .ctors         : { *(.ctors)   }
+  .dtors         : { *(.dtors)   }
+  .got           : { *(.got.plt) *(.got) }
+  .dynamic       : { *(.dynamic) }
+  /* We want the small data sections together, so single-instruction offsets
+     can access them all, and initialized data all before uninitialized, so
+     we can shorten the on-disk segment size.  */
+  .sdata     : { *(.sdata) }
+  . = ALIGN(4);
+  _edata  =  .;
+  PROVIDE (edata = .);
+
+  __bss_start = .;
+  _fbss = .;
+  .sbss      : { *(.sbss) *(.scommon) }
+  .bss       :
+  {
+   *(.dynbss)
+   *(.bss)
+   *(COMMON)
+   .  = ALIGN(4);
+  _end = . ;
+  PROVIDE (end = .);
+  }
+
+  /* Sections to be discarded */
+  /DISCARD/ :
+  {
+        *(.text.exit)
+        *(.data.exit)
+        *(.exitcall.exit)
+  }
+
+  /* This is the MIPS specific mdebug section.  */
+  .mdebug : { *(.mdebug) }
+  /* These are needed for ELF backends which have not yet been
+     converted to the new style linker.  */
+  .stab 0 : { *(.stab) }
+  .stabstr 0 : { *(.stabstr) }
+  /* DWARF debug sections.
+     Symbols in the .debug DWARF section are relative to the beginning of the
+     section so we begin .debug at 0.  It's not clear yet what needs to happen
+     for the others.   */
+  .debug          0 : { *(.debug) }
+  .debug_srcinfo  0 : { *(.debug_srcinfo) }
+  .debug_aranges  0 : { *(.debug_aranges) }
+  .debug_pubnames 0 : { *(.debug_pubnames) }
+  .debug_sfnames  0 : { *(.debug_sfnames) }
+  .line           0 : { *(.line) }
+  /* These must appear regardless of  .  */
+  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
+  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
+  .comment : { *(.comment) }
+  .note : { *(.note) }
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/ld.script.little linux/arch/mips/ld.script.little
--- v2.4.5/linux/arch/mips/ld.script.little	Wed Jul 12 15:14:41 2000
+++ linux/arch/mips/ld.script.little	Wed Dec 31 16:00:00 1969
@@ -1,120 +0,0 @@
-OUTPUT_FORMAT("elf32-littlemips")
-OUTPUT_ARCH(mips)
-ENTRY(kernel_entry)
-SECTIONS
-{
-  /* Read-only sections, merged into text segment: */
-  . = 0x80000000;
-  .init          : { *(.init)		} =0
-  .text      :
-  {
-    _ftext = . ;
-    *(.text)
-    *(.rodata)
-    *(.rodata1)
-    /* .gnu.warning sections are handled specially by elf32.em.  */
-    *(.gnu.warning)
-  } =0
-  _etext = .;
-  PROVIDE (etext = .);
-
-  . = ALIGN(8192);
-  .data.init_task : { *(.data.init_task) }
-
-  /* Startup code */
-  . = ALIGN(4096);
-  __init_begin = .;
-  .text.init : { *(.text.init) }
-  .data.init : { *(.data.init) }
-  . = ALIGN(16);
-  __setup_start = .;
-  .setup.init : { *(.setup.init) }
-  __setup_end = .;
-  __initcall_start = .;
-  .initcall.init : { *(.initcall.init) }
-  __initcall_end = .;
-  . = ALIGN(4096);	/* Align double page for init_task_union */
-  __init_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  .fini      : { *(.fini)    } =0
-  .reginfo : { *(.reginfo) }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  It would
-     be more correct to do this:
-       . = .;
-     The current expression does not correctly handle the case of a
-     text segment ending precisely at the end of a page; it causes the
-     data segment to skip a page.  The above expression does not have
-     this problem, but it will currently (2/95) cause BFD to allocate
-     a single segment, combining both text and data, for this case.
-     This will prevent the text segment from being shared among
-     multiple executions of the program; I think that is more
-     important than losing a page of the virtual address space (note
-     that no actual memory is lost; the page which is skipped can not
-     be referenced).  */
-  . = .;
-  .data    :
-  {
-    _fdata = . ;
-    *(.data)
-    CONSTRUCTORS
-  }
-  .data1   : { *(.data1) }
-  _gp = . + 0x8000;
-  .lit8 : { *(.lit8) }
-  .lit4 : { *(.lit4) }
-  .ctors         : { *(.ctors)   }
-  .dtors         : { *(.dtors)   }
-  .got           : { *(.got.plt) *(.got) }
-  .dynamic       : { *(.dynamic) }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .sdata     : { *(.sdata) }
-  _edata  =  .;
-  PROVIDE (edata = .);
-
-  __bss_start = .;
-  _fbss = .;
-  .sbss      : { *(.sbss) *(.scommon) }
-  .bss       :
-  {
-   *(.dynbss)
-   *(.bss)
-   *(COMMON)
-  _end = . ;
-  PROVIDE (end = .);
-  }
-
-  /* Sections to be discarded */
-  /DISCARD/ : 
-  {
-        *(.text.exit)
-        *(.data.exit)
-        *(.exitcall.exit)
-  }
-
-  /* These are needed for ELF backends which have not yet been
-     converted to the new style linker.  */
-  .stab 0 : { *(.stab) }
-  .stabstr 0 : { *(.stabstr) }
-  /* DWARF debug sections.
-     Symbols in the .debug DWARF section are relative to the beginning of the
-     section so we begin .debug at 0.  It's not clear yet what needs to happen
-     for the others.   */
-  .debug          0 : { *(.debug) }
-  .debug_srcinfo  0 : { *(.debug_srcinfo) }
-  .debug_aranges  0 : { *(.debug_aranges) }
-  .debug_pubnames 0 : { *(.debug_pubnames) }
-  .debug_sfnames  0 : { *(.debug_sfnames) }
-  .line           0 : { *(.line) }
-  /* These must appear regardless of  .  */
-  .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) }
-  .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) }
-}
diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/Makefile linux/arch/mips/lib/Makefile
--- v2.4.5/linux/arch/mips/lib/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/lib/Makefile	Mon Jul  2 13:56:40 2001
@@ -17,11 +17,7 @@
 ifdef CONFIG_CPU_R3000
   obj-y	+= r3k_dump_tlb.o 
 else
-  ifdef CONFIG_CPU_R3912
-    obj-y	+= r3k_dump_tlb.o 
-  else
-    obj-y	+= dump_tlb.o 
-  endif
+  obj-y	+= dump_tlb.o 
 endif
 
 obj-$(CONFIG_BLK_DEV_FD)	+= floppy-no.o floppy-std.o
diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/kbd-std.c linux/arch/mips/lib/kbd-std.c
--- v2.4.5/linux/arch/mips/lib/kbd-std.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/lib/kbd-std.c	Mon Jul  2 13:56:40 2001
@@ -8,7 +8,6 @@
  *
  * Copyright (C) 1998, 1999 by Ralf Baechle
  */
-#include <linux/config.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
 #include <linux/pc_keyb.h>
@@ -21,7 +20,6 @@
 static void std_kbd_request_region(void)
 {
 #ifdef CONFIG_MIPS_ITE8172
-	printk("std_kbd_request_region\n");
 	request_region(0x14000060, 16, "keyboard");
 #else
 	request_region(0x60, 16, "keyboard");
@@ -30,7 +28,6 @@
 
 static int std_kbd_request_irq(void (*handler)(int, void *, struct pt_regs *))
 {
-	printk("std_kbd_request_irq\n");
 	return request_irq(KEYBOARD_IRQ, handler, 0, "keyboard", NULL);
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/memset.S linux/arch/mips/lib/memset.S
--- v2.4.5/linux/arch/mips/lib/memset.S	Tue Dec  5 23:15:12 2000
+++ linux/arch/mips/lib/memset.S	Mon Jul  2 13:56:40 2001
@@ -54,6 +54,7 @@
 1:
 
 EXPORT(__bzero)
+	.type   __bzero, @function
 	sltiu	t0, a2, 4			/* very small region? */
 	bnez	t0, small_memset
 	 andi	t0, a0, 3			/* aligned? */
diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/rtc-no.c linux/arch/mips/lib/rtc-no.c
--- v2.4.5/linux/arch/mips/lib/rtc-no.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/lib/rtc-no.c	Mon Jul  2 13:56:40 2001
@@ -1,5 +1,4 @@
-/* $Id: rtc-no.c,v 1.2 1998/06/25 20:19:15 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
@@ -7,28 +6,25 @@
  * Stub RTC routines to keep Linux from crashing on machine which don't
  * have a RTC chip.
  *
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2001 by Ralf Baechle
  */
 #include <linux/kernel.h>
 #include <linux/mc146818rtc.h>
 
-static unsigned char no_rtc_read_data(unsigned long addr)
+static unsigned int shouldnt_happen(void)
 {
-	panic("no_rtc_read_data called - shouldn't happen.");
-}
+	static int called;
 
-static void no_rtc_write_data(unsigned char data, unsigned long addr)
-{
-	panic("no_rtc_write_data called - shouldn't happen.");
-}
+	if (!called) {
+		called = 1;
+		printk(KERN_DEBUG "RTC functions called - shouldn't happen\n");
+	}
 
-static int no_rtc_bcd_mode(void)
-{
-	panic("no_rtc_bcd_mode called - shouldn't happen.");
+	return 0;
 }
 
 struct rtc_ops no_rtc_ops = {
-	&no_rtc_read_data,
-	&no_rtc_write_data,
-	&no_rtc_bcd_mode
+    rtc_read_data:  (void *) &shouldnt_happen,
+    rtc_write_data: (void *) &shouldnt_happen,
+    rtc_bcd_mode:   (void *) &shouldnt_happen
 };
diff -u --recursive --new-file v2.4.5/linux/arch/mips/lib/rtc-std.c linux/arch/mips/lib/rtc-std.c
--- v2.4.5/linux/arch/mips/lib/rtc-std.c	Sat May 13 08:29:14 2000
+++ linux/arch/mips/lib/rtc-std.c	Mon Jul  2 13:56:40 2001
@@ -1,12 +1,11 @@
-/* $Id: rtc-std.c,v 1.2 1998/06/25 20:19:16 ralf Exp $
- *
+/*
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
  * RTC routines for PC style attached Dallas chip.
  *
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2001 by Ralf Baechle
  */
 #include <linux/mc146818rtc.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.5/linux/arch/mips/math-emu/cp1emu.c linux/arch/mips/math-emu/cp1emu.c
--- v2.4.5/linux/arch/mips/math-emu/cp1emu.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/math-emu/cp1emu.c	Mon Jul  2 13:56:40 2001
@@ -49,6 +49,7 @@
  *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
  *  Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
  *************************************************************************/
+#include <linux/config.h>
 #include <linux/mm.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
diff -u --recursive --new-file v2.4.5/linux/arch/mips/math-emu/dp_sub.c linux/arch/mips/math-emu/dp_sub.c
--- v2.4.5/linux/arch/mips/math-emu/dp_sub.c	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/math-emu/dp_sub.c	Mon Jul  2 13:56:40 2001
@@ -176,11 +176,12 @@
 			xe = xe;
 			xs = ys;
 		}
-		if (xm == 0)
+		if (xm == 0) {
 			if (ieee754_csr.rm == IEEE754_RD)
 				return ieee754dp_zero(1);	/* round negative inf. => sign = -1 */
 			else
 				return ieee754dp_zero(0);	/* other round modes   => sign = 1 */
+		}
 
 		/* normalize to rounding precision 
 		 */
diff -u --recursive --new-file v2.4.5/linux/arch/mips/mm/Makefile linux/arch/mips/mm/Makefile
--- v2.4.5/linux/arch/mips/mm/Makefile	Fri Apr 13 20:26:07 2001
+++ linux/arch/mips/mm/Makefile	Mon Jul  2 13:56:40 2001
@@ -9,11 +9,10 @@
 
 O_TARGET := mm.o
 
-export-objs			+= umap.o
-obj-y				+= extable.o init.o fault.o loadmmu.o
+export-objs			+= ioremap.o umap.o
+obj-y				+= extable.o init.o ioremap.o fault.o loadmmu.o
 
 obj-$(CONFIG_CPU_R3000)		+= r2300.o
-obj-$(CONFIG_CPU_R3912)		+= r2300.o
 obj-$(CONFIG_CPU_R4300)		+= r4xx0.o
 obj-$(CONFIG_CPU_R4X00)		+= r4xx0.o
 obj-$(CONFIG_CPU_R5000)		+= r4xx0.o
diff -u --recursive --new-file v2.4.5/linux/arch/mips/tools/offset.c linux/arch/mips/tools/offset.c
--- v2.4.5/linux/arch/mips/tools/offset.c	Thu Jul 27 18:36:54 2000
+++ linux/arch/mips/tools/offset.c	Mon Jul  2 13:56:40 2001
@@ -1,12 +1,13 @@
-/* $Id: offset.c,v 1.11 1999/09/28 22:25:50 ralf Exp $
- *
+/*
  * offset.c: Calculate pt_regs and task_struct offsets.
  *
  * Copyright (C) 1996 David S. Miller
  * Copyright (C) 1997, 1998, 1999 Ralf Baechle
  * Copyright (C) 1999 Silicon Graphics, Inc.
+ *
+ * Kevin Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000 MIPS Technologies, Inc.
  */
-
 #include <linux/types.h>
 #include <linux/sched.h>
 
@@ -84,6 +85,7 @@
 	offset("#define TASK_COUNTER       ", struct task_struct, counter);
 	offset("#define TASK_NICE          ", struct task_struct, nice);
 	offset("#define TASK_MM            ", struct task_struct, mm);
+	offset("#define TASK_PID           ", struct task_struct, pid);
 	size("#define TASK_STRUCT_SIZE   ", struct task_struct);
 	linefeed;
 }
@@ -119,6 +121,10 @@
 	       thread.irix_trampoline);
 	offset("#define THREAD_OLDCTX  ", struct task_struct, \
 	       thread.irix_oldctx);
+	offset("#define THREAD_DSEEPC  ", struct task_struct, \
+	       thread.dsemul_epc);
+	offset("#define THREAD_DSEAERPC ", struct task_struct, \
+	       thread.dsemul_aerpc);
 	linefeed;
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/ld.script.elf32.S linux/arch/mips64/ld.script.elf32.S
--- v2.4.5/linux/arch/mips64/ld.script.elf32.S	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/ld.script.elf32.S	Mon Jul  2 14:40:58 2001
@@ -8,6 +8,7 @@
   {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/ld.script.elf64 linux/arch/mips64/ld.script.elf64
--- v2.4.5/linux/arch/mips64/ld.script.elf64	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/ld.script.elf64	Mon Jul  2 14:40:58 2001
@@ -18,6 +18,7 @@
   .text : {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     /* .gnu.warning sections are handled specially by elf32.em.  */
     *(.gnu.warning)
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/Makefile linux/arch/mips64/math-emu/Makefile
--- v2.4.5/linux/arch/mips64/math-emu/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/Makefile	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,24 @@
+#
+# Makefile for the Linux/MIPS kernel FPU emulation.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+.S.o:
+	$(CC) $(CFLAGS) -c $< -o $*.o
+
+EXTRA_ASFLAGS = -mips2 -mcpu=r4000
+
+O_TARGET:= fpu_emulator.o
+
+obj-y	:= cp1emu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
+	   ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
+	   dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
+	   dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
+	   sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
+	   sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
+	   dp_sqrt.o sp_sqrt.o kernel_linkage.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/cp1emu.c linux/arch/mips64/math-emu/cp1emu.c
--- v2.4.5/linux/arch/mips64/math-emu/cp1emu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/cp1emu.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,1807 @@
+/*
+ * MIPS floating point support
+ *
+ * This program is free software; you can distribute it and/or modify it
+ * under the terms of the GNU General Public License (Version 2) as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * cp1emu.c: a MIPS coprocessor 1 (fpu) instruction emulator
+ * 
+ * A complete emulator for MIPS coprocessor 1 instructions.  This is
+ * required for #float(switch) or #float(trap), where it catches all
+ * COP1 instructions via the "CoProcessor Unusable" exception.  
+ *
+ * More surprisingly it is also required for #float(ieee), to help out
+ * the hardware fpu at the boundaries of the IEEE-754 representation
+ * (denormalised values, infinities, underflow, etc).  It is made
+ * quite nasty because emulation of some non-COP1 instructions is
+ * required, e.g. in branch delay slots.
+ * 
+ * Notes: 
+ *  1) the IEEE754 library (-le) performs the actual arithmetic;
+ *  2) if you know that you won't have an fpu, then you'll get much 
+ *     better performance by compiling with -msoft-float!  */
+ *
+ *  Nov 7, 2000
+ *  Massive changes to integrate with Linux kernel.
+ *
+ *  Replace use of kernel data area with use of user stack 
+ *  for execution of instructions in branch delay slots.
+ *
+ *  Replace use of static kernel variables with thread_struct elements.
+ *
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ * Copyright (C) 2000  MIPS Technologies, Inc.  All rights reserved.
+ */
+#include <linux/config.h>
+#include <linux/mm.h>
+#include <linux/signal.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/asm.h>
+#include <asm/branch.h>
+#include <asm/byteorder.h>
+#include <asm/inst.h>
+#include <asm/uaccess.h>
+#include <asm/processor.h>
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+
+#include <asm/fpu_emulator.h>
+
+#include "ieee754.h"
+
+/* Strap kernel emulator for full MIPS IV emulation */
+
+#ifdef __mips
+#undef __mips
+#endif
+#define __mips 4
+
+typedef void *vaddr_t;
+
+/* Function which emulates the instruction in a branch delay slot. */
+
+static int mips_dsemul(struct pt_regs *, mips_instruction, vaddr_t);
+
+/* Function which emulates a floating point instruction. */
+
+static int fpu_emu(struct pt_regs *, struct mips_fpu_soft_struct *,
+	 mips_instruction);
+
+#if __mips >= 4 && __mips != 32
+static int fpux_emu(struct pt_regs *,
+		    struct mips_fpu_soft_struct *, mips_instruction);
+#endif
+
+/* Further private data for which no space exists in mips_fpu_soft_struct */
+
+struct mips_fpu_emulator_private fpuemuprivate;
+
+/* Control registers */
+
+#define FPCREG_RID	0	/* $0  = revision id */
+#define FPCREG_CSR	31	/* $31 = csr */
+
+/* Convert Mips rounding mode (0..3) to IEEE library modes. */
+static const unsigned char ieee_rm[4] = {
+	IEEE754_RN, IEEE754_RZ, IEEE754_RU, IEEE754_RD
+};
+
+#if __mips >= 4
+/* convert condition code register number to csr bit */
+static const unsigned int fpucondbit[8] = {
+	FPU_CSR_COND0,
+	FPU_CSR_COND1,
+	FPU_CSR_COND2,
+	FPU_CSR_COND3,
+	FPU_CSR_COND4,
+	FPU_CSR_COND5,
+	FPU_CSR_COND6,
+	FPU_CSR_COND7
+};
+#endif
+
+
+
+/* 
+ * Redundant with logic already in kernel/branch.c,
+ * embedded in compute_return_epc.  At some point,
+ * a single subroutine should be used across both
+ * modules.
+ */
+static int isBranchInstr(mips_instruction * i)
+{
+	switch (MIPSInst_OPCODE(*i)) {
+	case spec_op:
+		switch (MIPSInst_FUNC(*i)) {
+		case jalr_op:
+		case jr_op:
+			return 1;
+		}
+		break;
+
+	case bcond_op:
+		switch (MIPSInst_RT(*i)) {
+		case bltz_op:
+		case bgez_op:
+		case bltzl_op:
+		case bgezl_op:
+		case bltzal_op:
+		case bgezal_op:
+		case bltzall_op:
+		case bgezall_op:
+			return 1;
+		}
+		break;
+
+	case j_op:
+	case jal_op:
+	case jalx_op:
+	case beq_op:
+	case bne_op:
+	case blez_op:
+	case bgtz_op:
+	case beql_op:
+	case bnel_op:
+	case blezl_op:
+	case bgtzl_op:
+		return 1;
+
+	case cop0_op:
+	case cop1_op:
+	case cop2_op:
+	case cop1x_op:
+		if (MIPSInst_RS(*i) == bc_op)
+			return 1;
+		break;
+	}
+
+	return 0;
+}
+
+#define REG_TO_VA (vaddr_t)
+#define VA_TO_REG (unsigned long)
+
+static unsigned long
+mips_get_word(struct pt_regs *xcp, void *va, int *perr)
+{
+	unsigned long temp;
+
+	if (!user_mode(xcp)) {
+		*perr = 0;
+		return (*(unsigned long *) va);
+	} else {
+		/* Use kernel get_user() macro */
+		*perr = (int) get_user(temp, (unsigned long *) va);
+		return temp;
+	}
+}
+
+static unsigned long long
+mips_get_dword(struct pt_regs *xcp, void *va, int *perr)
+{
+	unsigned long long temp;
+
+	if (!user_mode(xcp)) {
+		*perr = 0;
+		return (*(unsigned long long *) va);
+	} else {
+		/* Use kernel get_user() macro */
+		*perr = (int) get_user(temp, (unsigned long long *) va);
+		return temp;
+	}
+}
+
+static int mips_put_word(struct pt_regs *xcp, void *va, unsigned long val)
+{
+	if (!user_mode(xcp)) {
+		*(unsigned long *) va = val;
+		return 0;
+	} else {
+		/* Use kernel get_user() macro */
+		return (int) put_user(val, (unsigned long *) va);
+	}
+}
+
+static int mips_put_dword(struct pt_regs *xcp, void *va, long long val)
+{
+	if (!user_mode(xcp)) {
+		*(unsigned long long *) va = val;
+		return 0;
+	} else {
+		/* Use kernel get_user() macro */
+		return (int) put_user(val, (unsigned long long *) va);
+	}
+}
+
+
+/*
+ * In the Linux kernel, we support selection of FPR format on the
+ * basis of the Status.FR bit.  This does imply that, if a full 32
+ * FPRs are desired, there needs to be a flip-flop that can be written
+ * to one at that bit position.  In any case, normal MIPS ABI uses
+ * only the even FPRs (Status.FR = 0).
+ */
+
+#define CP0_STATUS_FR_SUPPORT
+
+/*
+ * Emulate the single floating point instruction pointed at by EPC.
+ * Two instructions if the instruction is in a branch delay slot.
+ */
+
+static int
+cop1Emulate(int xcptno, struct pt_regs *xcp,
+	    struct mips_fpu_soft_struct *ctx)
+{
+	mips_instruction ir;
+	vaddr_t emulpc;
+	vaddr_t contpc;
+	unsigned int cond;
+	int err = 0;
+
+
+	ir = mips_get_word(xcp, REG_TO_VA xcp->cp0_epc, &err);
+	if (err) {
+		fpuemuprivate.stats.errors++;
+		return SIGBUS;
+	}
+
+	/* XXX NEC Vr54xx bug workaround */
+	if ((xcp->cp0_cause & CAUSEF_BD) && !isBranchInstr(&ir))
+		xcp->cp0_cause &= ~CAUSEF_BD;
+
+	if (xcp->cp0_cause & CAUSEF_BD) {
+		/*
+		 * The instruction to be emulated is in a branch delay slot
+		 * which means that we have to  emulate the branch instruction
+		 * BEFORE we do the cop1 instruction. 
+		 *
+		 * This branch could be a COP1 branch, but in that case we
+		 * would have had a trap for that instruction, and would not
+		 * come through this route.
+		 *
+		 * Linux MIPS branch emulator operates on context, updating the
+		 * cp0_epc.
+		 */
+		emulpc = REG_TO_VA(xcp->cp0_epc + 4);	/* Snapshot emulation target */
+
+		if (__compute_return_epc(xcp)) {
+#ifdef CP1DBG
+			printk("failed to emulate branch at %p\n",
+				    REG_TO_VA(xcp->cp0_epc));
+#endif
+			return SIGILL;;
+		}
+		ir = mips_get_word(xcp, emulpc, &err);
+		if (err) {
+			fpuemuprivate.stats.errors++;
+			return SIGBUS;
+		}
+		contpc = REG_TO_VA xcp->cp0_epc;
+	} else {
+		emulpc = REG_TO_VA xcp->cp0_epc;
+		contpc = REG_TO_VA xcp->cp0_epc + 4;
+	}
+
+      emul:
+	fpuemuprivate.stats.emulated++;
+	switch (MIPSInst_OPCODE(ir)) {
+#ifdef CP0_STATUS_FR_SUPPORT
+		/* R4000+ 64-bit fpu registers */
+#ifndef SINGLE_ONLY_FPU
+	case ldc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			int ft = MIPSInst_RT(ir);
+			if (!(xcp->cp0_status & ST0_FR))
+				ft &= ~1;
+			ctx->regs[ft] = mips_get_dword(xcp, va, &err);
+			fpuemuprivate.stats.loads++;
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+
+	case sdc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			int ft = MIPSInst_RT(ir);
+			if (!(xcp->cp0_status & ST0_FR))
+				ft &= ~1;
+			fpuemuprivate.stats.stores++;
+			if (mips_put_dword(xcp, va, ctx->regs[ft])) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+#endif
+
+	case lwc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			fpureg_t val;
+			int ft = MIPSInst_RT(ir);
+			fpuemuprivate.stats.loads++;
+			val = mips_get_word(xcp, va, &err);
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+			if (xcp->cp0_status & ST0_FR) {
+				/* load whole register */
+				ctx->regs[ft] = val;
+			} else if (ft & 1) {
+				/* load to m.s. 32 bits */
+#ifdef SINGLE_ONLY_FPU
+				/* illegal register in single-float mode */
+				return SIGILL;
+#else
+				ctx->regs[(ft & ~1)] &= 0xffffffff;
+				ctx->regs[(ft & ~1)] |= val << 32;
+#endif
+			} else {
+				/* load to l.s. 32 bits */
+				ctx->regs[ft] &= ~0xffffffffLL;
+				ctx->regs[ft] |= val;
+			}
+		}
+		break;
+
+	case swc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int val;
+			int ft = MIPSInst_RT(ir);
+			fpuemuprivate.stats.stores++;
+			if (xcp->cp0_status & ST0_FR) {
+				/* store whole register */
+				val = ctx->regs[ft];
+			} else if (ft & 1) {
+#ifdef SINGLE_ONLY_FPU
+				/* illegal register in single-float mode */
+				return SIGILL;
+#else
+				/* store from m.s. 32 bits */
+				val = ctx->regs[(ft & ~1)] >> 32;
+#endif
+			} else {
+				/* store from l.s. 32 bits */
+				val = ctx->regs[ft];
+			}
+			if (mips_put_word(xcp, va, val)) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+#else				/* old 32-bit fpu registers */
+	case lwc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			ctx->regs[MIPSInst_RT(ir)] =
+			    mips_get_word(xcp, va, &err);
+			fpuemuprivate.stats.loads++;
+			if (err) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+
+	case swc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			fpuemuprivate.stats.stores++;
+			if (mips_put_word
+			    (xcp, va, ctx->regs[MIPSInst_RT(ir)])) {
+				fpuemuprivate.stats.errors++;
+				return SIGBUS;
+			}
+		}
+		break;
+	case ldc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int rt = MIPSInst_RT(ir) & ~1;
+			int errs = 0;
+			fpuemuprivate.stats.loads++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+			ctx->regs[rt + 1] =
+			    mips_get_word(xcp, va + 0, &err);
+			errs += err;
+			ctx->regs[rt + 0] =
+			    mips_get_word(xcp, va + 4, &err);
+			errs += err;
+#else
+			ctx->regs[rt + 0] =
+			    mips_get_word(xcp, va + 0, &err);
+			errs += err;
+			ctx->regs[rt + 1] =
+			    mips_get_word(xcp, va + 4, &err);
+			errs += err;
+#endif
+			if (err)
+				return SIGBUS;
+		}
+		break;
+
+	case sdc1_op:
+		{
+			void *va = REG_TO_VA(xcp->regs[MIPSInst_RS(ir)])
+			    + MIPSInst_SIMM(ir);
+			unsigned int rt = MIPSInst_RT(ir) & ~1;
+			fpuemuprivate.stats.stores++;
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 1]))
+				return SIGBUS;
+			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 0]))
+				return SIGBUS;
+#else
+			if (mips_put_word(xcp, va + 0, ctx->regs[rt + 0]))
+				return SIGBUS;
+			if (mips_put_word(xcp, va + 4, ctx->regs[rt + 1]))
+				return SIGBUS;
+#endif
+		}
+		break;
+#endif
+
+	case cop1_op:
+		switch (MIPSInst_RS(ir)) {
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case dmfc_op:
+			/* copregister fs -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				int fs = MIPSInst_RD(ir);
+				if (!(xcp->cp0_status & ST0_FR))
+					fs &= ~1;
+				xcp->regs[MIPSInst_RT(ir)] = ctx->regs[fs];
+			}
+			break;
+
+		case dmtc_op:
+			/* copregister fs <- rt */
+			{
+				fpureg_t value;
+				int fs = MIPSInst_RD(ir);
+				if (!(xcp->cp0_status & ST0_FR))
+					fs &= ~1;
+				value =
+				    (MIPSInst_RT(ir) ==
+				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+				ctx->regs[fs] = value;
+			}
+			break;
+#endif
+
+		case mfc_op:
+			/* copregister rd -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				/* default value from l.s. 32 bits */
+				int value = ctx->regs[MIPSInst_RD(ir)];
+				if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+					/* illegal register in single-float mode */
+					return SIGILL;
+#else
+					if (!(xcp->cp0_status & ST0_FR)) {
+						/* move from m.s. 32 bits */
+						value =
+						    ctx->
+						    regs[MIPSInst_RD(ir) &
+							 ~1] >> 32;
+					}
+#endif
+				}
+				xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case mtc_op:
+			/* copregister rd <- rt */
+			{
+				fpureg_t value;
+				if (MIPSInst_RT(ir) == 0)
+					value = 0;
+				else
+					value =
+					    (unsigned int) xcp->
+					    regs[MIPSInst_RT(ir)];
+				if (MIPSInst_RD(ir) & 1) {
+#ifdef SINGLE_ONLY_FPU
+					/* illegal register in single-float mode */
+					return SIGILL;
+#else
+					if (!(xcp->cp0_status & ST0_FR)) {
+						/* move to m.s. 32 bits */
+						ctx->
+						    regs[
+							 (MIPSInst_RD(ir) &
+							  ~1)] &=
+						    0xffffffff;
+						ctx->
+						    regs[
+							 (MIPSInst_RD(ir) &
+							  ~1)] |=
+						    value << 32;
+						break;
+					}
+#endif
+				}
+				/* move to l.s. 32 bits */
+				ctx->regs[MIPSInst_RD(ir)] &=
+				    ~0xffffffffLL;
+				ctx->regs[MIPSInst_RD(ir)] |= value;
+			}
+			break;
+#else
+
+		case mfc_op:
+			/* copregister rd -> gpr[rt] */
+			if (MIPSInst_RT(ir) != 0) {
+				unsigned value =
+				    ctx->regs[MIPSInst_RD(ir)];
+				xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case mtc_op:
+			/* copregister rd <- rt */
+			{
+				unsigned value;
+				value =
+				    (MIPSInst_RT(ir) ==
+				     0) ? 0 : xcp->regs[MIPSInst_RT(ir)];
+				ctx->regs[MIPSInst_RD(ir)] = value;
+			}
+			break;
+#endif
+
+		case cfc_op:
+			/* cop control register rd -> gpr[rt] */
+			{
+				unsigned value;
+
+				if (MIPSInst_RD(ir) == FPCREG_CSR) {
+					value = ctx->sr;
+#ifdef CSRTRACE
+					printk
+					    ("%p gpr[%d]<-csr=%08x\n",
+					     REG_TO_VA(xcp->cp0_epc),
+					     MIPSInst_RT(ir), value);
+#endif
+				} else if (MIPSInst_RD(ir) == FPCREG_RID)
+					value = 0;
+				else
+					value = 0;
+				if (MIPSInst_RT(ir))
+					xcp->regs[MIPSInst_RT(ir)] = value;
+			}
+			break;
+
+		case ctc_op:
+			/* copregister rd <- rt */
+			{
+				unsigned value;
+
+				if (MIPSInst_RT(ir) == 0)
+					value = 0;
+				else
+					value = xcp->regs[MIPSInst_RT(ir)];
+
+				/* we only have one writable control reg
+				 */
+				if (MIPSInst_RD(ir) == FPCREG_CSR) {
+#ifdef CSRTRACE
+					printk
+					    ("%p gpr[%d]->csr=%08x\n",
+					     REG_TO_VA(xcp->cp0_epc),
+					     MIPSInst_RT(ir), value);
+#endif
+					ctx->sr = value;
+					/* copy new rounding mode to ieee library state! */
+					ieee754_csr.rm =
+					    ieee_rm[value & 0x3];
+				}
+			}
+			break;
+
+		case bc_op:
+			if (xcp->cp0_cause & CAUSEF_BD) {
+				return SIGILL;
+			}
+			{
+				int likely = 0;
+
+#if __mips >= 4
+				cond =
+				    ctx->
+				    sr & fpucondbit[MIPSInst_RT(ir) >> 2];
+#else
+				cond = ctx->sr & FPU_CSR_COND;
+#endif
+				switch (MIPSInst_RT(ir) & 3) {
+				case bcfl_op:
+					likely = 1;
+				case bcf_op:
+					cond = !cond;
+					break;
+				case bctl_op:
+					likely = 1;
+				case bct_op:
+					break;
+				default:
+					/* thats an illegal instruction */
+					return SIGILL;
+				}
+
+				xcp->cp0_cause |= CAUSEF_BD;
+				if (cond) {
+					/* branch taken: emulate dslot instruction */
+					xcp->cp0_epc += 4;
+					contpc =
+					    REG_TO_VA xcp->cp0_epc +
+					    (MIPSInst_SIMM(ir) << 2);
+
+					ir =
+					    mips_get_word(xcp,
+							  REG_TO_VA(xcp->
+								    cp0_epc),
+							  &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+
+					switch (MIPSInst_OPCODE(ir)) {
+					case lwc1_op:
+					case swc1_op:
+#if (__mips >= 2 || __mips64) && !defined(SINGLE_ONLY_FPU)
+					case ldc1_op:
+					case sdc1_op:
+#endif
+					case cop1_op:
+#if __mips >= 4 && __mips != 32
+					case cop1x_op:
+#endif
+						/* its one of ours */
+						goto emul;
+#if __mips >= 4
+					case spec_op:
+						if (MIPSInst_FUNC(ir) ==
+						    movc_op) goto emul;
+						break;
+#endif
+					}
+
+					/* single step the non-cp1 instruction in the dslot */
+					return mips_dsemul(xcp, ir, contpc);
+				} else {
+					/* branch not taken */
+					if (likely)
+						/* branch likely nullifies dslot if not taken */
+						xcp->cp0_epc += 4;
+					/* else continue & execute dslot as normal insn */
+				}
+			}
+			break;
+
+		default:
+			if (!(MIPSInst_RS(ir) & 0x10)) {
+				return SIGILL;
+			}
+			/* a real fpu computation instruction */
+			{
+				int sig;
+				if ((sig = fpu_emu(xcp, ctx, ir)))
+					return sig;
+			}
+		}
+		break;
+
+#if __mips >= 4 && __mips != 32
+	case cop1x_op:
+		{
+			int sig;
+			if ((sig = fpux_emu(xcp, ctx, ir)))
+				return sig;
+		}
+		break;
+#endif
+
+#if __mips >= 4
+	case spec_op:
+		if (MIPSInst_FUNC(ir) != movc_op)
+			return SIGILL;
+		cond = fpucondbit[MIPSInst_RT(ir) >> 2];
+		if (((ctx->sr & cond) != 0) !=
+		    ((MIPSInst_RT(ir) & 1) != 0)) return 0;
+		xcp->regs[MIPSInst_RD(ir)] = xcp->regs[MIPSInst_RS(ir)];
+		break;
+#endif
+
+	default:
+		return SIGILL;
+	}
+
+	/* we did it !! */
+	xcp->cp0_epc = VA_TO_REG(contpc);
+	xcp->cp0_cause &= ~CAUSEF_BD;
+	return 0;
+}
+
+/*
+ * Emulate the arbritrary instruction ir at xcp->cp0_epc.  Required when
+ * we have to emulate the instruction in a COP1 branch delay slot.  Do
+ * not change cp0_epc due to the instruction
+ *
+ * According to the spec:
+ * 1) it shouldnt be a branch :-)
+ * 2) it can be a COP instruction :-(
+ * 3) if we are tring to run a protected memory space we must take
+ *    special care on memory access instructions :-(
+ */
+
+/*
+ * "Trampoline" return routine to catch exception following
+ *  execution of delay-slot instruction execution.
+ */
+
+int do_dsemulret(struct pt_regs *xcp)
+{
+#ifdef DSEMUL_TRACE
+	printk("desemulret\n");
+#endif
+	/* Set EPC to return to post-branch instruction */
+	xcp->cp0_epc = current->thread.dsemul_epc;
+	/*
+	 * Clear the state that got us here.
+	 */
+	current->thread.dsemul_aerpc = (unsigned long) 0;
+
+	return 0;
+}
+
+
+#define AdELOAD 0x8c000001	/* lw $0,1($0) */
+
+static int
+mips_dsemul(struct pt_regs *xcp, mips_instruction ir, vaddr_t cpc)
+{
+	mips_instruction *dsemul_insns;
+	mips_instruction forcetrap;
+	extern asmlinkage void handle_dsemulret(void);
+
+	if (ir == 0) {		/* a nop is easy */
+		xcp->cp0_epc = VA_TO_REG(cpc);
+		return 0;
+	}
+#ifdef DSEMUL_TRACE
+	printk("desemul %p %p\n", REG_TO_VA(xcp->cp0_epc), cpc);
+#endif
+
+	/* 
+	 * The strategy is to push the instruction onto the user stack 
+	 * and put a trap after it which we can catch and jump to 
+	 * the required address any alternative apart from full 
+	 * instruction emulation!!.
+	 */
+	dsemul_insns = (mips_instruction *) (xcp->regs[29] & ~3);
+	dsemul_insns -= 3;	/* Two instructions, plus one for luck ;-) */
+	/* Verify that the stack pointer is not competely insane */
+	if (verify_area
+	    (VERIFY_WRITE, dsemul_insns, sizeof(mips_instruction) * 2))
+		return SIGBUS;
+
+	if (mips_put_word(xcp, &dsemul_insns[0], ir)) {
+		fpuemuprivate.stats.errors++;
+		return (SIGBUS);
+	}
+
+	/* 
+	 * Algorithmics used a system call instruction, and
+	 * borrowed that vector.  MIPS/Linux version is a bit
+	 * more heavyweight in the interests of portability and
+	 * multiprocessor support.  We flag the thread for special
+	 * handling in the unaligned access handler and force an
+	 * address error excpetion.
+	 */
+
+	/* If one is *really* paranoid, one tests for a bad stack pointer */
+	if ((xcp->regs[29] & 0x3) == 0x3)
+		forcetrap = AdELOAD - 1;
+	else
+		forcetrap = AdELOAD;
+
+	if (mips_put_word(xcp, &dsemul_insns[1], forcetrap)) {
+		fpuemuprivate.stats.errors++;
+		return (SIGBUS);
+	}
+
+	/* Set thread state to catch and handle the exception */
+	current->thread.dsemul_epc = (unsigned long) cpc;
+	current->thread.dsemul_aerpc = (unsigned long) &dsemul_insns[1];
+	xcp->cp0_epc = VA_TO_REG & dsemul_insns[0];
+
+	/* What we'd really like to do is just flush the line(s) of the */
+	/* icache containing the dsemulret instructions, but there's no */
+	/* mechanism to do this yet...  */
+	flush_cache_all();
+	return SIGILL;		/* force out of emulation loop */
+}
+
+/* 
+ * Conversion table from MIPS compare ops 48-63
+ * cond = ieee754dp_cmp(x,y,IEEE754_UN);
+ */
+static const unsigned char cmptab[8] = {
+	0,					/* cmp_0 (sig) cmp_sf */
+	IEEE754_CUN,				/* cmp_un (sig) cmp_ngle */
+	IEEE754_CEQ,				/* cmp_eq (sig) cmp_seq */
+	IEEE754_CEQ | IEEE754_CUN,		/* cmp_ueq (sig) cmp_ngl  */
+	IEEE754_CLT,				/* cmp_olt (sig) cmp_lt */
+	IEEE754_CLT | IEEE754_CUN,		/* cmp_ult (sig) cmp_nge */
+	IEEE754_CLT | IEEE754_CEQ,		/* cmp_ole (sig) cmp_le */
+	IEEE754_CLT | IEEE754_CEQ | IEEE754_CUN, /* cmp_ule (sig) cmp_ngt */
+};
+
+#define SIFROMREG(si,x)	((si) = ctx->regs[x])
+#define SITOREG(si,x)	(ctx->regs[x] = (int)(si))
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+#define DIFROMREG(di,x)	((di) = ctx->regs[x])
+#define DITOREG(di,x)	(ctx->regs[x] = (di))
+#endif
+
+#define SPFROMREG(sp,x)	((sp).bits = ctx->regs[x])
+#define SPTOREG(sp,x)	(ctx->regs[x] = (sp).bits)
+
+#ifdef CP0_STATUS_FR_SUPPORT
+#define DPFROMREG(dp,x)	((dp).bits = \
+			ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)])
+#define DPTOREG(dp,x)	(ctx->regs[(xcp->cp0_status & ST0_FR) ? x : (x & ~1)]\
+			= (dp).bits)
+#else
+/* Beware: MIPS COP1 doubles are always little_word endian in registers */
+#define DPFROMREG(dp,x)	\
+  ((dp).bits = ((unsigned long long)ctx->regs[(x)+1] << 32) | ctx->regs[x])
+#define DPTOREG(dp,x) \
+  (ctx->regs[x] = (dp).bits, ctx->regs[(x)+1] = (dp).bits >> 32)
+#endif
+
+#if __mips >= 4 && __mips != 32
+
+/*
+ * Additional MIPS4 instructions
+ */
+
+static ieee754dp fpemu_dp_recip(ieee754dp d)
+{
+	return ieee754dp_div(ieee754dp_one(0), d);
+}
+
+static ieee754dp fpemu_dp_rsqrt(ieee754dp d)
+{
+	return ieee754dp_div(ieee754dp_one(0), ieee754dp_sqrt(d));
+}
+
+static ieee754sp fpemu_sp_recip(ieee754sp s)
+{
+	return ieee754sp_div(ieee754sp_one(0), s);
+}
+
+static ieee754sp fpemu_sp_rsqrt(ieee754sp s)
+{
+	return ieee754sp_div(ieee754sp_one(0), ieee754sp_sqrt(s));
+}
+
+
+static ieee754dp fpemu_dp_madd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_add(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_msub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_sub(ieee754dp_mul(s, t), r);
+}
+
+static ieee754dp fpemu_dp_nmadd(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_neg(ieee754dp_add(ieee754dp_mul(s, t), r));
+}
+
+static ieee754dp fpemu_dp_nmsub(ieee754dp r, ieee754dp s, ieee754dp t)
+{
+	return ieee754dp_neg(ieee754dp_sub(ieee754dp_mul(s, t), r));
+}
+
+
+static ieee754sp fpemu_sp_madd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_add(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_msub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_sub(ieee754sp_mul(s, t), r);
+}
+
+static ieee754sp fpemu_sp_nmadd(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_neg(ieee754sp_add(ieee754sp_mul(s, t), r));
+}
+
+static ieee754sp fpemu_sp_nmsub(ieee754sp r, ieee754sp s, ieee754sp t)
+{
+	return ieee754sp_neg(ieee754sp_sub(ieee754sp_mul(s, t), r));
+}
+
+static int
+fpux_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+	 mips_instruction ir)
+{
+	unsigned rcsr = 0;	/* resulting csr */
+
+	fpuemuprivate.stats.cp1xops++;
+
+	switch (MIPSInst_FMA_FFMT(ir)) {
+	case s_fmt:		/* 0 */
+		{
+			ieee754sp(*handler) (ieee754sp, ieee754sp,
+					     ieee754sp);
+			ieee754sp fd, fr, fs, ft;
+
+			switch (MIPSInst_FUNC(ir)) {
+			case lwxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					fpureg_t val;
+					int err = 0;
+					val = mips_get_word(xcp, va, &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+					if (xcp->cp0_status & ST0_FR) {
+						/* load whole register */
+						ctx->
+						    regs[MIPSInst_FD(ir)] =
+						    val;
+					} else if (MIPSInst_FD(ir) & 1) {
+						/* load to m.s. 32 bits */
+#if defined(SINGLE_ONLY_FPU)
+						/* illegal register in single-float mode */
+						return SIGILL;
+#else
+						ctx->
+						    regs[
+							 (MIPSInst_FD(ir) &
+							  ~1)] &=
+						    0xffffffff;
+						ctx->
+						    regs[
+							 (MIPSInst_FD(ir) &
+							  ~1)] |=
+						    val << 32;
+#endif
+					} else {
+						/* load to l.s. 32 bits */
+						ctx->
+						    regs[MIPSInst_FD(ir)]
+						    &= ~0xffffffffLL;
+						ctx->
+						    regs[MIPSInst_FD(ir)]
+						    |= val;
+					}
+				}
+				break;
+
+			case swxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					unsigned int val;
+					if (xcp->cp0_status & ST0_FR) {
+						/* store whole register */
+						val =
+						    ctx->
+						    regs[MIPSInst_FS(ir)];
+					} else if (MIPSInst_FS(ir) & 1) {
+#if defined(SINGLE_ONLY_FPU)
+						/* illegal register in single-float mode */
+						return SIGILL;
+#else
+						/* store from m.s. 32 bits */
+						val =
+						    ctx->
+						    regs[
+							 (MIPSInst_FS(ir) &
+							  ~1)] >> 32;
+#endif
+					} else {
+						/* store from l.s. 32 bits */
+						val =
+						    ctx->
+						    regs[MIPSInst_FS(ir)];
+					}
+					if (mips_put_word(xcp, va, val)) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case madd_s_op:
+				handler = fpemu_sp_madd;
+				goto scoptop;
+			case msub_s_op:
+				handler = fpemu_sp_msub;
+				goto scoptop;
+			case nmadd_s_op:
+				handler = fpemu_sp_nmadd;
+				goto scoptop;
+			case nmsub_s_op:
+				handler = fpemu_sp_nmsub;
+				goto scoptop;
+
+			      scoptop:
+				SPFROMREG(fr, MIPSInst_FR(ir));
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+				fd = (*handler) (fr, fs, ft);
+				SPTOREG(fd, MIPSInst_FD(ir));
+
+			      copcsr:
+				if (ieee754_cxtest(IEEE754_INEXACT))
+					rcsr |=
+					    FPU_CSR_INE_X | FPU_CSR_INE_S;
+				if (ieee754_cxtest(IEEE754_UNDERFLOW))
+					rcsr |=
+					    FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+				if (ieee754_cxtest(IEEE754_OVERFLOW))
+					rcsr |=
+					    FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+				if (ieee754_cxtest
+				    (IEEE754_INVALID_OPERATION)) rcsr |=
+					    FPU_CSR_INV_X | FPU_CSR_INV_S;
+
+				ctx->sr =
+				    (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+				if ((ctx->sr >> 5) & ctx->
+				    sr & FPU_CSR_ALL_E) {
+		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+					return SIGFPE;
+				}
+
+				break;
+
+			default:
+				return SIGILL;
+			}
+		}
+		break;
+
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt:		/* 1 */
+		{
+			ieee754dp(*handler) (ieee754dp, ieee754dp,
+					     ieee754dp);
+			ieee754dp fd, fr, fs, ft;
+
+			switch (MIPSInst_FUNC(ir)) {
+			case ldxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					int err = 0;
+					ctx->regs[MIPSInst_FD(ir)] =
+					    mips_get_dword(xcp, va, &err);
+					if (err) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case sdxc1_op:
+				{
+					void *va =
+					    REG_TO_VA(xcp->
+						      regs[MIPSInst_FR(ir)]
+						      +
+						      xcp->
+						      regs[MIPSInst_FT
+							   (ir)]);
+					if (mips_put_dword
+					    (xcp, va,
+					     ctx->regs[MIPSInst_FS(ir)])) {
+						fpuemuprivate.stats.
+						    errors++;
+						return SIGBUS;
+					}
+				}
+				break;
+
+			case madd_d_op:
+				handler = fpemu_dp_madd;
+				goto dcoptop;
+			case msub_d_op:
+				handler = fpemu_dp_msub;
+				goto dcoptop;
+			case nmadd_d_op:
+				handler = fpemu_dp_nmadd;
+				goto dcoptop;
+			case nmsub_d_op:
+				handler = fpemu_dp_nmsub;
+				goto dcoptop;
+
+			      dcoptop:
+				DPFROMREG(fr, MIPSInst_FR(ir));
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+				fd = (*handler) (fr, fs, ft);
+				DPTOREG(fd, MIPSInst_FD(ir));
+				goto copcsr;
+
+			default:
+				return SIGILL;
+			}
+		}
+		break;
+#endif
+
+	case 0x7:		/* 7 */
+		{
+			if (MIPSInst_FUNC(ir) != pfetch_op) {
+				return SIGILL;
+			}
+			/* ignore prefx operation */
+		}
+		break;
+
+	default:
+		return SIGILL;
+	}
+
+	return 0;
+}
+#endif
+
+
+
+/*
+ * Emulate a single COP1 arithmetic instruction.
+ */
+static int
+fpu_emu(struct pt_regs *xcp, struct mips_fpu_soft_struct *ctx,
+	mips_instruction ir)
+{
+	int rfmt;		/* resulting format */
+	unsigned rcsr = 0;	/* resulting csr */
+	unsigned cond;
+	union {
+		ieee754dp d;
+		ieee754sp s;
+		int w;
+#if __mips64
+		long long l;
+#endif
+	} rv;			/* resulting value */
+
+	fpuemuprivate.stats.cp1ops++;
+	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
+
+	case s_fmt:{		/* 0 */
+		ieee754sp(*handler) ();
+
+		switch (MIPSInst_FUNC(ir)) {
+			/* binary ops */
+		case fadd_op:
+			handler = ieee754sp_add;
+			goto scopbop;
+		case fsub_op:
+			handler = ieee754sp_sub;
+			goto scopbop;
+		case fmul_op:
+			handler = ieee754sp_mul;
+			goto scopbop;
+		case fdiv_op:
+			handler = ieee754sp_div;
+			goto scopbop;
+
+			/* unary  ops */
+#if __mips >= 2 || __mips64
+		case fsqrt_op:
+			handler = ieee754sp_sqrt;
+			goto scopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+		case frsqrt_op:
+			handler = fpemu_sp_rsqrt;
+			goto scopuop;
+		case frecip_op:
+			handler = fpemu_sp_recip;
+			goto scopuop;
+#endif
+#if __mips >= 4
+		case fmovc_op:
+			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+			if (((ctx->sr & cond) != 0) !=
+			    ((MIPSInst_FT(ir) & 1) != 0))
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+		case fmovz_op:
+			if (xcp->regs[MIPSInst_FT(ir)] != 0)
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+		case fmovn_op:
+			if (xcp->regs[MIPSInst_FT(ir)] == 0)
+				return 0;
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+#endif
+		case fabs_op:
+			handler = ieee754sp_abs;
+			goto scopuop;
+		case fneg_op:
+			handler = ieee754sp_neg;
+			goto scopuop;
+		case fmov_op:
+			/* an easy one */
+			SPFROMREG(rv.s, MIPSInst_FS(ir));
+			break;
+			/* binary op on handler */
+scopbop:
+			{
+				ieee754sp fs, ft;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+
+				rv.s = (*handler) (fs, ft);
+				goto copcsr;
+			}
+scopuop:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.s = (*handler) (fs);
+				goto copcsr;
+			}
+copcsr:
+			if (ieee754_cxtest(IEEE754_INEXACT))
+				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
+			if (ieee754_cxtest(IEEE754_UNDERFLOW))
+				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
+			if (ieee754_cxtest(IEEE754_OVERFLOW))
+				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
+			if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
+				rcsr |= FPU_CSR_DIV_X | FPU_CSR_DIV_S;
+			if (ieee754_cxtest
+				(IEEE754_INVALID_OPERATION)) rcsr |=
+					    FPU_CSR_INV_X | FPU_CSR_INV_S;
+				break;
+
+				/* unary conv ops */
+		case fcvts_op:
+			return SIGILL;	/* not defined */
+		case fcvtd_op:
+#if defined(SINGLE_ONLY_FPU)
+			return SIGILL;	/* not defined */
+#else
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.d = ieee754dp_fsp(fs);
+				rfmt = d_fmt;
+				goto copcsr;
+			}
+#endif
+		case fcvtw_op:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.w = ieee754sp_tint(fs);
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+
+#if __mips >= 2 || __mips64
+		case fround_op:
+		case ftrunc_op:
+		case fceil_op:
+		case ffloor_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.w = ieee754sp_tint(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+#endif			/* __mips >= 2 */
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case fcvtl_op:
+			{
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				rv.l = ieee754sp_tlong(fs);
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+
+		case froundl_op:
+		case ftruncl_op:
+		case fceill_op:
+		case ffloorl_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754sp fs;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.l = ieee754sp_tlong(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+#endif /* __mips64 && !fpu(single) */
+
+		default:
+			if (MIPSInst_FUNC(ir) >= fcmp_op) {
+				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+				ieee754sp fs, ft;
+
+				SPFROMREG(fs, MIPSInst_FS(ir));
+				SPFROMREG(ft, MIPSInst_FT(ir));
+				rv.w = ieee754sp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+				rfmt = -1;
+				if ((cmpop & 0x8) && ieee754_cxtest(IEEE754_INVALID_OPERATION))
+					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+				} else {
+					return SIGILL;
+				}
+				break;
+			}
+			break;
+		}
+
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt: {
+		ieee754dp(*handler) ();
+
+		switch (MIPSInst_FUNC(ir)) {
+			/* binary ops */
+		case fadd_op:
+			handler = ieee754dp_add;
+			goto dcopbop;
+		case fsub_op:
+			handler = ieee754dp_sub;
+			goto dcopbop;
+		case fmul_op:
+			handler = ieee754dp_mul;
+			goto dcopbop;
+		case fdiv_op:
+			handler = ieee754dp_div;
+			goto dcopbop;
+
+			/* unary  ops */
+#if __mips >= 2 || __mips64
+		case fsqrt_op:
+			handler = ieee754dp_sqrt;
+			goto dcopuop;
+#endif
+#if __mips >= 4 && __mips != 32
+		case frsqrt_op:
+			handler = fpemu_dp_rsqrt;
+			goto dcopuop;
+		case frecip_op:
+			handler = fpemu_dp_recip;
+			goto dcopuop;
+#endif
+#if __mips >= 4
+		case fmovc_op:
+			cond = fpucondbit[MIPSInst_FT(ir) >> 2];
+			if (((ctx->sr & cond) != 0) != ((MIPSInst_FT(ir) & 1) != 0))
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+		case fmovz_op:
+			if (xcp->regs[MIPSInst_FT(ir)] != 0)
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+		case fmovn_op:
+			if (xcp->regs[MIPSInst_FT(ir)] == 0)
+				return 0;
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+#endif
+		case fabs_op:
+			handler = ieee754dp_abs;
+			goto dcopuop;
+		case fneg_op:
+			handler = ieee754dp_neg;
+			goto dcopuop;
+		case fmov_op:
+			/* an easy one */
+			DPFROMREG(rv.d, MIPSInst_FS(ir));
+			break;
+
+			/* binary op on handler */
+dcopbop:
+			{
+				ieee754dp fs, ft;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+
+				rv.d = (*handler) (fs, ft);
+				goto copcsr;
+			}
+dcopuop:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.d = (*handler) (fs);
+				goto copcsr;
+			}
+
+		/* unary conv ops */
+		case fcvts_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.s = ieee754sp_fdp(fs);
+				rfmt = s_fmt;
+				goto copcsr;
+			}
+		case fcvtd_op:
+			return SIGILL;	/* not defined */
+		case fcvtw_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.w = ieee754dp_tint(fs);	/* wrong */
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+
+#if __mips >= 2 || __mips64
+		case fround_op:
+		case ftrunc_op:
+		case fceil_op:
+		case ffloor_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.w = ieee754dp_tint(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = w_fmt;
+				goto copcsr;
+			}
+#endif
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+		case fcvtl_op:
+			{
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				rv.l = ieee754dp_tlong(fs);
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+
+		case froundl_op:
+		case ftruncl_op:
+		case fceill_op:
+		case ffloorl_op:
+			{
+				unsigned int oldrm = ieee754_csr.rm;
+				ieee754dp fs;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				ieee754_csr.rm = ieee_rm[MIPSInst_FUNC(ir) & 0x3];
+				rv.l = ieee754dp_tlong(fs);
+				ieee754_csr.rm = oldrm;
+				rfmt = l_fmt;
+				goto copcsr;
+			}
+#endif /* __mips >= 3 && !fpu(single) */
+
+		default:
+			if (MIPSInst_FUNC(ir) >= fcmp_op) {
+				unsigned cmpop = MIPSInst_FUNC(ir) - fcmp_op;
+				ieee754dp fs, ft;
+
+				DPFROMREG(fs, MIPSInst_FS(ir));
+				DPFROMREG(ft, MIPSInst_FT(ir));
+				rv.w = ieee754dp_cmp(fs, ft, cmptab[cmpop & 0x7]);
+				rfmt = -1;
+				if ((cmpop & 0x8) && ieee754_cxtest (IEEE754_INVALID_OPERATION))
+					rcsr = FPU_CSR_INV_X | FPU_CSR_INV_S;
+			} else {
+				return SIGILL;
+			}
+			break;
+		}
+		break;
+	}
+#endif				/* !defined(SINGLE_ONLY_FPU) */
+
+	case w_fmt: {
+		switch (MIPSInst_FUNC(ir)) {
+		case fcvts_op:
+			/* convert word to single precision real */
+			rv.s = ieee754sp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = s_fmt;
+			goto copcsr;
+#if !defined(SINGLE_ONLY_FPU)
+		case fcvtd_op:
+			/* convert word to double precision real */
+			rv.d = ieee754dp_fint(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = d_fmt;
+			goto copcsr;
+#endif
+		default:
+			return SIGILL;
+		}
+		break;
+	}
+
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+	case l_fmt: {
+		switch (MIPSInst_FUNC(ir)) {
+		case fcvts_op:
+			/* convert long to single precision real */
+			rv.s = ieee754sp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = s_fmt;
+			goto copcsr;
+		case fcvtd_op:
+			/* convert long to double precision real */
+			rv.d = ieee754dp_flong(ctx-> regs[MIPSInst_FS(ir)]);
+			rfmt = d_fmt;
+			goto copcsr;
+		default:
+			return SIGILL;
+		}
+		break;
+	}
+#endif
+
+	default:
+		return SIGILL;
+	}
+
+	/*
+	 * Update the fpu CSR register for this operation.
+	 * If an exception is required, generate a tidy SIGFPE exception,
+	 * without updating the result register.
+	 * Note: cause exception bits do not accumulate, they are rewritten
+	 * for each op; only the flag/sticky bits accumulate.
+	 */
+	ctx->sr = (ctx->sr & ~FPU_CSR_ALL_X) | rcsr;
+	if ((ctx->sr >> 5) & ctx->sr & FPU_CSR_ALL_E) {
+		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->sr); */
+		return SIGFPE;
+	}
+
+	/* 
+	 * Now we can safely write the result back to the register file.
+	 */
+	switch (rfmt) {
+	case -1: {
+#if __mips >= 4
+		cond = fpucondbit[MIPSInst_FD(ir) >> 2];
+#else
+		cond = FPU_CSR_COND;
+#endif
+		if (rv.w)
+			ctx->sr |= cond;
+		else
+			ctx->sr &= ~cond;
+		break;
+	}
+#if !defined(SINGLE_ONLY_FPU)
+	case d_fmt:
+		DPTOREG(rv.d, MIPSInst_FD(ir));
+		break;
+#endif
+	case s_fmt:
+		SPTOREG(rv.s, MIPSInst_FD(ir));
+		break;
+	case w_fmt:
+		SITOREG(rv.w, MIPSInst_FD(ir));
+		break;
+#if __mips64 && !defined(SINGLE_ONLY_FPU)
+	case l_fmt:
+		DITOREG(rv.l, MIPSInst_FD(ir));
+		break;
+#endif
+	default:
+		return SIGILL;
+	}
+
+	return 0;
+}
+
+
+/*
+ * Emulate the floating point instruction at EPC, and continue
+ * to run until we hit a non-fp instruction, or a backward
+ * branch.  This cuts down dramatically on the per instruction 
+ * exception overhead.
+ */
+int fpu_emulator_cop1Handler(int xcptno, struct pt_regs *xcp)
+{
+	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+	unsigned long oldepc, prevepc;
+	unsigned int insn;
+	int sig = 0;
+	int err = 0;
+
+	oldepc = xcp->cp0_epc;
+	do {
+		prevepc = xcp->cp0_epc;
+		insn = mips_get_word(xcp, REG_TO_VA(xcp->cp0_epc), &err);
+		if (err) {
+			fpuemuprivate.stats.errors++;
+			return SIGBUS;
+		}
+		if (insn != 0)
+			sig = cop1Emulate(xcptno, xcp, ctx);
+		else
+			xcp->cp0_epc += 4;	/* skip nops */
+	} while (xcp->cp0_epc > prevepc && sig == 0);
+
+	/* SIGILL indicates a non-fpu instruction */
+	if (sig == SIGILL && xcp->cp0_epc != oldepc)
+		/* but if epc has advanced, then ignore it */
+		sig = 0;
+
+	return sig;
+}
+
+
+#ifdef NOTDEF
+/*
+ * Patch up the hardware fpu state when an f.p. exception occurs.  
+ */
+static int cop1Patcher(int xcptno, struct pt_regs *xcp)
+{
+	struct mips_fpu_soft_struct *ctx = &current->thread.fpu.soft;
+	unsigned sr;
+	int sig;
+
+	/* reenable Cp1, else fpe_save() will get nested exception */
+	sr = mips_bissr(ST0_CU1);
+
+	/* get fpu registers and status, then clear pending exceptions */
+	fpe_save(ctx);
+	fpe_setsr(ctx->sr &= ~FPU_CSR_ALL_X);
+
+	/* get current rounding mode for IEEE library, and emulate insn */
+	ieee754_csr.rm = ieee_rm[ctx->sr & 0x3];
+	sig = cop1Emulate(xcptno, xcp, ctx);
+
+	/* don't return with f.p. exceptions pending */
+	ctx->sr &= ~FPU_CSR_ALL_X;
+	fpe_restore(ctx);
+
+	mips_setsr(sr);
+	return sig;
+}
+
+void _cop1_init(int emulate)
+{
+	extern int _nofpu;
+
+	if (emulate) {
+		/* 
+		 * Install cop1 emulator to handle "coprocessor unusable" exception
+		 */
+		xcption(XCPTCPU, cop1Handler);
+		fpuemuactive = 1;	/* tell dbg.c that we are in charge */
+		_nofpu = 0;	/* tell setjmp() it "has" an fpu */
+	} else {
+		/* 
+		 * Install cop1 emulator for floating point exceptions only,
+		 * i.e. denormalised results, underflow, overflow etc, which
+		 * must be emulated in s/w.
+		 */
+#ifdef 1
+		/* r4000 or above use dedicate exception */
+		xcption(XCPTFPE, cop1Patcher);
+#else
+		/* r3000 et al use interrupt */
+		extern int _sbd_getfpuintr(void);
+		int intno = _sbd_getfpuintr();
+		intrupt(intno, cop1Patcher, 0);
+		mips_bissr(SR_IM0 << intno);
+#endif
+
+#if (#cpu(r4640) || #cpu(r4650)) && !defined(SINGLE_ONLY_FPU)
+		/* For R4640/R4650 compiled *without* the -msingle-float flag,
+		   then we share responsibility: the h/w handles the single
+		   precision operations, and the trap emulator handles the
+		   double precision. We set fpuemuactive so that dbg.c first
+		   fetches the s/w state before saving the h/w state. */
+		fpuemuactive = 1;
+		{
+			int i;
+			/* initialise the unused d.p high order words to be NaN */
+			for (i = 0; i < 32; i++)
+				current->thread.fpu.soft.regs[i] =
+				    0x7ff80bad00000000LL;
+		}
+#endif				/* (r4640 || r4650) && !fpu(single) */
+	}
+}
+#endif
+
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_add.c linux/arch/mips64/math-emu/dp_add.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_add.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_add.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,186 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ *
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	CLEARCX;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "add", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs == ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs == ys)
+			return x;
+		else
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+		/* FALL THROUGH */
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		ym = XDPSRS(ym, s);
+		ye += s;
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		xm = XDPSRS(xm, s);
+		xe += s;
+	}
+	assert(xe == ye);
+	assert(xe <= DP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 * leaving result in xm,xs,xe
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (DP_MBITS + 1 + 3)) {	/* carry out */
+			xm = XDPSRS1(xm);
+			xe++;
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+		/* normalize to rounding precision */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+
+	}
+	DPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_cmp.c linux/arch/mips64/math-emu/dp_cmp.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_cmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_cmp.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
+		if (cmp & IEEE754_CUN)
+			return 1;
+		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+			if (SETCX(IEEE754_INVALID_OPERATION))
+				return ieee754si_xcpt(0, "fcmpf", x);
+		}
+		return 0;
+	} else {
+		long long int vx = x.bits;
+		long long int vy = y.bits;
+
+		if (vx < 0)
+			vx = -vx ^ DP_SIGN_BIT;
+		if (vy < 0)
+			vy = -vy ^ DP_SIGN_BIT;
+
+		if (vx < vy)
+			return (cmp & IEEE754_CLT) != 0;
+		else if (vx == vy)
+			return (cmp & IEEE754_CEQ) != 0;
+		else
+			return (cmp & IEEE754_CGT) != 0;
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_div.c linux/arch/mips64/math-emu/dp_div.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_div.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_div.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "div", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return ieee754dp_zero(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return ieee754dp_inf(xs ^ ys);
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_ZERO_DIVIDE);
+		return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return ieee754dp_zero(xs == ys ? 0 : 1);
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+	/* provide rounding space */
+	xm <<= 3;
+	ym <<= 3;
+
+	{
+		/* now the dirty work */
+
+		unsigned long long rm = 0;
+		int re = xe - ye;
+		unsigned long long bm;
+
+		for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
+			if (xm >= ym) {
+				xm -= ym;
+				rm |= bm;
+				if (xm == 0)
+					break;
+			}
+			xm <<= 1;
+		}
+		rm <<= 1;
+		if (xm)
+			rm |= 1;	/* have remainder, set sticky */
+
+		assert(rm);
+
+		/* normalise rm to rounding precision ?
+		 */
+		while ((rm >> (DP_MBITS + 3)) == 0) {
+			rm <<= 1;
+			re--;
+		}
+
+		DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_fint.c linux/arch/mips64/math-emu/dp_fint.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_fint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_fint.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fint(int x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754dp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754dp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754dp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1 << 31))
+			xm = ((unsigned) 1 << 31);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+
+#if 1
+	/* normalize - result can never be inexact or overflow */
+	xe = DP_MBITS;
+	while ((xm >> DP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+#else
+	/* normalize */
+	xe = DP_MBITS + 3;
+	while ((xm >> (DP_MBITS + 3)) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	DPNORMRET1(xs, xe, xm, "fint", x);
+#endif
+}
+
+ieee754dp ieee754dp_funs(unsigned int u)
+{
+	if ((int) u < 0)
+		return ieee754dp_add(ieee754dp_1e31(),
+				     ieee754dp_fint(u & ~(1 << 31)));
+	return ieee754dp_fint(u);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_flong.c linux/arch/mips64/math-emu/dp_flong.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_flong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_flong.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,76 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_flong(long long x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754dp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754dp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754dp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1ULL << 63))
+			xm = (1ULL << 63);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+
+	/* normalize */
+	xe = DP_MBITS + 3;
+	if (xm >> (DP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits */
+		while (xm >> (DP_MBITS + 1 + 3)) {
+			XDPSRSX1();
+		}
+	} else {
+		/* normalize in grs extended double precision */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	DPNORMRET1(xs, xe, xm, "dp_flong", x);
+}
+
+ieee754dp ieee754dp_fulong(unsigned long long u)
+{
+	if ((long long) u < 0)
+		return ieee754dp_add(ieee754dp_1e63(),
+				     ieee754dp_flong(u & ~(1ULL << 63)));
+	return ieee754dp_flong(u);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_frexp.c linux/arch/mips64/math-emu/dp_frexp.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_frexp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_frexp.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* close to ieeep754dp_logb 
+*/
+ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
+{
+	COMPXDP;
+	CLEARCX;
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*eptr = 0;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	*eptr = xe + 1;
+	return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_fsp.c linux/arch/mips64/math-emu/dp_fsp.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_fsp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_fsp.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,70 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_fsp(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(builddp(xs,
+						 DP_EMAX + 1 + DP_EBIAS,
+						 ((unsigned long long) xm
+						  << (DP_MBITS -
+						      SP_MBITS))), "fsp",
+					 x);
+	case IEEE754_CLASS_INF:
+		return ieee754dp_inf(xs);
+	case IEEE754_CLASS_ZERO:
+		return ieee754dp_zero(xs);
+	case IEEE754_CLASS_DNORM:
+		/* normalize */
+		while ((xm >> SP_MBITS) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+
+	/* CANT possibly overflow,underflow, or need rounding
+	 */
+
+	/* drop the hidden bit */
+	xm &= ~SP_HIDDEN_BIT;
+
+	return builddp(xs, xe + DP_EBIAS,
+		       (unsigned long long) xm << (DP_MBITS - SP_MBITS));
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_logb.c linux/arch/mips64/math-emu/dp_logb.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_logb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_logb.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_logb(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x, "logb", x);
+	case IEEE754_CLASS_QNAN:
+		return x;
+	case IEEE754_CLASS_INF:
+		return ieee754dp_inf(0);
+	case IEEE754_CLASS_ZERO:
+		return ieee754dp_inf(1);
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	return ieee754dp_fint(xe);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_modf.c linux/arch/mips64/math-emu/dp_modf.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_modf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_modf.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*ip = x;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		/* far to small */
+		*ip = ieee754dp_zero(xs);
+		return x;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe < 0) {
+		*ip = ieee754dp_zero(xs);
+		return x;
+	}
+	if (xe >= DP_MBITS) {
+		*ip = x;
+		return ieee754dp_zero(xs);
+	}
+	/* generate ipart mantissa by clearing bottom bits 
+	 */
+	*ip = builddp(xs, xe + DP_EBIAS,
+		      ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
+		      ~DP_HIDDEN_BIT);
+
+	/* generate fpart mantissa by clearing top bits
+	 * and normalizing (must be able to normalize)
+	 */
+	xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
+	if (xm == 0)
+		return ieee754dp_zero(xs);
+
+	while ((xm >> DP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_mul.c linux/arch/mips64/math-emu/dp_mul.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_mul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_mul.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "mul", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		return ieee754dp_inf(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return ieee754dp_zero(xs ^ ys);
+
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* rm = xm * ym, re = xe+ye basicly */
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+	{
+		int re = xe + ye;
+		int rs = xs ^ ys;
+		unsigned long long rm;
+
+		/* shunt to top of word */
+		xm <<= 64 - (DP_MBITS + 1);
+		ym <<= 64 - (DP_MBITS + 1);
+
+		/* multiply 32bits xm,ym to give high 32bits rm with stickness
+		 */
+
+		/* 32 * 32 => 64 */
+#define DPXMULT(x,y)	((unsigned long long)(x) * (unsigned long long)y)
+
+		{
+			unsigned lxm = xm;
+			unsigned hxm = xm >> 32;
+			unsigned lym = ym;
+			unsigned hym = ym >> 32;
+			unsigned long long lrm;
+			unsigned long long hrm;
+
+			lrm = DPXMULT(lxm, lym);
+			hrm = DPXMULT(hxm, hym);
+
+			{
+				unsigned long long t = DPXMULT(lxm, hym);
+				{
+					unsigned long long at =
+					    lrm + (t << 32);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 32);
+			}
+
+			{
+				unsigned long long t = DPXMULT(hxm, lym);
+				{
+					unsigned long long at =
+					    lrm + (t << 32);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 32);
+			}
+			rm = hrm | (lrm != 0);
+		}
+
+		/*
+		 * sticky shift down to normal rounding precision
+		 */
+		if ((signed long long) rm < 0) {
+			rm =
+			    (rm >> (64 - (DP_MBITS + 1 + 3))) |
+			    ((rm << (DP_MBITS + 1 + 3)) != 0);
+			re++;
+		} else {
+			rm =
+			    (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
+			    ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
+		}
+		assert(rm & (DP_HIDDEN_BIT << 3));
+		DPNORMRET2(rs, re, rm, "mul", x, y);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_scalb.c linux/arch/mips64/math-emu/dp_scalb.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_scalb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_scalb.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_scalb(ieee754dp x, int n)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754dp_nanxcpt(x, "scalb", x, n);
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
+{
+	return ieee754dp_scalb(x, n);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_simple.c linux/arch/mips64/math-emu/dp_simple.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_simple.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_finite(ieee754dp x)
+{
+	return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
+}
+
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
+{
+	CLEARCX;
+	DPSIGN(x) = DPSIGN(y);
+	return x;
+}
+
+
+ieee754dp ieee754dp_neg(ieee754dp x)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x))	/* but not infinity */
+		return ieee754dp_nanxcpt(x, "neg", x);
+
+	/* quick fix up */
+	DPSIGN(x) ^= 1;
+	return x;
+}
+
+
+ieee754dp ieee754dp_abs(ieee754dp x)
+{
+	CLEARCX;
+
+	if (ieee754dp_isnan(x))	/* but not infinity */
+		return ieee754dp_nanxcpt(x, "abs", x);
+
+	/* quick fix up */
+	DPSIGN(x) = 0;
+	return x;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_sqrt.c linux/arch/mips64/math-emu/dp_sqrt.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_sqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_sqrt.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,167 @@
+/* IEEE754 floating point arithmetic
+ * double precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+static const struct ieee754dp_konst knan = {
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+	0, 0, DP_EBIAS + DP_EMAX + 1, 0
+#else
+	0, DP_EBIAS + DP_EMAX + 1, 0, 0
+#endif
+};
+
+#define nan	((ieee754dp)knan)
+
+static const unsigned table[] = {
+	0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
+	29598, 36145, 43202, 50740, 58733, 67158, 75992,
+	85215, 83599, 71378, 60428, 50647, 41945, 34246,
+	27478, 21581, 16499, 12183, 8588, 5674, 3403,
+	1742, 661, 130
+};
+
+ieee754dp ieee754dp_sqrt(ieee754dp x)
+{
+	struct ieee754_csr oldcsr;
+	ieee754dp y, z, t;
+	unsigned scalx, yh;
+	COMPXDP;
+
+	EXPLODEXDP;
+
+	/* x == INF or NAN? */
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		/* sqrt(Nan) = Nan */
+		return ieee754dp_nanxcpt(x, "sqrt");
+	case IEEE754_CLASS_ZERO:
+		/* sqrt(0) = 0 */
+		return x;
+	case IEEE754_CLASS_INF:
+		if (xs)
+			/* sqrt(-Inf) = Nan */
+			return ieee754dp_nanxcpt(nan, "sqrt");
+		/* sqrt(+Inf) = Inf */
+		return x;
+	case IEEE754_CLASS_DNORM:
+		DPDNORMX;
+		/* fall through */
+	case IEEE754_CLASS_NORM:
+		if (xs)
+			/* sqrt(-x) = Nan */
+			return ieee754dp_nanxcpt(nan, "sqrt");
+		break;
+	}
+
+	/* save old csr; switch off INX enable & flag; set RN rounding */
+	oldcsr = ieee754_csr;
+	ieee754_csr.mx &= ~IEEE754_INEXACT;
+	ieee754_csr.sx &= ~IEEE754_INEXACT;
+	ieee754_csr.rm = IEEE754_RN;
+
+	/* adjust exponent to prevent overflow */
+	scalx = 0;
+	if (xe > 512) {		/* x > 2**-512? */
+		xe -= 512;	/* x = x / 2**512 */
+		scalx += 256;
+	} else if (xe < -512) {	/* x < 2**-512? */
+		xe += 512;	/* x = x * 2**512 */
+		scalx -= 256;
+	}
+
+	y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+
+	/* magic initial approximation to almost 8 sig. bits */
+	yh = y.bits >> 32;
+	yh = (yh >> 1) + 0x1ff80000;
+	yh = yh - table[(yh >> 15) & 31];
+	y.bits = ((unsigned long long) yh << 32) | (y.bits & 0xffffffff);
+
+	/* Heron's rule once with correction to improve to ~18 sig. bits */
+	/* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
+	t = ieee754dp_div(x, y);
+	y = ieee754dp_add(y, t);
+	y.bits -= 0x0010000600000000LL;
+	y.bits &= 0xffffffff00000000LL;
+
+	/* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
+	/* t=y*y; z=t;  pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
+	z = t = ieee754dp_mul(y, y);
+	t.parts.bexp += 0x001;
+	t = ieee754dp_add(t, z);
+	z = ieee754dp_mul(ieee754dp_sub(x, z), y);
+
+	/* t=z/(t+x) ;  pt[n0]+=0x00100000; y+=t; */
+	t = ieee754dp_div(z, ieee754dp_add(t, x));
+	t.parts.bexp += 0x001;
+	y = ieee754dp_add(y, t);
+
+	/* twiddle last bit to force y correctly rounded */
+
+	/* set RZ, clear INEX flag */
+	ieee754_csr.rm = IEEE754_RZ;
+	ieee754_csr.sx &= ~IEEE754_INEXACT;
+
+	/* t=x/y; ...chopped quotient, possibly inexact */
+	t = ieee754dp_div(x, y);
+
+	if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
+
+		if (!(ieee754_csr.sx & IEEE754_INEXACT))
+			/* t = t-ulp */
+			t.bits -= 1;
+
+		/* add inexact to result status */
+		oldcsr.cx |= IEEE754_INEXACT;
+		oldcsr.sx |= IEEE754_INEXACT;
+
+		switch (oldcsr.rm) {
+		case IEEE754_RP:
+			y.bits += 1;
+			/* drop through */
+		case IEEE754_RN:
+			t.bits += 1;
+			break;
+		}
+
+		/* y=y+t; ...chopped sum */
+		y = ieee754dp_add(y, t);
+
+		/* adjust scalx for correctly rounded sqrt(x) */
+		scalx -= 1;
+	}
+
+	/* py[n0]=py[n0]+scalx; ...scale back y */
+	y.parts.bexp += scalx;
+
+	/* restore rounding mode, possibly set inexact */
+	ieee754_csr = oldcsr;
+
+	return y;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_sub.c linux/arch/mips64/math-emu/dp_sub.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_sub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_sub.c	Mon Jul  2 13:56:40 2001
@@ -0,0 +1,194 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
+{
+	COMPXDP;
+	COMPYDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+	EXPLODEYDP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(ieee754dp_bestnan(x, y), "sub", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754dp_nanxcpt(y, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754dp_nanxcpt(x, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754dp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs != ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+		return ieee754dp_inf(ys ^ 1);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs != ys)
+			return x;
+		else
+			return ieee754dp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		/* quick fix up */
+		DPSIGN(y) ^= 1;
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		DPDNORMX;
+		/* FAAL THOROUGH */
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		/* normalize ym,ye */
+		DPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		/* normalize xm,xe */
+		DPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* flip sign of y and handle as add */
+	ys ^= 1;
+
+	assert(xm & DP_HIDDEN_BIT);
+	assert(ym & DP_HIDDEN_BIT);
+
+
+	/* provide guard,round and stick bit dpace */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		ym = XDPSRS(ym, s);
+		ye += s;
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		xm = XDPSRS(xm, s);
+		xe += s;
+	}
+	assert(xe == ye);
+	assert(xe <= DP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (DP_MBITS + 1 + 3)) {	/* carry out */
+			xm = XDPSRS1(xm);	/* shift preserving sticky */
+			xe++;
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0) {
+			if (ieee754_csr.rm == IEEE754_RD)
+				return ieee754dp_zero(1);	/* round negative inf. => sign = -1 */
+			else
+				return ieee754dp_zero(0);	/* other round modes   => sign = 1 */
+		}
+
+		/* normalize to rounding precision 
+		 */
+		while ((xm >> (DP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	DPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_tint.c linux/arch/mips64/math-emu/dp_tint.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_tint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_tint.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754dp.h"
+
+int ieee754dp_tint(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fixdp", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fixdp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 31) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fix", x);
+	}
+	/* oh gawd */
+	if (xe > DP_MBITS) {
+		xm <<= xe - DP_MBITS;
+	} else if (xe < DP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= DP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned int ieee754dp_tuns(ieee754dp x)
+{
+	ieee754dp hb = ieee754dp_1e31();
+
+	/* what if x < 0 ?? */
+	if (ieee754dp_lt(x, hb))
+		return (unsigned) ieee754dp_tint(x);
+
+	return (unsigned) ieee754dp_tint(ieee754dp_sub(x, hb)) |
+	    ((unsigned) 1 << 31);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/dp_tlong.c linux/arch/mips64/math-emu/dp_tlong.c
--- v2.4.5/linux/arch/mips64/math-emu/dp_tlong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/dp_tlong.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,141 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+long long ieee754dp_tlong(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much too small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "dp_tlong", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 63) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
+	}
+	if (xe < 0) {
+		if (ieee754_csr.rm == IEEE754_RU) {
+			if (xs) {	/* Negative  */
+				return 0x0000000000000000LL;
+			} else {	/* Positive */
+				return 0x0000000000000001LL;
+			}
+		} else if (ieee754_csr.rm == IEEE754_RD) {
+			if (xs) {	/* Negative , return -1 */
+				return 0xffffffffffffffffLL;
+			} else {	/* Positive */
+				return 0x0000000000000000LL;
+			}
+		} else {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754di_xcpt(0, "dp_tlong", x);
+		}
+	}
+	/* oh gawd */
+	if (xe > DP_MBITS) {
+		xm <<= xe - DP_MBITS;
+	} else if (xe < DP_MBITS) {
+		unsigned long long residue;
+		unsigned long long mask = 0;
+		int i;
+		int round;
+		int sticky;
+		int odd;
+
+		/* compute mask */
+		for (i = 0; i < DP_MBITS - xe; i++) {
+			mask = mask << 1;
+			mask = mask | 0x1;
+		}
+		residue = (xm & mask) << (64 - (DP_MBITS - xe));
+		round =
+		    ((0x8000000000000000LL & residue) !=
+		     0x0000000000000000LL);
+		sticky =
+		    ((0x7fffffffffffffffLL & residue) !=
+		     0x0000000000000000LL);
+
+		xm >>= DP_MBITS - xe;
+
+		odd = ((xm & 0x1) != 0x0000000000000000LL);
+
+		/* Do the rounding */
+		if (!round && sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)) {
+				xm++;
+			}
+		} else if (round && !sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)
+			    || (ieee754_csr.rm == IEEE754_RN && odd)) {
+				xm++;
+			}
+		} else if (round && sticky) {
+			if ((ieee754_csr.rm == IEEE754_RU && !xs)
+			    || (ieee754_csr.rm == IEEE754_RD && xs)
+			    || (ieee754_csr.rm == IEEE754_RN)) {
+				xm++;
+			}
+		}
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned long long ieee754dp_tulong(ieee754dp x)
+{
+	ieee754dp hb = ieee754dp_1e63();
+
+	/* what if x < 0 ?? */
+	if (ieee754dp_lt(x, hb))
+		return (unsigned long long) ieee754dp_tlong(x);
+
+	return (unsigned long long) ieee754dp_tlong(ieee754dp_sub(x, hb)) |
+	    (1ULL << 63);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754.c linux/arch/mips64/math-emu/ieee754.c
--- v2.4.5/linux/arch/mips64/math-emu/ieee754.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,138 @@
+/* ieee754 floating point arithmetic
+ * single and double precision
+ *
+ * BUGS
+ * not much dp done
+ * doesnt generate IEEE754_INEXACT
+ *
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+
+/* indexed by class */
+const char *const ieee754_cname[] = {
+	"Normal",
+	"Zero",
+	"Denormal",
+	"Infinity",
+	"QNaN",
+	"SNaN",
+};
+
+/* the control status register 
+*/
+struct ieee754_csr ieee754_csr;
+
+/* special constants
+*/
+
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+#define SPSTR(s,b,m) {m,b,s}
+#define DPSTR(s,b,mh,ml) {ml,mh,b,s}
+#endif
+
+#ifdef __MIPSEB__
+#define SPSTR(s,b,m) {s,b,m}
+#define DPSTR(s,b,mh,ml) {s,b,mh,ml}
+#endif
+
+const struct ieee754dp_konst __ieee754dp_spcvals[] = {
+	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0),	/* + zero   */
+	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0),	/* - zero   */
+	DPSTR(0, DP_EBIAS, 0, 0),	/* + 1.0   */
+	DPSTR(1, DP_EBIAS, 0, 0),	/* - 1.0   */
+	DPSTR(0, 3 + DP_EBIAS, 0x40000, 0),	/* + 10.0   */
+	DPSTR(1, 3 + DP_EBIAS, 0x40000, 0),	/* - 10.0   */
+	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0),	/* + infinity */
+	DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0),	/* - infinity */
+	DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x40000, 0),	/* + indef quiet Nan */
+	DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* + max */
+	DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF),	/* - max */
+	DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0),	/* + min normal */
+	DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0),	/* - min normal */
+	DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1),	/* + min denormal */
+	DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1),	/* - min denormal */
+	DPSTR(0, 31 + DP_EBIAS, 0, 0),	/* + 1.0e31 */
+	DPSTR(0, 63 + DP_EBIAS, 0, 0),	/* + 1.0e63 */
+};
+
+const struct ieee754sp_konst __ieee754sp_spcvals[] = {
+	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0),	/* + zero   */
+	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0),	/* - zero   */
+	SPSTR(0, SP_EBIAS, 0),	/* + 1.0   */
+	SPSTR(1, SP_EBIAS, 0),	/* - 1.0   */
+	SPSTR(0, 3 + SP_EBIAS, 0x200000),	/* + 10.0   */
+	SPSTR(1, 3 + SP_EBIAS, 0x200000),	/* - 10.0   */
+	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0),	/* + infinity */
+	SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0),	/* - infinity */
+	SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x200000),	/* + indef quiet Nan  */
+	SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF),	/* + max normal */
+	SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF),	/* - max normal */
+	SPSTR(0, SP_EMIN + SP_EBIAS, 0),	/* + min normal */
+	SPSTR(1, SP_EMIN + SP_EBIAS, 0),	/* - min normal */
+	SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1),	/* + min denormal */
+	SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1),	/* - min denormal */
+	SPSTR(0, 31 + SP_EBIAS, 0),	/* + 1.0e31 */
+	SPSTR(0, 63 + SP_EBIAS, 0),	/* + 1.0e63 */
+};
+
+
+int ieee754si_xcpt(int r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+	ax.op = op;
+	ax.rt = IEEE754_RT_SI;
+	ax.rv.si = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.si;
+}
+
+long long ieee754di_xcpt(long long r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+	ax.op = op;
+	ax.rt = IEEE754_RT_DI;
+	ax.rv.di = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.di;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754.h linux/arch/mips64/math-emu/ieee754.h
--- v2.4.5/linux/arch/mips64/math-emu/ieee754.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754.h	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,490 @@
+/* single and double precision fp ops
+ * missing extended precision.
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modification to allow integration with Linux kernel 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#ifdef __KERNEL__
+/* Going from Algorithmics to Linux native environment, add this */
+#include <linux/types.h>
+
+/* 
+ * Not very pretty, but the Linux kernel's normal va_list definition 
+ * does not allow it to be used as a structure element, as it is here.
+ */
+#ifndef _STDARG_H
+#include <stdarg.h>
+#endif
+
+#else
+
+/* Note that __KERNEL__ is taken to mean Linux kernel */
+
+#if #system(OpenBSD)
+#include <machine/types.h>
+#endif
+#include <machine/endian.h>
+
+#endif				/* __KERNEL__ */
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__MIPSEL__)
+struct ieee754dp_konst {
+	unsigned mantlo:32;
+	unsigned manthi:20;
+	unsigned bexp:11;
+	unsigned sign:1;
+};
+struct ieee754sp_konst {
+	unsigned mant:23;
+	unsigned bexp:8;
+	unsigned sign:1;
+};
+
+typedef union _ieee754dp {
+	struct ieee754dp_konst oparts;
+	struct {
+		unsigned long long mant:52;
+		unsigned int bexp:11;
+		unsigned int sign:1;
+	} parts;
+	unsigned long long bits;
+	double d;
+} ieee754dp;
+
+typedef union _ieee754sp {
+	struct ieee754sp_konst parts;
+	float f;
+	unsigned long bits;
+} ieee754sp;
+#endif
+
+#if (defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN) || defined(__MIPSEB__)
+struct ieee754dp_konst {
+	unsigned sign:1;
+	unsigned bexp:11;
+	unsigned manthi:20;
+	unsigned mantlo:32;
+};
+typedef union _ieee754dp {
+	struct ieee754dp_konst oparts;
+	struct {
+		unsigned int sign:1;
+		unsigned int bexp:11;
+		unsigned long long mant:52;
+	} parts;
+	double d;
+	unsigned long long bits;
+} ieee754dp;
+
+struct ieee754sp_konst {
+	unsigned sign:1;
+	unsigned bexp:8;
+	unsigned mant:23;
+};
+
+typedef union _ieee754sp {
+	struct ieee754sp_konst parts;
+	float f;
+	unsigned long bits;
+} ieee754sp;
+#endif
+
+/*
+ * single precision (often aka float)
+*/
+int ieee754sp_finite(ieee754sp x);
+int ieee754sp_class(ieee754sp x);
+
+ieee754sp ieee754sp_abs(ieee754sp x);
+ieee754sp ieee754sp_neg(ieee754sp x);
+ieee754sp ieee754sp_scalb(ieee754sp x, int);
+ieee754sp ieee754sp_logb(ieee754sp x);
+
+/* x with sign of y */
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
+
+ieee754sp ieee754sp_fint(int x);
+ieee754sp ieee754sp_funs(unsigned x);
+ieee754sp ieee754sp_flong(long long x);
+ieee754sp ieee754sp_fulong(unsigned long long x);
+ieee754sp ieee754sp_fdp(ieee754dp x);
+
+int ieee754sp_tint(ieee754sp x);
+unsigned int ieee754sp_tuns(ieee754sp x);
+long long ieee754sp_tlong(ieee754sp x);
+unsigned long long ieee754sp_tulong(ieee754sp x);
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
+ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
+ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
+
+ieee754sp ieee754sp_ceil(ieee754sp x);
+ieee754sp ieee754sp_floor(ieee754sp x);
+ieee754sp ieee754sp_trunc(ieee754sp x);
+
+ieee754sp ieee754sp_sqrt(ieee754sp x);
+
+/*
+ * double precision (often aka double)
+*/
+int ieee754dp_finite(ieee754dp x);
+int ieee754dp_class(ieee754dp x);
+
+/* x with sign of y */
+ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
+ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
+
+ieee754dp ieee754dp_abs(ieee754dp x);
+ieee754dp ieee754dp_neg(ieee754dp x);
+ieee754dp ieee754dp_scalb(ieee754dp x, int);
+
+/* return exponent as integer in floating point format 
+ */
+ieee754dp ieee754dp_logb(ieee754dp x);
+
+ieee754dp ieee754dp_fint(int x);
+ieee754dp ieee754dp_funs(unsigned x);
+ieee754dp ieee754dp_flong(long long x);
+ieee754dp ieee754dp_fulong(unsigned long long x);
+ieee754dp ieee754dp_fsp(ieee754sp x);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+int ieee754dp_tint(ieee754dp x);
+unsigned int ieee754dp_tuns(ieee754dp x);
+long long ieee754dp_tlong(ieee754dp x);
+unsigned long long ieee754dp_tulong(ieee754dp x);
+
+int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop);
+/*
+ * basic sp math
+ */
+ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
+ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
+ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
+
+ieee754dp ieee754dp_ceil(ieee754dp x);
+ieee754dp ieee754dp_floor(ieee754dp x);
+ieee754dp ieee754dp_trunc(ieee754dp x);
+
+ieee754dp ieee754dp_sqrt(ieee754dp x);
+
+
+
+/* 5 types of floating point number 
+*/
+#define IEEE754_CLASS_NORM	0x00
+#define IEEE754_CLASS_ZERO	0x01
+#define IEEE754_CLASS_DNORM	0x02
+#define IEEE754_CLASS_INF	0x03
+#define IEEE754_CLASS_SNAN	0x04
+#define IEEE754_CLASS_QNAN	0x05
+extern const char *const ieee754_cname[];
+
+/* exception numbers */
+#define IEEE754_INEXACT			0x01
+#define IEEE754_UNDERFLOW		0x02
+#define IEEE754_OVERFLOW		0x04
+#define IEEE754_ZERO_DIVIDE		0x08
+#define IEEE754_INVALID_OPERATION	0x10
+
+/* cmp operators
+*/
+#define IEEE754_CLT	0x01
+#define IEEE754_CEQ	0x02
+#define IEEE754_CGT	0x04
+#define IEEE754_CUN	0x08
+
+/* rounding mode 
+*/
+#define IEEE754_RN	0	/* round to nearest */
+#define IEEE754_RZ	1	/* round toward zero  */
+#define IEEE754_RD	2	/* round toward -Infinity */
+#define IEEE754_RU	3	/* round toward +Infinity */
+
+/* other naming */
+#define IEEE754_RM	IEEE754_RD
+#define IEEE754_RP	IEEE754_RU
+
+/* "normal" comparisons
+*/
+static __inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y,
+			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754sp_le(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CGT);
+}
+
+
+static __inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
+{
+	return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y,
+			     IEEE754_CLT | IEEE754_CGT | IEEE754_CUN);
+}
+
+static __inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CLT);
+}
+
+static __inline int ieee754dp_le(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ);
+}
+
+static __inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CGT);
+}
+
+static __inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
+{
+	return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ);
+}
+
+
+/* like strtod
+*/
+ieee754dp ieee754dp_fstr(const char *s, char **endp);
+char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
+
+
+/* the control status register 
+*/
+struct ieee754_csr {
+	unsigned pad:13;
+	unsigned noq:1;		/* set 1 for no quiet NaN's */
+	unsigned nod:1;		/* set 1 for no denormalised numbers */
+	unsigned cx:5;		/* exceptions this operation */
+	unsigned mx:5;		/* exception enable  mask */
+	unsigned sx:5;		/* exceptions total */
+	unsigned rm:2;		/* current rounding mode */
+};
+extern struct ieee754_csr ieee754_csr;
+
+static __inline unsigned ieee754_getrm(void)
+{
+	return (ieee754_csr.rm);
+}
+static __inline unsigned ieee754_setrm(unsigned rm)
+{
+	return (ieee754_csr.rm = rm);
+}
+
+/*
+ * get current exceptions
+ */
+static __inline unsigned ieee754_getcx(void)
+{
+	return (ieee754_csr.cx);
+}
+
+/* test for current exception condition 
+ */
+static __inline int ieee754_cxtest(unsigned n)
+{
+	return (ieee754_csr.cx & n);
+}
+
+/*
+ * get sticky exceptions
+ */
+static __inline unsigned ieee754_getsx(void)
+{
+	return (ieee754_csr.sx);
+}
+
+/* clear sticky conditions
+*/
+static __inline unsigned ieee754_clrsx(void)
+{
+	return (ieee754_csr.sx = 0);
+}
+
+/* test for sticky exception condition 
+ */
+static __inline int ieee754_sxtest(unsigned n)
+{
+	return (ieee754_csr.sx & n);
+}
+
+/* debugging */
+ieee754sp ieee754sp_dump(char *s, ieee754sp x);
+ieee754dp ieee754dp_dump(char *s, ieee754dp x);
+
+#define IEEE754_SPCVAL_PZERO	0
+#define IEEE754_SPCVAL_NZERO	1
+#define IEEE754_SPCVAL_PONE	2
+#define IEEE754_SPCVAL_NONE	3
+#define IEEE754_SPCVAL_PTEN	4
+#define IEEE754_SPCVAL_NTEN	5
+#define IEEE754_SPCVAL_PINFINITY	6
+#define IEEE754_SPCVAL_NINFINITY	7
+#define IEEE754_SPCVAL_INDEF	8
+#define IEEE754_SPCVAL_PMAX	9	/* +max norm */
+#define IEEE754_SPCVAL_NMAX	10	/* -max norm */
+#define IEEE754_SPCVAL_PMIN	11	/* +min norm */
+#define IEEE754_SPCVAL_NMIN	12	/* +min norm */
+#define IEEE754_SPCVAL_PMIND	13	/* +min denorm */
+#define IEEE754_SPCVAL_NMIND	14	/* +min denorm */
+#define IEEE754_SPCVAL_P1E31	15	/* + 1.0e31 */
+#define IEEE754_SPCVAL_P1E63	16	/* + 1.0e63 */
+
+extern const struct ieee754dp_konst __ieee754dp_spcvals[];
+extern const struct ieee754sp_konst __ieee754sp_spcvals[];
+#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
+#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
+
+/* return infinity with given sign
+*/
+#define ieee754dp_inf(sn)	\
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754dp_zero(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754dp_one(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754dp_ten(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754dp_indef() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754dp_max(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754dp_min(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754dp_mind(sn) \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754dp_1e31() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754dp_1e63() \
+  (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
+
+#define ieee754sp_inf(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
+#define ieee754sp_zero(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
+#define ieee754sp_one(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
+#define ieee754sp_ten(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
+#define ieee754sp_indef() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
+#define ieee754sp_max(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
+#define ieee754sp_min(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
+#define ieee754sp_mind(sn) \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
+#define ieee754sp_1e31() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
+#define ieee754sp_1e63() \
+  (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
+
+/* indefinite integer value 
+*/
+#define ieee754si_indef()	INT_MIN
+#ifdef LONG_LONG_MIN
+#define ieee754di_indef()	LONG_LONG_MIN
+#else
+#define ieee754di_indef()	(-9223372036854775807LL-1)
+#endif
+
+/* IEEE exception context, passed to handler */
+struct ieee754xctx {
+	const char *op;		/* operation name */
+	int rt;			/* result type */
+	union {
+		ieee754sp sp;	/* single precision */
+		ieee754dp dp;	/* double precision */
+#ifdef IEEE854_XP
+		ieee754xp xp;	/* extended precision */
+#endif
+		int si;		/* standard signed integer (32bits) */
+		long long di;	/* extended signed integer (64bits) */
+	} rv;			/* default result format implied by op */
+	va_list ap;
+};
+
+/* result types for xctx.rt */
+#define IEEE754_RT_SP	0
+#define IEEE754_RT_DP	1
+#define IEEE754_RT_XP	2
+#define IEEE754_RT_SI	3
+#define IEEE754_RT_DI	4
+
+extern void ieee754_xcpt(struct ieee754xctx *xcp);
+
+/* compat */
+#define ieee754dp_fix(x)	ieee754dp_tint(x)
+#define ieee754sp_fix(x)	ieee754sp_tint(x)
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754d.c linux/arch/mips64/math-emu/ieee754d.c
--- v2.4.5/linux/arch/mips64/math-emu/ieee754d.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754d.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,142 @@
+/* some debug functions
+*/
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Modified to build and operate in Linux kernel environment. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+#define DP_FBITS	52
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+#define SP_FBITS	23
+
+#define DP_MBIT(x)	((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT	DP_MBIT(DP_FBITS)
+#define DP_SIGN_BIT	DP_MBIT(63)
+
+
+#define SP_MBIT(x)	((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT	SP_MBIT(SP_FBITS)
+#define SP_SIGN_BIT	SP_MBIT(31)
+
+
+#define SPSIGN(sp)	(sp.parts.sign)
+#define SPBEXP(sp)	(sp.parts.bexp)
+#define SPMANT(sp)	(sp.parts.mant)
+
+#define DPSIGN(dp)	(dp.parts.sign)
+#define DPBEXP(dp)	(dp.parts.bexp)
+#define DPMANT(dp)	(dp.parts.mant)
+
+ieee754dp ieee754dp_dump(char *m, ieee754dp x)
+{
+	int i;
+
+	printk("%s", m);
+	printk("<%08x,%08x>\n", (unsigned) (x.bits >> 32),
+	       (unsigned) x.bits);
+	printk("\t=");
+	switch (ieee754dp_class(x)) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		printk("Nan %c", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		break;
+	case IEEE754_CLASS_INF:
+		printk("%cInfinity", DPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_ZERO:
+		printk("%cZero", DPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_DNORM:
+		printk("%c0.", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		printk("e%d", DPBEXP(x) - DP_EBIAS);
+		break;
+	case IEEE754_CLASS_NORM:
+		printk("%c1.", DPSIGN(x) ? '-' : '+');
+		for (i = DP_FBITS - 1; i >= 0; i--)
+			printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
+		printk("e%d", DPBEXP(x) - DP_EBIAS);
+		break;
+	default:
+		printk("Illegal/Unknown IEEE754 value class");
+	}
+	printk("\n");
+	return x;
+}
+
+ieee754sp ieee754sp_dump(char *m, ieee754sp x)
+{
+	int i;
+
+	printk("%s=", m);
+	printk("<%08x>\n", (unsigned) x.bits);
+	printk("\t=");
+	switch (ieee754sp_class(x)) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		printk("Nan %c", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		break;
+	case IEEE754_CLASS_INF:
+		printk("%cInfinity", SPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_ZERO:
+		printk("%cZero", SPSIGN(x) ? '-' : '+');
+		break;
+	case IEEE754_CLASS_DNORM:
+		printk("%c0.", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		printk("e%d", SPBEXP(x) - SP_EBIAS);
+		break;
+	case IEEE754_CLASS_NORM:
+		printk("%c1.", SPSIGN(x) ? '-' : '+');
+		for (i = SP_FBITS - 1; i >= 0; i--)
+			printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
+		printk("e%d", SPBEXP(x) - SP_EBIAS);
+		break;
+	default:
+		printk("Illegal/Unknown IEEE754 value class");
+	}
+	printk("\n");
+	return x;
+}
+
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754dp.c linux/arch/mips64/math-emu/ieee754dp.c
--- v2.4.5/linux/arch/mips64/math-emu/ieee754dp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754dp.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * double precision: common utilities
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754dp.h"
+
+int ieee754dp_class(ieee754dp x)
+{
+	COMPXDP;
+	EXPLODEXDP;
+	return xc;
+}
+
+int ieee754dp_isnan(ieee754dp x)
+{
+	return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754dp_issnan(ieee754dp x)
+{
+	assert(ieee754dp_isnan(x));
+	if (ieee754_csr.noq)
+		return 1;
+	return !(DPMANT(x) & DP_MBIT(DP_MBITS - 1));
+}
+
+
+ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+	if (!TSTX())
+		return r;
+
+	ax.op = op;
+	ax.rt = IEEE754_RT_DP;
+	ax.rv.dp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	assert(ieee754dp_isnan(r));
+
+	if (!ieee754dp_issnan(r))	/* QNAN does not cause invalid op !! */
+		return r;
+
+	if (!SETCX(IEEE754_INVALID_OPERATION)) {
+		/* not enabled convert to a quiet NaN */
+		if (ieee754_csr.noq)
+			return r;
+		DPMANT(r) |= DP_MBIT(DP_MBITS - 1);
+		return r;
+	}
+
+	ax.op = op;
+	ax.rt = 0;
+	ax.rv.dp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.dp;
+}
+
+ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
+{
+	assert(ieee754dp_isnan(x));
+	assert(ieee754dp_isnan(y));
+
+	if (DPMANT(x) > DPMANT(y))
+		return x;
+	else
+		return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754dp ieee754dp_format(int sn, int xe, unsigned long long xm)
+{
+	assert(xm);		/* we dont gen exact zeros (probably should) */
+
+	assert((xm >> (DP_MBITS + 1 + 3)) == 0);	/* no execess */
+	assert(xm & (DP_HIDDEN_BIT << 3));
+
+	if (xe < DP_EMIN) {
+		/* strip lower bits */
+		int es = DP_EMIN - xe;
+
+		if (ieee754_csr.nod) {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754dp_zero(sn);
+		}
+
+		/* sticky right shift es bits 
+		 */
+		xm = XDPSRS(xm, es);
+		xe += es;
+
+		assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
+		assert(xe == DP_EMIN);
+	}
+	if (xm & (DP_MBIT(3) - 1)) {
+		SETCX(IEEE754_INEXACT);
+		/* inexact must round of 3 bits 
+		 */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+		/* adjust exponent for rounding add overflowing 
+		 */
+		if (xm >> (DP_MBITS + 3 + 1)) {	/* add causes mantissa overflow */
+			xm >>= 1;
+			xe++;
+		}
+	}
+	/* strip grs bits */
+	xm >>= 3;
+
+	assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */
+	assert(xe >= DP_EMIN);
+
+	if (xe > DP_EMAX) {
+		SETCX(IEEE754_OVERFLOW);
+		/* -O can be table indexed by (rm,sn) */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RN:
+			return ieee754dp_inf(sn);
+		case IEEE754_RZ:
+			return ieee754dp_max(sn);
+		case IEEE754_RU:	/* toward +Infinity */
+			if (sn == 0)
+				return ieee754dp_inf(0);
+			else
+				return ieee754dp_max(1);
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn == 0)
+				return ieee754dp_max(0);
+			else
+				return ieee754dp_inf(1);
+		}
+	}
+	/* gen norm/denorm/zero */
+
+	if ((xm & DP_HIDDEN_BIT) == 0) {
+		/* we underflow (tiny/zero) */
+		assert(xe == DP_EMIN);
+		SETCX(IEEE754_UNDERFLOW);
+		return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
+	} else {
+		assert((xm >> (DP_MBITS + 1)) == 0);	/* no execess */
+		assert(xm & DP_HIDDEN_BIT);
+
+		return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754dp.h linux/arch/mips64/math-emu/ieee754dp.h
--- v2.4.5/linux/arch/mips64/math-emu/ieee754dp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754dp.h	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,83 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended double precision sticky right shift */
+#define XDPSRS(v,rs)	\
+  ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
+
+#define XDPSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define XDPSRS1(v)	\
+  (((v) >> 1) | ((v) & 1))
+
+/* convert denormal to normalized with extended exponent */
+#define DPDNORMx(m,e) \
+  while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
+#define DPDNORMX	DPDNORMx(xm,xe)
+#define DPDNORMY	DPDNORMx(ym,ye)
+
+static __inline ieee754dp builddp(int s, int bx, unsigned long long m)
+{
+	ieee754dp r;
+
+	assert((s) == 0 || (s) == 1);
+	assert((bx) >= DP_EMIN - 1 + DP_EBIAS
+	       && (bx) <= DP_EMAX + 1 + DP_EBIAS);
+	assert(((m) >> DP_MBITS) == 0);
+
+	r.parts.sign = s;
+	r.parts.bexp = bx;
+	r.parts.mant = m;
+	return r;
+}
+
+extern int ieee754dp_isnan(ieee754dp);
+extern int ieee754dp_issnan(ieee754dp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
+extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
+extern ieee754dp ieee754dp_format(int, int, unsigned long long);
+
+
+#define DPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754dp V = ieee754dp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754dp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define DPNORMRET1(s,e,m,name,a0)  DPNORMRET2(s,e,m,name,a0,a0)
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754int.h linux/arch/mips64/math-emu/ieee754int.h
--- v2.4.5/linux/arch/mips64/math-emu/ieee754int.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754int.h	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,135 @@
+/* 
+ * IEEE754 floating point
+ * common internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+#define DP_EBIAS	1023
+#define DP_EMIN		(-1022)
+#define DP_EMAX		1023
+#define DP_MBITS	52
+
+#define SP_EBIAS	127
+#define SP_EMIN		(-126)
+#define SP_EMAX		127
+#define SP_MBITS	23
+
+#define DP_MBIT(x)	((unsigned long long)1 << (x))
+#define DP_HIDDEN_BIT	DP_MBIT(DP_MBITS)
+#define DP_SIGN_BIT	DP_MBIT(63)
+
+#define SP_MBIT(x)	((unsigned long)1 << (x))
+#define SP_HIDDEN_BIT	SP_MBIT(SP_MBITS)
+#define SP_SIGN_BIT	SP_MBIT(31)
+
+
+#define SPSIGN(sp)	(sp.parts.sign)
+#define SPBEXP(sp)	(sp.parts.bexp)
+#define SPMANT(sp)	(sp.parts.mant)
+
+#define DPSIGN(dp)	(dp.parts.sign)
+#define DPBEXP(dp)	(dp.parts.bexp)
+#define DPMANT(dp)	(dp.parts.mant)
+
+#define CLPAIR(x,y)	((x)*6+(y))
+
+#define CLEARCX	\
+  (ieee754_csr.cx = 0)
+
+#define SETCX(x) \
+  (ieee754_csr.cx |= (x),ieee754_csr.sx |= (x),ieee754_csr.mx & (x))
+
+#define TSTX()	\
+	(ieee754_csr.cx & ieee754_csr.mx)
+
+
+#define COMPXSP \
+  unsigned xm; int xe; int xs; int xc
+
+#define COMPYSP \
+  unsigned ym; int ye; int ys; int yc
+
+#define EXPLODESP(v,vc,vs,ve,vm) \
+{\
+    vs = SPSIGN(v);\
+    ve = SPBEXP(v);\
+    vm = SPMANT(v);\
+    if(ve == SP_EMAX+1+SP_EBIAS){\
+	if(vm == 0)\
+	  vc = IEEE754_CLASS_INF;\
+	else if(vm & SP_MBIT(SP_MBITS-1)) \
+	  vc = IEEE754_CLASS_QNAN;\
+	else \
+	  vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == SP_EMIN-1+SP_EBIAS) {\
+	if(vm) {\
+	    ve = SP_EMIN;\
+	    vc = IEEE754_CLASS_DNORM;\
+	} else\
+	  vc = IEEE754_CLASS_ZERO;\
+    } else {\
+	ve -= SP_EBIAS;\
+	vm |= SP_HIDDEN_BIT;\
+	vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXSP EXPLODESP(x,xc,xs,xe,xm)
+#define EXPLODEYSP EXPLODESP(y,yc,ys,ye,ym)
+
+
+#define COMPXDP \
+unsigned long long xm; int xe; int xs; int xc
+
+#define COMPYDP \
+unsigned long long ym; int ye; int ys; int yc
+
+#define EXPLODEDP(v,vc,vs,ve,vm) \
+{\
+    vm = DPMANT(v);\
+    vs = DPSIGN(v);\
+    ve = DPBEXP(v);\
+    if(ve == DP_EMAX+1+DP_EBIAS){\
+	if(vm == 0)\
+	  vc = IEEE754_CLASS_INF;\
+	else if(vm & DP_MBIT(DP_MBITS-1)) \
+	  vc = IEEE754_CLASS_QNAN;\
+	else \
+	  vc = IEEE754_CLASS_SNAN;\
+    } else if(ve == DP_EMIN-1+DP_EBIAS) {\
+	if(vm) {\
+	    ve = DP_EMIN;\
+	    vc = IEEE754_CLASS_DNORM;\
+	} else\
+	  vc = IEEE754_CLASS_ZERO;\
+    } else {\
+	ve -= DP_EBIAS;\
+	vm |= DP_HIDDEN_BIT;\
+	vc = IEEE754_CLASS_NORM;\
+    }\
+}
+#define EXPLODEXDP EXPLODEDP(x,xc,xs,xe,xm)
+#define EXPLODEYDP EXPLODEDP(y,yc,ys,ye,ym)
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754m.c linux/arch/mips64/math-emu/ieee754m.c
--- v2.4.5/linux/arch/mips64/math-emu/ieee754m.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754m.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,56 @@
+/*
+ * floor, trunc, ceil
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754.h"
+
+ieee754dp ieee754dp_floor(ieee754dp x)
+{
+	ieee754dp i;
+
+	if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+		return ieee754dp_sub(i, ieee754dp_one(0));
+	else
+		return i;
+}
+
+ieee754dp ieee754dp_ceil(ieee754dp x)
+{
+	ieee754dp i;
+
+	if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
+		return ieee754dp_add(i, ieee754dp_one(0));
+	else
+		return i;
+}
+
+ieee754dp ieee754dp_trunc(ieee754dp x)
+{
+	ieee754dp i;
+
+	(void) ieee754dp_modf(x, &i);
+	return i;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754sp.c linux/arch/mips64/math-emu/ieee754sp.c
--- v2.4.5/linux/arch/mips64/math-emu/ieee754sp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754sp.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,197 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_class(ieee754sp x)
+{
+	COMPXSP;
+	EXPLODEXSP;
+	return xc;
+}
+
+int ieee754sp_isnan(ieee754sp x)
+{
+	return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
+}
+
+int ieee754sp_issnan(ieee754sp x)
+{
+	assert(ieee754sp_isnan(x));
+	if (ieee754_csr.noq)
+		return 1;
+	return !(SPMANT(x) & SP_MBIT(SP_MBITS - 1));
+}
+
+
+ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	if (!TSTX())
+		return r;
+
+	ax.op = op;
+	ax.rt = IEEE754_RT_SP;
+	ax.rv.sp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
+{
+	struct ieee754xctx ax;
+
+	assert(ieee754sp_isnan(r));
+
+	if (!ieee754sp_issnan(r))	/* QNAN does not cause invalid op !! */
+		return r;
+
+	if (!SETCX(IEEE754_INVALID_OPERATION)) {
+		/* not enabled convert to a quiet NaN */
+		if (ieee754_csr.noq)
+			return r;
+		SPMANT(r) |= SP_MBIT(SP_MBITS - 1);
+		return r;
+	}
+
+	ax.op = op;
+	ax.rt = 0;
+	ax.rv.sp = r;
+	va_start(ax.ap, op);
+	ieee754_xcpt(&ax);
+	return ax.rv.sp;
+}
+
+ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
+{
+	assert(ieee754sp_isnan(x));
+	assert(ieee754sp_isnan(y));
+
+	if (SPMANT(x) > SPMANT(y))
+		return x;
+	else
+		return y;
+}
+
+
+/* generate a normal/denormal number with over,under handeling
+ * sn is sign
+ * xe is an unbiased exponent
+ * xm is 3bit extended precision value.
+ */
+ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
+{
+	assert(xm);		/* we dont gen exact zeros (probably should) */
+
+	assert((xm >> (SP_MBITS + 1 + 3)) == 0);	/* no execess */
+	assert(xm & (SP_HIDDEN_BIT << 3));
+
+	if (xe < SP_EMIN) {
+		/* strip lower bits */
+		int es = SP_EMIN - xe;
+
+		if (ieee754_csr.nod) {
+			SETCX(IEEE754_UNDERFLOW);
+			return ieee754sp_zero(sn);
+		}
+
+		/* sticky right shift es bits 
+		 */
+		SPXSRSXn(es);
+
+		assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
+		assert(xe == SP_EMIN);
+	}
+	if (xm & (SP_MBIT(3) - 1)) {
+		SETCX(IEEE754_INEXACT);
+		/* inexact must round of 3 bits 
+		 */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RZ:
+			break;
+		case IEEE754_RN:
+			xm += 0x3 + ((xm >> 3) & 1);
+			/* xm += (xm&0x8)?0x4:0x3 */
+			break;
+		case IEEE754_RU:	/* toward +Infinity */
+			if (!sn)	/* ?? */
+				xm += 0x8;
+			break;
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn)	/* ?? */
+				xm += 0x8;
+			break;
+		}
+		/* adjust exponent for rounding add overflowing 
+		 */
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* add causes mantissa overflow */
+			xm >>= 1;
+			xe++;
+		}
+	}
+	/* strip grs bits */
+	xm >>= 3;
+
+	assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */
+	assert(xe >= SP_EMIN);
+
+	if (xe > SP_EMAX) {
+		SETCX(IEEE754_OVERFLOW);
+		/* -O can be table indexed by (rm,sn) */
+		switch (ieee754_csr.rm) {
+		case IEEE754_RN:
+			return ieee754sp_inf(sn);
+		case IEEE754_RZ:
+			return ieee754sp_max(sn);
+		case IEEE754_RU:	/* toward +Infinity */
+			if (sn == 0)
+				return ieee754sp_inf(0);
+			else
+				return ieee754sp_max(1);
+		case IEEE754_RD:	/* toward -Infinity */
+			if (sn == 0)
+				return ieee754sp_max(0);
+			else
+				return ieee754sp_inf(1);
+		}
+	}
+	/* gen norm/denorm/zero */
+
+	if ((xm & SP_HIDDEN_BIT) == 0) {
+		/* we underflow (tiny/zero) */
+		assert(xe == SP_EMIN);
+		SETCX(IEEE754_UNDERFLOW);
+		return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
+	} else {
+		assert((xm >> (SP_MBITS + 1)) == 0);	/* no execess */
+		assert(xm & SP_HIDDEN_BIT);
+
+		return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754sp.h linux/arch/mips64/math-emu/ieee754sp.h
--- v2.4.5/linux/arch/mips64/math-emu/ieee754sp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754sp.h	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,89 @@
+/* 
+ * IEEE754 floating point
+ * double precision internal header file
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754int.h"
+
+#define assert(expr) ((void)0)
+
+/* 3bit extended single precision sticky right shift */
+#define SPXSRSXn(rs) \
+  (xe += rs, \
+   xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
+
+#define SPXSRSX1() \
+  (xe++, (xm = (xm >> 1) | (xm & 1)))
+
+#define SPXSRSYn(rs) \
+   (ye+=rs, \
+    ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
+
+#define SPXSRSY1() \
+   (ye++, (ym = (ym >> 1) | (ym & 1)))
+
+/* convert denormal to normalized with extended exponent */
+#define SPDNORMx(m,e) \
+  while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
+#define SPDNORMX	SPDNORMx(xm,xe)
+#define SPDNORMY	SPDNORMx(ym,ye)
+
+static __inline ieee754sp buildsp(int s, int bx, unsigned m)
+{
+	ieee754sp r;
+
+	assert((s) == 0 || (s) == 1);
+	assert((bx) >= SP_EMIN - 1 + SP_EBIAS
+	       && (bx) <= SP_EMAX + 1 + SP_EBIAS);
+	assert(((m) >> SP_MBITS) == 0);
+
+	r.parts.sign = s;
+	r.parts.bexp = bx;
+	r.parts.mant = m;
+
+	return r;
+}
+
+extern int ieee754sp_isnan(ieee754sp);
+extern int ieee754sp_issnan(ieee754sp);
+extern int ieee754si_xcpt(int, const char *, ...);
+extern long long ieee754di_xcpt(long long, const char *, ...);
+extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
+extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
+extern ieee754sp ieee754sp_format(int, int, unsigned);
+
+
+#define SPNORMRET2(s,e,m,name,a0,a1) \
+{ \
+    ieee754sp V = ieee754sp_format(s,e,m); \
+    if(TSTX()) \
+      return ieee754sp_xcpt(V,name,a0,a1); \
+    else \
+      return V; \
+}
+
+#define SPNORMRET1(s,e,m,name,a0)  SPNORMRET2(s,e,m,name,a0,a0)
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/ieee754xcpt.c linux/arch/mips64/math-emu/ieee754xcpt.c
--- v2.4.5/linux/arch/mips64/math-emu/ieee754xcpt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/ieee754xcpt.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,48 @@
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+/**************************************************************************
+ *  Nov 7, 2000
+ *  Added preprocessor hacks to map to Linux kernel diagnostics. 
+ *
+ *  Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *************************************************************************/
+
+#include "ieee754.h"
+
+/*
+ * Very naff exception handler (you can plug in your own and
+ * override this).
+ */
+
+static const char *const rtnames[] = {
+	"sp", "dp", "xp", "si", "di"
+};
+
+void ieee754_xcpt(struct ieee754xctx *xcp)
+{
+	printk("floating point exception in \"%s\", type=%s\n",
+		xcp->op, rtnames[xcp->rt]);
+}
+
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/kernel_linkage.c linux/arch/mips64/math-emu/kernel_linkage.c
--- v2.4.5/linux/arch/mips64/math-emu/kernel_linkage.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/kernel_linkage.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,95 @@
+/**************************************************************************
+ *
+ *  arch/mips/math_emu/kernel_linkage.c
+ *
+ *  Kevin D. Kissell, kevink@mips and Carsten Langgaard, carstenl@mips.com
+ *  Copyright (C) 2000 MIPS Technologies, Inc.  All rights reserved.
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ *************************************************************************/
+/*
+ * Routines corresponding to Linux kernel FP context
+ * manipulation primitives for the Algorithmics MIPS
+ * FPU Emulator
+ */
+
+#include <linux/sched.h>
+#include <asm/processor.h>
+#include <asm/signal.h>
+#include <asm/uaccess.h>
+
+#include <asm/fpu_emulator.h>
+
+extern struct mips_fpu_emulator_private fpuemuprivate;
+
+#define SIGNALLING_NAN 0x7ff800007ff80000LL
+
+void fpu_emulator_init_fpu(void)
+{
+	static int first = 1;
+	int i;
+ 
+	if (first) {
+		first = 0;
+		printk("Algorithmics/MIPS FPU Emulator v1.4\n");
+	}
+
+	current->thread.fpu.soft.sr = 0;
+	for (i = 0; i < 32; i++) {
+		current->thread.fpu.soft.regs[i] = SIGNALLING_NAN;
+	}
+}
+
+
+/*
+ * Emulator context save/restore to/from a signal context
+ * presumed to be on the user stack, and therefore accessed
+ * with appropriate macros from uaccess.h
+ */
+
+int fpu_emulator_save_context(struct sigcontext *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < 32; i++) {
+		err |=
+		    __put_user(current->thread.fpu.soft.regs[i],
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __put_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+	err |= __put_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+	return err;
+}
+
+int fpu_emulator_restore_context(struct sigcontext *sc)
+{
+	int i;
+	int err = 0;
+
+	for (i = 0; i < 32; i++) {
+		err |=
+		    __get_user(current->thread.fpu.soft.regs[i],
+			       &sc->sc_fpregs[i]);
+	}
+	err |= __get_user(current->thread.fpu.soft.sr, &sc->sc_fpc_csr);
+	err |= __get_user(fpuemuprivate.eir, &sc->sc_fpc_eir);
+
+	return err;
+}
+
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_add.c linux/arch/mips64/math-emu/sp_add.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_add.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_add.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,180 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	CLEARCX;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "add", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs == ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs == ys)
+			return x;
+		else
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		SPXSRSYn(s);
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		SPXSRSXn(s);
+	}
+	assert(xe == ye);
+	assert(xe <= SP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 * leaving result in xm,xs,xe
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* carry out */
+			SPXSRSX1();
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+		/* normalize in extended single precision */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+
+	}
+	SPNORMRET2(xs, xe, xm, "add", x, y);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_cmp.c linux/arch/mips64/math-emu/sp_cmp.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_cmp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_cmp.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
+		if (cmp & IEEE754_CUN)
+			return 1;
+		if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
+			if (SETCX(IEEE754_INVALID_OPERATION))
+				return ieee754si_xcpt(0, "fcmpf", x);
+		}
+		return 0;
+	} else {
+		int vx = x.bits;
+		int vy = y.bits;
+
+		if (vx < 0)
+			vx = -vx ^ SP_SIGN_BIT;
+		if (vy < 0)
+			vy = -vy ^ SP_SIGN_BIT;
+
+		if (vx < vy)
+			return (cmp & IEEE754_CLT) != 0;
+		else if (vx == vy)
+			return (cmp & IEEE754_CEQ) != 0;
+		else
+			return (cmp & IEEE754_CGT) != 0;
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_div.c linux/arch/mips64/math-emu/sp_div.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_div.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_div.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,160 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "div", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+		return ieee754sp_zero(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return ieee754sp_inf(xs ^ ys);
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		SETCX(IEEE754_ZERO_DIVIDE);
+		return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		return ieee754sp_zero(xs == ys ? 0 : 1);
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	/* provide rounding space */
+	xm <<= 3;
+	ym <<= 3;
+
+	{
+		/* now the dirty work */
+
+		unsigned rm = 0;
+		int re = xe - ye;
+		unsigned bm;
+
+		for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
+			if (xm >= ym) {
+				xm -= ym;
+				rm |= bm;
+				if (xm == 0)
+					break;
+			}
+			xm <<= 1;
+		}
+		rm <<= 1;
+		if (xm)
+			rm |= 1;	/* have remainder, set sticky */
+
+		assert(rm);
+
+		/* normalise rm to rounding precision ?
+		 */
+		while ((rm >> (SP_MBITS + 3)) == 0) {
+			rm <<= 1;
+			re--;
+		}
+
+		SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_fdp.c linux/arch/mips64/math-emu/sp_fdp.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_fdp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_fdp.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,69 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fdp(ieee754dp x)
+{
+	COMPXDP;
+
+	CLEARCX;
+
+	EXPLODEXDP;
+
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(buildsp(xs,
+						 SP_EMAX + 1 + SP_EBIAS,
+						 (unsigned long)
+						 (xm >>
+						  (DP_MBITS - SP_MBITS))),
+					 "fdp", x);
+	case IEEE754_CLASS_INF:
+		return ieee754sp_inf(xs);
+	case IEEE754_CLASS_ZERO:
+		return ieee754sp_zero(xs);
+	case IEEE754_CLASS_DNORM:
+		/* cant possibly be sp representable */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+
+	{
+		unsigned long rm;
+
+		/* convert from DP_MBITS to SP_MBITS+3 with sticky right shift 
+		 */
+		rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
+		    ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
+
+		SPNORMRET1(xs, xe, rm, "fdp", x);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_fint.c linux/arch/mips64/math-emu/sp_fint.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_fint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_fint.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,78 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_fint(int x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754sp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754sp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754sp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1 << 31))
+			xm = ((unsigned) 1 << 31);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+	xe = SP_MBITS + 3;
+
+	if (xm >> (SP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits 
+		 */
+		while (xm >> (SP_MBITS + 1 + 3)) {
+			SPXSRSX1();
+		}
+	} else {
+		/* normalize in grs extended single precision 
+		 */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET1(xs, xe, xm, "fint", x);
+}
+
+
+ieee754sp ieee754sp_funs(unsigned int u)
+{
+	if ((int) u < 0)
+		return ieee754sp_add(ieee754sp_1e31(),
+				     ieee754sp_fint(u & ~(1 << 31)));
+	return ieee754sp_fint(u);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_flong.c linux/arch/mips64/math-emu/sp_flong.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_flong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_flong.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,77 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_flong(long long x)
+{
+	COMPXDP;		/* <--- need 64-bit mantissa temp */
+
+	CLEARCX;
+
+	if (x == 0)
+		return ieee754sp_zero(0);
+	if (x == 1 || x == -1)
+		return ieee754sp_one(x < 0);
+	if (x == 10 || x == -10)
+		return ieee754sp_ten(x < 0);
+
+	xs = (x < 0);
+	if (xs) {
+		if (x == (1ULL << 63))
+			xm = (1ULL << 63);	/* max neg can't be safely negated */
+		else
+			xm = -x;
+	} else {
+		xm = x;
+	}
+	xe = SP_MBITS + 3;
+
+	if (xm >> (SP_MBITS + 1 + 3)) {
+		/* shunt out overflow bits 
+		 */
+		while (xm >> (SP_MBITS + 1 + 3)) {
+			SPXSRSX1();
+		}
+	} else {
+		/* normalize in grs extended single precision */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET1(xs, xe, xm, "sp_flong", x);
+}
+
+
+ieee754sp ieee754sp_fulong(unsigned long long u)
+{
+	if ((long long) u < 0)
+		return ieee754sp_add(ieee754sp_1e63(),
+				     ieee754sp_flong(u & ~(1ULL << 63)));
+	return ieee754sp_flong(u);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_frexp.c linux/arch/mips64/math-emu/sp_frexp.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_frexp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_frexp.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,53 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* close to ieeep754sp_logb 
+*/
+ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
+{
+	COMPXSP;
+	CLEARCX;
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*eptr = 0;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	*eptr = xe + 1;
+	return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_logb.c linux/arch/mips64/math-emu/sp_logb.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_logb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_logb.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,54 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_logb(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x, "logb", x);
+	case IEEE754_CLASS_QNAN:
+		return x;
+	case IEEE754_CLASS_INF:
+		return ieee754sp_inf(0);
+	case IEEE754_CLASS_ZERO:
+		return ieee754sp_inf(1);
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	return ieee754sp_fint(xe);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_modf.c linux/arch/mips64/math-emu/sp_modf.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_modf.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_modf.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,80 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+/* modf function is always exact for a finite number
+*/
+ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		*ip = x;
+		return x;
+	case IEEE754_CLASS_DNORM:
+		/* far to small */
+		*ip = ieee754sp_zero(xs);
+		return x;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe < 0) {
+		*ip = ieee754sp_zero(xs);
+		return x;
+	}
+	if (xe >= SP_MBITS) {
+		*ip = x;
+		return ieee754sp_zero(xs);
+	}
+	/* generate ipart mantissa by clearing bottom bits 
+	 */
+	*ip = buildsp(xs, xe + SP_EBIAS,
+		      ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
+		      ~SP_HIDDEN_BIT);
+
+	/* generate fpart mantissa by clearing top bits
+	 * and normalizing (must be able to normalize)
+	 */
+	xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
+	if (xm == 0)
+		return ieee754sp_zero(xs);
+
+	while ((xm >> SP_MBITS) == 0) {
+		xm <<= 1;
+		xe--;
+	}
+	return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_mul.c linux/arch/mips64/math-emu/sp_mul.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_mul.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_mul.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,174 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "mul", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Infinity handeling */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		return ieee754sp_inf(xs ^ ys);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return ieee754sp_zero(xs ^ ys);
+
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* rm = xm * ym, re = xe+ye basicly */
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+	{
+		int re = xe + ye;
+		int rs = xs ^ ys;
+		unsigned rm;
+
+		/* shunt to top of word */
+		xm <<= 32 - (SP_MBITS + 1);
+		ym <<= 32 - (SP_MBITS + 1);
+
+		/* multiply 32bits xm,ym to give high 32bits rm with stickness
+		 */
+		{
+			unsigned short lxm = xm & 0xffff;
+			unsigned short hxm = xm >> 16;
+			unsigned short lym = ym & 0xffff;
+			unsigned short hym = ym >> 16;
+			unsigned lrm;
+			unsigned hrm;
+
+			lrm = lxm * lym;	/* 16 * 16 => 32 */
+			hrm = hxm * hym;	/* 16 * 16 => 32 */
+
+			{
+				unsigned t = lxm * hym;	/* 16 * 16 => 32 */
+				{
+					unsigned at = lrm + (t << 16);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 16);
+			}
+
+			{
+				unsigned t = hxm * lym;	/* 16 * 16 => 32 */
+				{
+					unsigned at = lrm + (t << 16);
+					hrm += at < lrm;
+					lrm = at;
+				}
+				hrm = hrm + (t >> 16);
+			}
+			rm = hrm | (lrm != 0);
+		}
+
+		/*
+		 * sticky shift down to normal rounding precision
+		 */
+		if ((int) rm < 0) {
+			rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
+			    ((rm << (SP_MBITS + 1 + 3)) != 0);
+			re++;
+		} else {
+			rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
+			    ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
+		}
+		assert(rm & (SP_HIDDEN_BIT << 3));
+
+		SPNORMRET2(rs, re, rm, "mul", x, y);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_scalb.c linux/arch/mips64/math-emu/sp_scalb.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_scalb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_scalb.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,58 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_scalb(ieee754sp x, int n)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+		return ieee754sp_nanxcpt(x, "scalb", x, n);
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_INF:
+	case IEEE754_CLASS_ZERO:
+		return x;
+	case IEEE754_CLASS_DNORM:
+		SPDNORMX;
+		break;
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
+}
+
+
+ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
+{
+	return ieee754sp_scalb(x, n);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_simple.c linux/arch/mips64/math-emu/sp_simple.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_simple.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_simple.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,66 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+int ieee754sp_finite(ieee754sp x)
+{
+	return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
+}
+
+ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
+{
+	CLEARCX;
+	SPSIGN(x) = SPSIGN(y);
+	return x;
+}
+
+
+ieee754sp ieee754sp_neg(ieee754sp x)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x))	/* but not infinity */
+		return ieee754sp_nanxcpt(x, "neg", x);
+
+	/* quick fix up */
+	SPSIGN(x) ^= 1;
+	return x;
+}
+
+
+ieee754sp ieee754sp_abs(ieee754sp x)
+{
+	CLEARCX;
+
+	if (ieee754sp_isnan(x))	/* but not infinity */
+		return ieee754sp_nanxcpt(x, "abs", x);
+
+	/* quick fix up */
+	SPSIGN(x) = 0;
+	return x;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_sqrt.c linux/arch/mips64/math-emu/sp_sqrt.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_sqrt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_sqrt.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,115 @@
+/* IEEE754 floating point arithmetic
+ * single precision square root
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+static const struct ieee754sp_konst knan = {
+	0, SP_EBIAS + SP_EMAX + 1, 0
+};
+
+#define nan	((ieee754sp)knan)
+
+ieee754sp ieee754sp_sqrt(ieee754sp x)
+{
+	int sign = (int) 0x80000000;
+	int ix, s, q, m, t, i;
+	unsigned int r;
+	COMPXDP;
+
+	/* take care of Inf and NaN */
+
+	EXPLODEXDP;
+
+	/* x == INF or NAN? */
+	switch (xc) {
+	case IEEE754_CLASS_QNAN:
+	case IEEE754_CLASS_SNAN:
+		/* sqrt(Nan) = Nan */
+		return ieee754sp_nanxcpt(x, "sqrt");
+	case IEEE754_CLASS_ZERO:
+		/* sqrt(0) = 0 */
+		return x;
+	case IEEE754_CLASS_INF:
+		if (xs)
+			/* sqrt(-Inf) = Nan */
+			return ieee754sp_nanxcpt(nan, "sqrt");
+		/* sqrt(+Inf) = Inf */
+		return x;
+	case IEEE754_CLASS_DNORM:
+	case IEEE754_CLASS_NORM:
+		if (xs)
+			/* sqrt(-x) = Nan */
+			return ieee754sp_nanxcpt(nan, "sqrt");
+		break;
+	}
+
+	ix = x.bits;
+
+	/* normalize x */
+	m = (ix >> 23);
+	if (m == 0) {		/* subnormal x */
+		for (i = 0; (ix & 0x00800000) == 0; i++)
+			ix <<= 1;
+		m -= i - 1;
+	}
+	m -= 127;		/* unbias exponent */
+	ix = (ix & 0x007fffff) | 0x00800000;
+	if (m & 1)		/* odd m, double x to make it even */
+		ix += ix;
+	m >>= 1;		/* m = [m/2] */
+
+	/* generate sqrt(x) bit by bit */
+	ix += ix;
+	q = s = 0;		/* q = sqrt(x) */
+	r = 0x01000000;		/* r = moving bit from right to left */
+
+	while (r != 0) {
+		t = s + r;
+		if (t <= ix) {
+			s = t + r;
+			ix -= t;
+			q += r;
+		}
+		ix += ix;
+		r >>= 1;
+	}
+
+	if (ix != 0) {
+		switch (ieee754_csr.rm) {
+		case IEEE754_RP:
+			q += 2;
+			break;
+		case IEEE754_RN:
+			q += (q & 1);
+			break;
+		}
+	}
+	ix = (q >> 1) + 0x3f000000;
+	ix += (m << 23);
+	x.bits = ix;
+	return x;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_sub.c linux/arch/mips64/math-emu/sp_sub.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_sub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_sub.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,187 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
+{
+	COMPXSP;
+	COMPYSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+	EXPLODEYSP;
+
+	switch (CLPAIR(xc, yc)) {
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(ieee754sp_bestnan(x, y), "sub", x,
+					 y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
+		return ieee754sp_nanxcpt(y, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
+		return ieee754sp_nanxcpt(x, "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
+		return ieee754sp_bestnan(x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
+	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
+		return x;
+
+
+		/* Inifity handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
+		if (xs != ys)
+			return x;
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
+		return ieee754sp_inf(ys ^ 1);
+
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
+		return x;
+
+		/* Zero handeling 
+		 */
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
+		if (xs != ys)
+			return x;
+		else
+			return ieee754sp_zero(ieee754_csr.rm ==
+					      IEEE754_RD);
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
+		return x;
+
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
+	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
+		/* quick fix up */
+		DPSIGN(y) ^= 1;
+		return y;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
+		SPDNORMX;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
+		SPDNORMY;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
+		SPDNORMX;
+		break;
+
+	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
+		break;
+	}
+	/* flip sign of y and handle as add */
+	ys ^= 1;
+
+	assert(xm & SP_HIDDEN_BIT);
+	assert(ym & SP_HIDDEN_BIT);
+
+
+	/* provide guard,round and stick bit space */
+	xm <<= 3;
+	ym <<= 3;
+
+	if (xe > ye) {
+		/* have to shift y fraction right to align
+		 */
+		int s = xe - ye;
+		SPXSRSYn(s);
+	} else if (ye > xe) {
+		/* have to shift x fraction right to align
+		 */
+		int s = ye - xe;
+		SPXSRSXn(s);
+	}
+	assert(xe == ye);
+	assert(xe <= SP_EMAX);
+
+	if (xs == ys) {
+		/* generate 28 bit result of adding two 27 bit numbers
+		 */
+		xm = xm + ym;
+		xe = xe;
+		xs = xs;
+
+		if (xm >> (SP_MBITS + 1 + 3)) {	/* carry out */
+			SPXSRSX1();	/* shift preserving sticky */
+		}
+	} else {
+		if (xm >= ym) {
+			xm = xm - ym;
+			xe = xe;
+			xs = xs;
+		} else {
+			xm = ym - xm;
+			xe = xe;
+			xs = ys;
+		}
+		if (xm == 0)
+			if (ieee754_csr.rm == IEEE754_RD)
+				return ieee754sp_zero(1);	/* round negative inf. => sign = -1 */
+			else
+				return ieee754sp_zero(0);	/* other round modes   => sign = 1 */
+
+		/* normalize to rounding precision 
+		 */
+		while ((xm >> (SP_MBITS + 3)) == 0) {
+			xm <<= 1;
+			xe--;
+		}
+	}
+	SPNORMRET2(xs, xe, xm, "sub", x, y);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_tint.c linux/arch/mips64/math-emu/sp_tint.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_tint.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_tint.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,88 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include <linux/kernel.h>
+#include "ieee754sp.h"
+
+int ieee754sp_tint(ieee754sp x)
+{
+	COMPXSP;
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fixsp", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fixsp", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 31) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754si_xcpt(ieee754si_indef(), "fix", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754si_xcpt(0, "fix", x);
+	}
+	/* oh gawd */
+	if (xe > SP_MBITS) {
+		xm <<= xe - SP_MBITS;
+	} else if (xe < SP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= SP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned int ieee754sp_tuns(ieee754sp x)
+{
+	ieee754sp hb = ieee754sp_1e31();
+
+	/* what if x < 0 ?? */
+	if (ieee754sp_lt(x, hb))
+		return (unsigned) ieee754sp_tint(x);
+
+	return (unsigned) ieee754sp_tint(ieee754sp_sub(x, hb)) |
+	    ((unsigned) 1 << 31);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/mips64/math-emu/sp_tlong.c linux/arch/mips64/math-emu/sp_tlong.c
--- v2.4.5/linux/arch/mips64/math-emu/sp_tlong.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/mips64/math-emu/sp_tlong.c	Mon Jul  2 13:56:41 2001
@@ -0,0 +1,87 @@
+/* IEEE754 floating point arithmetic
+ * single precision
+ */
+/*
+ * MIPS floating point support
+ * Copyright (C) 1994-2000 Algorithmics Ltd.  All rights reserved.
+ * http://www.algor.co.uk
+ *
+ * ########################################################################
+ *
+ *  This program is free software; you can distribute it and/or modify it
+ *  under the terms of the GNU General Public License (Version 2) as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope it will be useful, but WITHOUT
+ *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ *  for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
+ *
+ * ########################################################################
+ */
+
+
+#include "ieee754sp.h"
+
+long long ieee754sp_tlong(ieee754sp x)
+{
+	COMPXDP;		/* <-- need 64-bit mantissa tmp */
+
+	CLEARCX;
+
+	EXPLODEXSP;
+
+	switch (xc) {
+	case IEEE754_CLASS_SNAN:
+	case IEEE754_CLASS_QNAN:
+		SETCX(IEEE754_INVALID_OPERATION);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	case IEEE754_CLASS_INF:
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	case IEEE754_CLASS_ZERO:
+		return 0;
+	case IEEE754_CLASS_DNORM:	/* much to small */
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "sp_tlong", x);
+	case IEEE754_CLASS_NORM:
+		break;
+	}
+	if (xe >= 63) {
+		SETCX(IEEE754_OVERFLOW);
+		return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
+	}
+	if (xe < 0) {
+		SETCX(IEEE754_UNDERFLOW);
+		return ieee754di_xcpt(0, "sp_tlong", x);
+	}
+	/* oh gawd */
+	if (xe > SP_MBITS) {
+		xm <<= xe - SP_MBITS;
+	} else if (xe < SP_MBITS) {
+		/* XXX no rounding 
+		 */
+		xm >>= SP_MBITS - xe;
+	}
+	if (xs)
+		return -xm;
+	else
+		return xm;
+}
+
+
+unsigned long long ieee754sp_tulong(ieee754sp x)
+{
+	ieee754sp hb = ieee754sp_1e63();
+
+	/* what if x < 0 ?? */
+	if (ieee754sp_lt(x, hb))
+		return (unsigned long long) ieee754sp_tlong(x);
+
+	return (unsigned long long) ieee754sp_tlong(ieee754sp_sub(x, hb)) |
+	    (1ULL << 63);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/parisc/vmlinux.lds linux/arch/parisc/vmlinux.lds
--- v2.4.5/linux/arch/parisc/vmlinux.lds	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/vmlinux.lds	Mon Jul  2 14:40:58 2001
@@ -22,7 +22,7 @@
 	} = 0
 
   . = ALIGN(16);
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   _etext = .;			/* End of text section */
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/commproc.c linux/arch/ppc/8xx_io/commproc.c
--- v2.4.5/linux/arch/ppc/8xx_io/commproc.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/8xx_io/commproc.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.commproc.c 1.8 05/18/01 07:54:04 patch
+ * BK Id: SCCS/s.commproc.c 1.11 06/15/01 13:00:20 paulus
  */
 
 /*
@@ -47,12 +47,12 @@
 /* CPM interrupt vector functions.
 */
 struct	cpm_action {
-	void	(*handler)(void *);
+	void	(*handler)(void *, struct pt_regs * regs);
 	void	*dev_id;
 };
 static	struct	cpm_action cpm_vecs[CPMVEC_NR];
 static	void	cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
-static	void	cpm_error_interrupt(void *);
+static	void	cpm_error_interrupt(void *, struct pt_regs * regs);
 
 void
 m8xx_cpm_reset(uint host_page_addr)
@@ -129,7 +129,7 @@
 	vec >>= 11;
 
 	if (cpm_vecs[vec].handler != 0)
-		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
+		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id, regs);
 	else
 		((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
 
@@ -146,14 +146,15 @@
  * tests in the interrupt handler.
  */
 static	void
-cpm_error_interrupt(void *dev)
+cpm_error_interrupt(void *dev, struct pt_regs *regs)
 {
 }
 
 /* Install a CPM interrupt handler.
 */
 void
-cpm_install_handler(int vec, void (*handler)(void *), void *dev_id)
+cpm_install_handler(int vec, void (*handler)(void *, struct pt_regs *regs),
+		    void *dev_id)
 {
 
 	/* If null handler, assume we are trying to free the IRQ.
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h
--- v2.4.5/linux/arch/ppc/8xx_io/commproc.h	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/8xx_io/commproc.h	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.commproc.h 1.8 05/17/01 18:14:20 cort
+ * BK Id: SCCS/s.commproc.h 1.13 06/15/01 13:00:20 paulus
  */
 
 /*
@@ -789,7 +789,8 @@
 #define CICR_IEN		((uint)0x00000080)	/* Int. enable */
 #define CICR_SPS		((uint)0x00000001)	/* SCC Spread */
 
-extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id);
+extern void cpm_install_handler(int vec, 
+		void (*handler)(void *, struct pt_regs *regs), void *dev_id);
 extern void cpm_free_handler(int vec);
 
 #endif /* __CPM_8XX__ */
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.4.5/linux/arch/ppc/8xx_io/uart.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/8xx_io/uart.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.uart.c 1.10 05/17/01 18:14:20 cort
+ * BK Id: SCCS/s.uart.c 1.14 06/27/01 14:49:55 trini
  */
 /*
  *  UART driver for MPC860 CPM SCC or SMC
@@ -44,6 +44,9 @@
 #include <asm/8xx_immap.h>
 #include <asm/mpc8xx.h>
 #include "commproc.h"
+#ifdef CONFIG_MAGIC_SYSRQ
+#include <linux/sysrq.h>
+#endif
 
 #ifdef CONFIG_KGDB
 extern void breakpoint(void);
@@ -91,6 +94,15 @@
 static int serial_refcount;
 static int serial_console_setup(struct console *co, char *options);
 
+static int serial_console_wait_key(struct console *co);
+static void serial_console_write(struct console *c, const char *s,
+				unsigned count);
+static kdev_t serial_console_device(struct console *c);
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+static unsigned long break_pressed; /* break, really ... */
+#endif
+
 /*
  * Serial driver configuration section.  Here are the various options:
  */
@@ -202,6 +214,16 @@
 	cbd_t			*tx_cur;
 } ser_info_t;
 
+static struct console sercons = {
+	name:		"ttyS",
+	write:		serial_console_write,
+	device:		serial_console_device,
+	wait_key:	serial_console_wait_key,
+	setup:		serial_console_setup,
+	flags:		CON_PRINTBUFFER,
+	index:		CONFIG_SERIAL_CONSOLE_PORT,
+};
+
 static void change_speed(ser_info_t *info);
 static void rs_8xx_wait_until_sent(struct tty_struct *tty, int timeout);
 
@@ -325,7 +347,7 @@
 	mark_bh(SERIAL_BH);
 }
 
-static _INLINE_ void receive_chars(ser_info_t *info)
+static _INLINE_ void receive_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 	unsigned char ch, *cp;
@@ -413,7 +435,7 @@
 				}
 				 */
 				status &= info->read_status_mask;
-		
+
 				if (status & (BD_SC_BR)) {
 #ifdef SERIAL_DEBUG_INTR
 					printk("handling break....");
@@ -440,6 +462,17 @@
 					}
 				}
 			}
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+			if (break_pressed && info->line == sercons.index) {
+				if (ch != 0 && time_before(jiffies, 
+							break_pressed + HZ*5)) {
+					handle_sysrq(ch, regs, NULL, NULL);
+					break_pressed = 0;
+					goto ignore_char;
+				} else
+					break_pressed = 0;
+			}
+#endif
 			if (tty->flip.count >= TTY_FLIPBUF_SIZE)
 				break;
 
@@ -448,6 +481,7 @@
 			tty->flip.count++;
 		}
 
+	ignore_char:	
 		/* This BD is ready to be used again.  Clear status.
 		 * Get next BD.
 		 */
@@ -459,17 +493,27 @@
 		else
 			bdp++;
 	}
-
 	info->rx_cur = (cbd_t *)bdp;
 
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void receive_break(ser_info_t *info)
+static _INLINE_ void receive_break(ser_info_t *info, struct pt_regs *regs)
 {
 	struct tty_struct *tty = info->tty;
 
 	info->state->icount.brk++;
+
+#if defined(CONFIG_SERIAL_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
+	if (info->line == sercons.index) {
+		if (!break_pressed) {
+			break_pressed = jiffies;
+			return;
+		} else
+			break_pressed = 0;
+	}
+#endif
+
 	/* Check to see if there is room in the tty buffer for
 	 * the break.  If not, we exit now, losing the break.  FIXME
 	 */
@@ -482,7 +526,7 @@
 	queue_task(&tty->flip.tqueue, &tq_timer);
 }
 
-static _INLINE_ void transmit_chars(ser_info_t *info)
+static _INLINE_ void transmit_chars(ser_info_t *info, struct pt_regs *regs)
 {
 	
 	if ((info->flags & TX_WAKEUP) ||
@@ -571,7 +615,7 @@
 /*
  * This is the serial driver's interrupt routine for a single port
  */
-static void rs_8xx_interrupt(void *dev_id)
+static void rs_8xx_interrupt(void *dev_id, struct pt_regs *regs)
 {
 	u_char	events;
 	int	idx;
@@ -585,21 +629,23 @@
 	if (info->state->smc_scc_num & NUM_IS_SCC) {
 		sccp = &cpmp->cp_scc[idx];
 		events = sccp->scc_scce;
+		if (events & SMCM_BRKE)
+			receive_break(info, regs);
 		if (events & SCCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SCCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		sccp->scc_scce = events;
 	}
 	else {
 		smcp = &cpmp->cp_smc[idx];
 		events = smcp->smc_smce;
 		if (events & SMCM_BRKE)
-			receive_break(info);
+			receive_break(info, regs);
 		if (events & SMCM_RX)
-			receive_chars(info);
+			receive_chars(info, regs);
 		if (events & SMCM_TX)
-			transmit_chars(info);
+			transmit_chars(info, regs);
 		smcp->smc_smce = events;
 	}
 	
@@ -2428,17 +2474,6 @@
 	return MKDEV(TTY_MAJOR, 64 + c->index);
 }
 
-
-static struct console sercons = {
-	name:		"ttyS",
-	write:		serial_console_write,
-	device:		serial_console_device,
-	wait_key:	serial_console_wait_key,
-	setup:		serial_console_setup,
-	flags:		CON_PRINTBUFFER,
-	index:		CONFIG_SERIAL_CONSOLE_PORT,
-};
-
 /*
  *	Register console.
  */
@@ -2771,7 +2806,7 @@
 					immap->im_ioport.iop_padir &= ~iobits;
 					immap->im_ioport.iop_paodr &= ~iobits;
 				}
-#endif
+#endif /* CONFIG_ALTSMC2 */
 
 				/* Connect the baud rate generator to the
 				 * SMC based upon index in rs_table.  Also
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/chrp/main.c linux/arch/ppc/boot/chrp/main.c
--- v2.4.5/linux/arch/ppc/boot/chrp/main.c	Thu May 24 15:02:06 2001
+++ linux/arch/ppc/boot/chrp/main.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.main.c 1.9 06/12/01 16:42:26 paulus
  */
 /*
  * Copyright (C) Paul Mackerras 1997.
@@ -100,13 +100,13 @@
 	    rec->tag = BI_MACHTYPE;
 	    rec->data[0] = _MACH_chrp;
 	    rec->data[1] = 1;
-	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	    rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
 #if 0
 	    rec->tag = BI_SYSMAP;
 	    rec->data[0] = (unsigned long)sysmap_data;
 	    rec->data[1] = sysmap_len;
-	    rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	    rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	    rec = (struct bi_record *)((unsigned long)rec + rec->size);
 #endif
 	    rec->tag = BI_LAST;
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/common/misc-common.c linux/arch/ppc/boot/common/misc-common.c
--- v2.4.5/linux/arch/ppc/boot/common/misc-common.c	Thu May 24 15:02:06 2001
+++ linux/arch/ppc/boot/common/misc-common.c	Mon Jul  2 14:34:57 2001
@@ -38,7 +38,7 @@
 /* If we're on a ALL_PPC, assume we have a keyboard controller
  * Also note, if we're not ALL_PPC, we assume you are a serial
  * console - Tom */
-#ifdef CONFIG_ALL_PPC
+#if defined(CONFIG_ALL_PPC) && defined(CONFIG_VGA_CONSOLE)
 extern void cursor(int x, int y);
 extern void scroll(void);
 extern char *vidmem;
@@ -268,7 +268,7 @@
 	s.zfree = zfree;
 	r = inflateInit2(&s, -MAX_WBITS);
 	if (r != Z_OK) {
-		puts("inflateInit2 returned %d\n");
+		puts("inflateInit2 returned "); puthex(r); puts("\n");
 		exit();
 	}
 	s.next_in = src + i;
@@ -277,7 +277,7 @@
 	s.avail_out = dstlen;
 	r = inflate(&s, Z_FINISH);
 	if (r != Z_OK && r != Z_STREAM_END) {
-		puts("inflate returned %d\n");
+		puts("inflate returned "); puthex(r); puts("\n");
 		exit();
 	}
 	*lenp = s.next_out - (unsigned char *) dst;
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/mbx/Makefile linux/arch/ppc/boot/mbx/Makefile
--- v2.4.5/linux/arch/ppc/boot/mbx/Makefile	Thu May 24 15:02:06 2001
+++ linux/arch/ppc/boot/mbx/Makefile	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch
+# BK Id: SCCS/s.Makefile 1.7 06/05/01 20:20:05 paulus
 #
 #
 # arch/ppc/mbxboot/Makefile
@@ -87,13 +87,21 @@
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
 		--add-section=initrd=../images/ramdisk.image.gz \
 		--add-section=image=../images/vmlinux.gz \
-		$@.tmp ../images/$@.mbx
+		$@.tmp ../images/$@.embedded
 
 zImage: zvmlinux
-	ln -sf zvmlinux.mbx ../images/zImage.mbx
+ifeq ($(CONFIG_RPXCLASSIC),y)
+	dd if=../images/zvmlinux.embedded of=../images/zImage.embedded bs=65536 skip=1
+else
+	ln -sf ../images/zvmlinux.embedded ../images/zImage.embedded
+endif
 
 zImage.initrd: zvmlinux.initrd
-	ln -sf zvmlinux.initrd.mbx ../images/zImage.initrd.mbx
+ifeq ($(CONFIG_RPXCLASSIC),y)
+	dd if=../images/zvmlinux.initrd.embedded of=../images/zImage.initrd.embedded bs=65536 skip=1
+else
+	ln -sf ../images/zvmlinux.initrd.embedded ../images/zImage.initrd.embedded
+endif
 
 zvmlinux: $(OBJECTS) $(LIBS) ../images/vmlinux.gz
 #
@@ -114,14 +122,14 @@
 	$(LD) $(ZLINKFLAGS) -o $@.tmp $(OBJECTS) $(LIBS)
 	$(OBJCOPY) $(OBJCOPY_ARGS) -R .comment \
 		--add-section=image=../images/vmlinux.gz \
-		$@.tmp ../images/$@.mbx
-# Remove zvmlinux and zvmlinux.temp, we have ../images/zvmlinux.mbx
+		$@.tmp ../images/$@.embedded
+# Remove zvmlinux and zvmlinux.temp, we have ../images/zvmlinux.embedded
 	rm -f $@.tmp $@
 
 znetboot : zImage
-	cp ../images/zImage.mbx $(TFTPIMAGE)
+	cp ../images/zImage.embedded $(TFTPIMAGE)
 
 znetboot.initrd : zImage.initrd
-	cp ../images/zImage.initrd.mbx $(TFTPIMAGE)
+	cp ../images/zImage.initrd.embedded $(TFTPIMAGE)
 
 include $(TOPDIR)/Rules.make 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/Makefile linux/arch/ppc/boot/pmac/Makefile
--- v2.4.5/linux/arch/ppc/boot/pmac/Makefile	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/Makefile	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.8 05/21/01 09:10:38 trini
+# BK Id: SCCS/s.Makefile 1.10 06/05/01 20:22:51 paulus
 #
 # Makefile for making XCOFF bootable images for booting on PowerMacs
 # using Open Firmware.
@@ -7,7 +7,7 @@
 #
 # Cleaned up, moved into arch/ppc/boot/pmac
 # Tom Rini		January 2001
- 
+
 OBJCOPY_ARGS = -O aixcoff-rs6000 -R .stab -R .stabstr -R .comment
 COFF_LD_ARGS = -e _start -T ld.script -Ttext 500000 -Tdata 510000 -Bstatic
 CHRP_LD_ARGS = -Ttext 0x01000000
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/chrpmain.c linux/arch/ppc/boot/pmac/chrpmain.c
--- v2.4.5/linux/arch/ppc/boot/pmac/chrpmain.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/chrpmain.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.chrpmain.c 1.9 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.chrpmain.c 1.12 06/12/01 16:42:26 paulus
  */
 /*
  * Copyright (C) Paul Mackerras 1997.
@@ -34,15 +34,6 @@
 
 #define SCRATCH_SIZE	(128 << 10)
 
-#ifdef CONFIG_CMDLINE
-#define CMDLINE CONFIG_CMDLINE
-#else
-#define CMDLINE ""
-#endif
-char cmd_preset[] = CMDLINE;
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
-
 char *avail_ram;
 char *begin_avail, *end_avail;
 char *avail_high;
@@ -98,7 +89,6 @@
     }
 
     flush_cache(dst, len);
-    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
     make_bi_recs((unsigned long) dst + len);
 
     sa = (unsigned long)PROG_START;
@@ -133,19 +123,14 @@
 	rec->tag = BI_MACHTYPE;
 	rec->data[0] = _MACH_Pmac;
 	rec->data[1] = 1;
-	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-
-	rec->tag = BI_CMD_LINE;
-	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
-	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
+	rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
 
 #ifdef SYSMAP_OFFSET
 	rec->tag = BI_SYSMAP;
 	rec->data[0] = SYSMAP_OFFSET;
 	rec->data[1] = SYSMAP_SIZE;
-	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
 #endif /* SYSMAP_OFFSET */
 	
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/coffmain.c linux/arch/ppc/boot/pmac/coffmain.c
--- v2.4.5/linux/arch/ppc/boot/pmac/coffmain.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/coffmain.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.coffmain.c 1.9 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.coffmain.c 1.12 06/12/01 16:42:26 paulus
  */
 /*
  * Copyright (C) Paul Mackerras 1997.
@@ -24,7 +24,7 @@
 #define get_16be(x)	(*(unsigned short *)(x))
 #define get_32be(x)	(*(unsigned *)(x))
 
-#define RAM_START	0xc0000000
+#define RAM_START	0
 #define RAM_END		(RAM_START + 0x800000)	/* only 8M mapped with BATs */
 
 #define PROG_START	RAM_START
@@ -32,15 +32,6 @@
 
 #define SCRATCH_SIZE	(128 << 10)
 
-#ifdef CONFIG_CMDLINE
-#define CMDLINE CONFIG_CMDLINE
-#else
-#define CMDLINE ""
-#endif
-char cmd_preset[] = CMDLINE;
-char cmd_buf[256];
-char *cmd_line = cmd_buf;
-
 char *avail_ram;
 char *begin_avail, *end_avail;
 char *avail_high;
@@ -81,7 +72,7 @@
     claim(0, PROG_SIZE, 0);
     dst = (void *) RAM_START;
     if (im[0] == 0x1f && im[1] == 0x8b) {
-	/* claim some memory for scratch space */
+	/* set up scratch space */
 	begin_avail = avail_high = avail_ram = heap;
 	end_avail = heap + sizeof(heap);
 	printf("heap at 0x%x\n", avail_ram);
@@ -95,7 +86,6 @@
     }
 
     flush_cache(dst, len);
-    memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
     make_bi_recs((unsigned long)dst + len);
     
     sa = (unsigned long)PROG_START;
@@ -127,18 +117,13 @@
 	sprintf( (char *)rec->data, "coffboot");
 	rec->size = sizeof(struct bi_record) + strlen("coffboot") + 1;
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-	    
+
 	rec->tag = BI_MACHTYPE;
 	rec->data[0] = _MACH_Pmac;
 	rec->data[1] = 1;
-	rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+	rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-    
-	rec->tag = BI_CMD_LINE;
-	memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1);
-	rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1;
-	rec = (struct bi_record *)((unsigned long)rec + rec->size);
-    
+
 	rec->tag = BI_LAST;
 	rec->size = sizeof(struct bi_record);
 	rec = (struct bi_record *)((unsigned long)rec + rec->size);
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/pmac/ld.script linux/arch/ppc/boot/pmac/ld.script
--- v2.4.5/linux/arch/ppc/boot/pmac/ld.script	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/pmac/ld.script	Mon Jul  2 14:40:58 2001
@@ -32,6 +32,7 @@
   {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     *(.got1)
   }
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/prep/Makefile linux/arch/ppc/boot/prep/Makefile
--- v2.4.5/linux/arch/ppc/boot/prep/Makefile	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/prep/Makefile	Mon Jul  2 14:34:57 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.15 05/21/01 11:51:32 trini
+# BK Id: SCCS/s.Makefile 1.17 06/12/01 16:47:44 paulus
 #
 # arch/ppc/boot/Makefile
 #
@@ -33,13 +33,17 @@
 endif
 
 ZLINKFLAGS = -T $(TOPDIR)/arch/$(ARCH)/vmlinux.lds -Ttext 0x00800000
-OBJECTS := head.o misc.o vreset.o kbd.o ../common/misc-common.o \
+OBJECTS := head.o misc.o ../common/misc-common.o \
 		../common/string.o of1275.o
 OBJCOPY_ARGS = -O elf32-powerpc
 LIBS = ../lib/zlib.a
 
 ifeq ($(CONFIG_SERIAL_CONSOLE),y)
 OBJECTS += ns16550.o
+endif
+
+ifeq ($(CONFIG_VGA_CONSOLE),y)
+OBJECTS += vreset.o kbd.o
 endif
 
 # Tools
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/prep/misc.c linux/arch/ppc/boot/prep/misc.c
--- v2.4.5/linux/arch/ppc/boot/prep/misc.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/prep/misc.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.misc.c 1.8 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.misc.c 1.14 06/16/01 20:43:20 trini
  */
 /*
  * misc.c
@@ -13,8 +13,9 @@
 #include <linux/types.h>
 #include "zlib.h"
 #include <asm/residual.h>
-#include <linux/elf.h>
 #include <linux/config.h>
+#include <linux/threads.h>
+#include <linux/elf.h>
 #include <linux/pci_ids.h>
 #include <asm/page.h>
 #include <asm/processor.h>
@@ -102,6 +103,7 @@
 	return;
 }
 
+#ifdef CONFIG_VGA_CONSOLE
 void
 scroll()
 {
@@ -111,6 +113,7 @@
 	for ( i = ( lines - 1 ) * cols * 2; i < lines * cols * 2; i += 2 )
 		vidmem[i] = ' ';
 }
+#endif /* CONFIG_VGA_CONSOLE */
 
 /*
  * This routine is used to control the second processor on the 
@@ -170,7 +173,9 @@
 #if defined(CONFIG_SERIAL_CONSOLE)
 	com_port = serial_init(0);
 #endif /* CONFIG_SERIAL_CONSOLE */
-	vga_init((char)0xC0000000);
+#if defined(CONFIG_VGA_CONSOLE)
+	vga_init((unsigned char *)0xC0000000);
+#endif /* CONFIG_VGA_CONSOLE */
 
 	if (residual)
 	{
@@ -360,11 +365,18 @@
 	while (timer++ < 5*1000) {
 		if (tstc()) {
 			while ((ch = getc()) != '\n' && ch != '\r') {
-				if (ch == '\b') {
+				/* Test for backspace/delete */
+				if (ch == '\b' || ch == '\177') {
 					if (cp != cmd_line) {
 						cp--;
 						puts("\b \b");
 					}
+				/* Test for ^x/^u (and wipe the line) */
+				} else if (ch == '\030' || ch == '\025') {
+					while (cp != cmd_line) {
+						cp--;
+						puts("\b \b");
+					}
 				} else {
 					*cp++ = ch;
 					putc(ch);
@@ -393,7 +405,7 @@
 	{
 		struct bi_record *rec;
 	    
-		rec = (struct bi_record *)PAGE_ALIGN(zimage_size);
+		rec = (struct bi_record *)_ALIGN((unsigned long)(zimage_size)+(1<<20)-1,(1<<20));
 	    
 		rec->tag = BI_FIRST;
 		rec->size = sizeof(struct bi_record);
@@ -406,8 +418,8 @@
 	    
 		rec->tag = BI_MACHTYPE;
 		rec->data[0] = _MACH_prep;
-		rec->data[1] = 1;
-		rec->size = sizeof(struct bi_record) + sizeof(unsigned long);
+		rec->data[1] = 0;
+		rec->size = sizeof(struct bi_record) + 2 * sizeof(unsigned long);
 		rec = (struct bi_record *)((unsigned long)rec + rec->size);
 	    
 		rec->tag = BI_CMD_LINE;
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/tree/Makefile linux/arch/ppc/boot/tree/Makefile
--- v2.4.5/linux/arch/ppc/boot/tree/Makefile	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/tree/Makefile	Mon Jul  2 14:34:57 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.5 05/18/01 06:20:29 patch
+# BK Id: SCCS/s.Makefile 1.7 06/15/01 13:16:10 paulus
 #
 #
 #    Module name: Makefile
@@ -26,12 +26,13 @@
 
 GZIP	= gzip -vf9
 RM	= rm -f
-MKEVIMG	= ../utils/mkevimg -l
+MKEVIMG	= ../utils/mkevimg -l -c
 MKIRIMG	= ../utils/mkirimg
+CFLAGS	+= -I$(TOPDIR)/drivers/net
 LD_ARGS = -e _start -T ld.script -Ttext 0x00200000 -Bstatic
 
 OBJS	= ../common/crt0.o main.o misc.o irSect.o ../common/string.o \
-		../common/misc-common.o
+		../common/misc-common.o ../common/ns16550.o
 LIBS	= ../lib/zlib.a
 
 treeboot: $(OBJS) $(LIBS) ld.script
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/tree/ld.script linux/arch/ppc/boot/tree/ld.script
--- v2.4.5/linux/arch/ppc/boot/tree/ld.script	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/tree/ld.script	Mon Jul  2 14:40:58 2001
@@ -32,6 +32,7 @@
   {
     *(.text)
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
     *(.got1)
   }
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/tree/main.c linux/arch/ppc/boot/tree/main.c
--- v2.4.5/linux/arch/ppc/boot/tree/main.c	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/tree/main.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.main.c 1.7 05/18/01 06:20:29 patch
+ * BK Id: SCCS/s.main.c 1.9 06/15/01 13:16:10 paulus
  */
 /*
  *    Copyright (c) 1997 Paul Mackerras <paulus@cs.anu.edu.au>
@@ -74,16 +74,6 @@
 
 #define	ALIGN_UP(x, align)	(((x) + ((align) - 1)) & ~((align) - 1))
 
-#define stringify(s)    tostring(s)
-#define tostring(s)     #s
-
-#define mtdcr(rn, v)    asm volatile("mtdcr " stringify(rn) ",%0" : : "r" (v))
-#define mfdcr(rn)       ({unsigned int rval; \
-                        asm volatile("mfdcr %0," stringify(rn) \
-                                     : "=r" (rval)); rval;})
-#define DCRN_MALCR      0x180   /* MAL Configuration                          */
-#define   MALCR_SR      0x80000000      /* Software Reset                     */
-
 /* Global Variables */
 
 /* Needed by zalloc and zfree for allocating memory */
@@ -91,15 +81,11 @@
 char *avail_ram;	/* Indicates start of RAM available for heap */
 char *end_avail;	/* Indicates end of RAM available for heap */
 
-bd_t	board_info;
-
-/*
- * XXX - Until either the IBM boot ROM provides a way of passing arguments to
- *       the program it launches or until I/O is working in the boot loader,
- *       this is a good spot to pass in command line arguments to the kernel
- *       (e.g. console=tty0).
- */
+/* Needed for serial I/O.
+*/
+extern unsigned long *com_port;
 
+bd_t	board_info;
 
 /*
 ** The bootrom may change bootrom_cmdline to point to a buffer in the
@@ -116,35 +102,16 @@
 
 /* Function Prototypes */
 
-extern void *zalloc(void *x, unsigned items, unsigned size);
-
-/* serial I/O functions.
- * These should have generic names, although this is similar to 16550....
- */
-static volatile unsigned char *uart0_lsr = (unsigned char *)0xef600305;
-static volatile unsigned char *uart0_xcvr = (unsigned char *)0xef600300;
+extern void gunzip(void *dst, int dstlen, unsigned char *src, int *lenp);
 
 void
-serial_putc(void *unused, unsigned char c)
-{
- while ((*uart0_lsr & LSR_THRE) == 0);
- *uart0_xcvr = c;
-}
-
-unsigned char
-serial_getc(void *unused)
-{
- while ((*uart0_lsr & LSR_DR) == 0);
- return (*uart0_xcvr);
-}
-
-int
-serial_tstc(void *unused)
+kick_watchdog(void)
 {
- return ((*uart0_lsr & LSR_DR) != 0);
+#ifdef CONFIG_405GP
+    mtspr(SPRN_TSR, (TSR_ENW | TSR_WIS));
+#endif
 }
 
-
 void start(void)
 {
     void *options;
@@ -156,40 +123,34 @@
     bd_t *(*get_board_info)(void) = 
 	    (bd_t *(*)(void))(*(unsigned long *)BOARD_INFO_VECTOR);
     bd_t *bip = NULL;
-    volatile unsigned long *em0mr0 = (long *)0xEF600800;    /* ftr fixup */
 
 
+    com_port = (struct NS16550 *)serial_init(0);
 
-#if defined(CONFIG_WALNUT)
-    /* turn off ethernet */
+#ifdef CONFIG_405GP
+    /* turn off on-chip ethernet */
     /* This is to fix a problem with early walnut bootrom. */
-
-    mtdcr(DCRN_MALCR, MALCR_SR);                /* 1st reset MAL */
-
-    while (mfdcr(DCRN_MALCR) & MALCR_SR) {};    /* wait for the reset */
-
-    *em0mr0 = 0x20000000;                       /* then reset EMAC */
-#endif
-
-
-#if 0
-    /* ftr revisit - remove printf()s */
-
-    printf("\n\nbootrom_cmdline = >%s<\n\n", bootrom_cmdline);
-    if (*bootrom_cmdline != '\0') {
-	printf("bootrom_cmdline != NULL, copying it into cmdline\n\n");
-	*treeboot_bootrom_cmdline = '\0';
-	strcat(treeboot_bootrom_cmdline, bootrom_cmdline);
-	cmdline = treeboot_bootrom_cmdline;
+ 
+    {
+	/* Physical mapping of ethernet register space. */
+	static struct   ppc405_enet_regs *ppc405_enet_regp =
+	(struct ppc405_enet_regs *)PPC405_EM0_REG_ADDR;
+
+	mtdcr(DCRN_MALCR, MALCR_MMSR);                /* 1st reset MAL */
+
+	while (mfdcr(DCRN_MALCR) & MALCR_MMSR) {};    /* wait for the reset */
+    
+	ppc405_enet_regp->em0mr0 = 0x20000000;        /* then reset EMAC */
     }
 #endif
 
-
     if ((bip = get_board_info()) != NULL)
 	    memcpy(&board_info, bip, sizeof(bd_t));
 
     /* Init RAM disk (initrd) section */
 
+    kick_watchdog();
+
     if (initrdSect_start != 0 && (initrd_size = initrdSect_size) != 0) {
         initrd_start = (RAM_END - initrd_size) & ~0xFFF;
 
@@ -208,6 +169,8 @@
 
     /* Linux kernel image section */
 	
+    kick_watchdog();
+
     im = (unsigned char *)(imageSect_start);
     len = imageSect_size;
     dst = (void *)PROG_START;
@@ -233,6 +196,7 @@
 	memmove(dst, im, len);
     }
 
+    kick_watchdog();
 
     flush_cache(dst, len);
 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/boot/utils/mkevimg linux/arch/ppc/boot/utils/mkevimg
--- v2.4.5/linux/arch/ppc/boot/utils/mkevimg	Thu May 24 15:02:07 2001
+++ linux/arch/ppc/boot/utils/mkevimg	Mon Jul  2 14:34:57 2001
@@ -23,7 +23,8 @@
 #	 unsigned long num_512blocks;   Size, rounded-up, in 512 byte blocks
 #	 unsigned long debug_flag;      Run the debugger or image after load
 #        unsigned long entry_point;	The image address to jump to after load
-#	 unsigned long reserved[3];
+#	 unsigned long checksum; 	32 bit checksum including header
+#	 unsigned long reserved[2];
 #      } boot_block_t;
 #
 #   
@@ -61,6 +62,7 @@
   }
 
   if ($status != 1) {
+    print("  -c         Put checksum in load information block.\n");
     print("  -h         Print out this message and exit.\n");
     print("  -l         Linux mode; if present, copy 'image' and 'initrd' sections.\n");
     print("  -v         Verbose. Print out lots of ELF information.\n");
@@ -148,10 +150,14 @@
 
 sub decode_options {
 
-  if (!getopts("hlvV")) {
+  if (!getopts("chlvV")) {
     usage(1);
   }
 
+  if ($opt_c) {
+    $do_checksum = 1;
+  }
+
   if ($opt_h) {
     usage(0);
   }
@@ -360,14 +366,20 @@
     $output_size += $initrd_size;
   }
 
-  $num_blocks = $output_size / 512 + 1;
+  # 
+  # Compute size with header 
+  #
+
+  $header = pack("H8N7", "0052504f", 0, 0, 0, 0, 0, 0, 0);
+  $num_blocks = ($output_size + length($header) + 511) / 512;
 
   #
   # Write IBM PowerPC evaluation board boot_block_t header
   #
 
   $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0,
-		 $text_addr, 0, 0, 0);
+                 $text_addr, 0, 0, 0);
+
 
   $bytes = length($header);
   
@@ -412,18 +424,57 @@
 
   #
   # Pad to a multiple of 512 bytes
+  #  If the (size of the boot image mod 512) is between 509 and 511 bytes
+  #  then the tftp to the Walnut fails.  This may be fixed in more recent
+  #  Walnut bootrom.
   #
 
-  $pad_size = 512 - (length($header) + $output_size) % 512;
+  $pad_size = 512 - ((length($header) + $output_size) % 512);
+  if ($pad_size == 512) {
+    $pad_size = 0;
+  }
+
+  if ($pad_size != 0) {
+  
+    if ($verbose) {
+      print("Padding boot image by an additional $pad_size bytes.\n");
+    }
+
+    $pad_string = pack("H8","deadbeef") x 128;
+
+    syswrite(BOOT, $pad_string, $pad_size) or
+      die "Could not pad boot image in output file.\n";
 
-  if ($verbose) {
-    print("Padding boot image by an additional $pad_size bytes.\n");
   }
 
-  $pad_string = pack(("H8","deadbeef") x 128);
+  # 
+  # Compute 32 bit checksum over entire file.
+  #
+
+  if ($do_checksum) {
 
-  syswrite(BOOT, $pad_string, $pad_size) or
-    die "Could not pad boot image in output file.\n";
+    close(BOOT);
+    open(BOOT, "+<$ofile") || die "Cannot open output file";
+    undef $/;
+    $temp = unpack("%32N*", <BOOT>);
+    # Solaris and PPC Linux return 0x80000000 for "-$temp" when $temp
+    # is negative.  "~($temp - 1)" negates $temp properly.
+    $csum = ~($temp - 1);
+    printf("Checksum    = 0x%08x\r\n", $csum);
+
+    #
+    # Rewrite IBM PowerPC evaluation board boot_block_t header,
+    # this time with the checksum included
+    #
+
+    $header = pack("H8N7", "0052504f", $text_addr, $num_blocks, 0,
+                    $text_addr, $csum, 0, 0);
+
+    seek(BOOT, 0, 0);
+    syswrite(BOOT, $header, length($header)) or
+         die("Could not write boot image header to output file.");
+
+  }
 
   #
   # Clean-up and leave
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/config.in linux/arch/ppc/config.in
--- v2.4.5/linux/arch/ppc/config.in	Tue May 22 10:23:16 2001
+++ linux/arch/ppc/config.in	Mon Jul  2 14:34:57 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.config.in 1.24 05/21/01 00:48:24 cort
+# BK Id: SCCS/s.config.in 1.30 06/27/01 14:49:58 trini
 #
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
@@ -84,9 +84,9 @@
 
 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ]; then
   choice 'Machine Type'		\
-	"PowerMac/PReP/MTX/CHRP	CONFIG_ALL_PPC	\
-	 Gemini         CONFIG_GEMINI           \
-	 APUS		CONFIG_APUS"		PowerMac/PReP/MTX/CHRP
+	"CHRP/PowerMac/PReP	CONFIG_ALL_PPC		\
+  	 Amgia-APUS		CONFIG_APUS		\
+	 Synergy-Gemini        	CONFIG_GEMINI"		CHRP/PowerMac/PReP
 fi
 
 if [ "$CONFIG_PPC64BRIDGE" != "y" ]; then
@@ -364,6 +364,10 @@
 fi
 
 source drivers/usb/Config.in
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   source net/bluetooth/Config.in
+fi
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.4.5/linux/arch/ppc/kernel/Makefile	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/kernel/Makefile	Mon Jul  2 14:34:57 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.17 05/21/01 00:48:24 cort
+# BK Id: SCCS/s.Makefile 1.22 06/28/01 08:01:06 trini
 #
 #
 # Makefile for the linux kernel.
@@ -32,18 +32,14 @@
 export-objs			:= ppc_ksyms.o prep_setup.o 
 
 obj-y				:= entry.o traps.o irq.o idle.o time.o misc.o \
-					process.o signal.o bitops.o ptrace.o \
+					process.o signal.o ptrace.o \
 					ppc_htab.o semaphore.o syscalls.o  \
 					align.o setup.o
 obj-$(CONFIG_MODULES)		+= ppc_ksyms.o
 obj-$(CONFIG_POWER4)		+= xics.o
 obj-$(CONFIG_PCI)		+= pci.o pci-dma.o
 obj-$(CONFIG_KGDB)		+= ppc-stub.o
-obj-$(CONFIG_PMAC_PBOOK)	+= sleep.o
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_PPC_RTAS)		+= error_log.o proc_rtas.o
-obj-$(CONFIG_NVRAM)		+= pmac_nvram.o
-obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
 obj-$(CONFIG_4xx)		+= ppc4xx_pic.o
 obj-$(CONFIG_OAK)		+= oak_setup.o
 obj-$(CONFIG_WALNUT)		+= walnut_setup.o
@@ -52,12 +48,10 @@
 endif
 obj-$(CONFIG_8xx)		+= m8xx_setup.o ppc8xx_pic.o
 ifeq ($(CONFIG_8xx),y)
-obj-$(CONFIG_PCI)		+= qspan_pci.c
+obj-$(CONFIG_PCI)		+= qspan_pci.o
 ifndef CONFIG_MATH_EMULATION
 obj-y				+= softemu8xx.o
 endif
-else
-obj-y				+= hashtable.o
 endif
 obj-$(CONFIG_MBX)		+= i8259.o
 obj-$(CONFIG_APUS)		+= apus_setup.o
@@ -69,7 +63,11 @@
 					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_PPC_RTAS)		+= error_log.o proc_rtas.o
+obj-$(CONFIG_PREP_RESIDUAL)	+= residual.o
 obj-$(CONFIG_GEMINI)		+= gemini_prom.o gemini_pci.o gemini_setup.o \
 					open_pic.o
 obj-$(CONFIG_8260)		+= m8260_setup.o ppc8260_pic.o
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/chrp_pci.c linux/arch/ppc/kernel/chrp_pci.c
--- v2.4.5/linux/arch/ppc/kernel/chrp_pci.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/kernel/chrp_pci.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.chrp_pci.c 1.16 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.chrp_pci.c 1.17 06/28/01 16:11:56 paulus
  */
 /*
  * CHRP pci routines.
@@ -27,11 +27,6 @@
 #include "open_pic.h"
 #include "pci.h"
 
-
-#ifdef CONFIG_POWER4
-extern unsigned long pci_address_offset(int, unsigned int);
-#endif /* CONFIG_POWER4 */
-
 /* LongTrail */
 #define pci_config_addr(dev, offset) \
 (GG2_PCI_CONFIG_BASE | ((dev->bus->number)<<16) | ((dev->devfn)<<8) | (offset))
@@ -212,34 +207,6 @@
 	return 1;
 }
 
-#ifdef CONFIG_POWER4
-static void
-power4_fixup_dev(struct pci_dev *dev)
-{
-	int i;
-	unsigned long offset;
-
-	for (i = 0; i < 6; ++i) {
-		if (dev->resource[i].start == 0)
-			continue;
-		offset = pci_address_offset(dev->bus->number,
-					    dev->resource[i].flags);
-		if (offset) {
-			dev->resource[i].start += offset;
-			dev->resource[i].end += offset;
-			printk("device %x.%x[%d] now [%lx..%lx]\n",
-			       dev->bus->number, dev->devfn, i,
-			       dev->resource[i].start,
-			       dev->resource[i].end);
-		}
-		/* zap the 2nd function of the winbond chip */
-		if (dev->resource[i].flags & IORESOURCE_IO
-		    && dev->bus->number == 0 && dev->devfn == 0x81)
-			dev->resource[i].flags &= ~IORESOURCE_IO;
-	}
-}
-#endif /* CONFIG_POWER4 */
-
 void __init
 chrp_pcibios_fixup(void)
 {
@@ -261,48 +228,9 @@
 			pci_write_config_word(dev, PCI_VENDOR_ID,
 					      PCI_VENDOR_ID_AMD);
 		}
-#ifdef CONFIG_POWER4
-		power4_fixup_dev(dev);
-#endif
 	}
 }
 
-#if 0
-static struct {
-    /* parent is iomem */
-    struct resource ram, pci_mem, isa_mem, pci_io, pci_cfg, rom_exp, flash;
-    /* parent is isa_mem */
-    struct resource nvram;
-} gg2_resources = {
-    ram:	{ "RAM", 0x00000000, 0xbfffffff, IORESOURCE_MEM },
-    pci_mem:	{ "GG2 PCI mem", 0xc0000000, 0xf6ffffff, IORESOURCE_MEM },
-    isa_mem:	{ "GG2 ISA mem", 0xf7000000, 0xf7ffffff },
-    pci_io:	{ "GG2 PCI I/O", 0xf8000000, 0xf8ffffff },
-    pci_cfg:	{ "GG2 PCI cfg", 0xfec00000, 0xfec7ffff },
-    rom_exp:	{ "ROM exp", 0xff000000, 0xff7fffff, },
-    flash:	{ "Flash ROM", 0xfff80000, 0xffffffff },
-    nvram:	{ "NVRAM", 0xf70e0000, 0xf70e7fff },
-};
-
-static void __init gg2_pcibios_fixup(void)
-{
-	int i;
-	extern unsigned long *end_of_DRAM;
-
-	chrp_pcibios_fixup();
-	gg2_resources.ram.end = (unsigned long)end_of_DRAM-PAGE_OFFSET;
-	for (i = 0; i < 7; i++)
-	    request_resource(&iomem_resource,
-		    	     &((struct resource *)&gg2_resources)[i]);
-	request_resource(&gg2_resources.isa_mem, &gg2_resources.nvram);
-}
-
-static void __init gg2_pcibios_fixup_bus(struct pci_bus *bus)
-{
-    	bus->resource[1] = &gg2_resources.pci_mem;
-}
-#endif /* 0 */
-
 /* this is largely modeled and stolen after the pmac_pci code -- tgall
  */
 
@@ -314,14 +242,16 @@
 	struct pci_controller *hose;
 	volatile unsigned char *cfg;
 	unsigned int *dma;
-#ifdef CONFIG_POWER3
 	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
 
 	for(; dev != NULL; dev = dev->next, ++index) {
+		if (dev->parent != root)
+			continue;
 		if (dev->n_addrs < 1) {
 			printk(KERN_WARNING "Can't use %s: no address\n",
 			       dev->full_name);
@@ -374,23 +304,6 @@
 	}
 }
 
-#ifdef CONFIG_POWER4
-void __init
-power4_add_bridge(void)
-{
-	struct pci_controller* hose;
-
-	hose = pcibios_alloc_controller();
-	if (!hose)
-		return;
-	hose->first_busno = 0;
-	hose->last_busno = 0xff;
-	
-	hose->ops = &rtas_pci_ops;
-	pci_dram_offset = 0;
-}
-#endif /* CONFIG_POWER4 */
-
 void __init
 chrp_find_bridges(void)
 {
@@ -400,9 +313,6 @@
 
 	ppc_md.pcibios_fixup = chrp_pcibios_fixup;
 
-#ifdef CONFIG_POWER4
-	power4_add_bridge();
-#else /* CONFIG_POWER4 */
 	model = get_property(find_path_device("/"), "model", NULL);
         if (!strncmp("MOT", model, 3)) {
 		struct pci_controller *hose;
@@ -452,36 +362,4 @@
 	hose->ops = &gg2_pci_ops;
 	pci_dram_offset = 0;
 	pci_process_bridge_OF_ranges(hose, find_devices("pci"), 1);
-//	ppc_md.pcibios_fixup = gg2_pcibios_fixup;
-//	ppc_md.pcibios_fixup_bus = gg2_pcibios_fixup_bus;
-#endif /* CONFIG_POWER4 */
 }
-
-#ifdef CONFIG_PPC64BRIDGE
-#ifdef CONFIG_POWER4
-/*
- * Hack alert!!!
- * 64-bit machines like POWER3 and POWER4 have > 32 bit
- * physical addresses.  For now we remap particular parts
- * of the 32-bit physical address space that the Linux
- * page table gives us into parts of the physical address
- * space above 4GB so we can access the I/O devices.
- */
-unsigned long pci_address_offset(int busnr, unsigned int flags)
-{
-	unsigned long offset = 0;
-
-	if (busnr >= 0x1e) {
-		if (flags & IORESOURCE_IO)
-			offset = -0x100000;
-		else if (flags & IORESOURCE_MEM)
-			offset = 0x38000000;
-	} else if (busnr <= 0xf) {
-		if (flags & IORESOURCE_MEM)
-			offset = -0x40000000;
-		else
-	}
-	return offset;
-}
-#endif /* CONFIG_POWER4 */
-#endif /* CONFIG_PPC64BRIDGE */
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.4.5/linux/arch/ppc/kernel/chrp_setup.c	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/kernel/chrp_setup.c	Mon Jun 11 19:15:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.chrp_setup.c 1.17 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.chrp_setup.c 1.20 06/05/01 21:22:02 paulus
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -204,13 +204,10 @@
 	active = sio_read(0x30);
 	level0 = sio_read(0x70);
 	type0 = sio_read(0x71);
-	printk("sio: %s irq level %d, type %d, %sactive: ", name, level0,
-	       type0, !active ? "in" : "");
-	if (level0 == level && type0 == type && active)
-		printk("OK\n");
-	else {
-		printk("remapping to level %d, type %d, active\n", level,
-		       type);
+	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);
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
--- v2.4.5/linux/arch/ppc/kernel/entry.S	Mon May 21 17:04:46 2001
+++ linux/arch/ppc/kernel/entry.S	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.entry.S 1.12 05/21/01 11:49:59 paulus
+ * BK Id: SCCS/s.entry.S 1.17 06/19/01 22:40:51 paulus
  */
 /*
  *  PowerPC version 
@@ -283,6 +283,7 @@
 	 */ 
 	mfmsr	r0		/* Get current interrupt state */
 	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */
+	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0		/* Update machine state */
 	
 	lwz	r0,_MSR(r1)
@@ -310,25 +311,7 @@
 	beq	restore
 	.globl	ret_from_except
 ret_from_except:
-	lwz	r5,_MSR(r1)
-	andi.	r5,r5,MSR_EE
-	beq	2f
-	lis	r4,irq_stat@ha		/* &softirq_active for cpu 0 */
-	addi	r4,r4,irq_stat@l
-#ifdef CONFIG_SMP
-	/* get processor # */
-	lwz	r3,PROCESSOR(r2)
-	slwi	r3,r3,LG_CACHE_LINE_SIZE
-	add	r4,r4,r3
-#endif /* CONFIG_SMP */
-	lwz	r5,0(r4)		/* softirq_active */
-	lwz	r4,4(r4)		/* softirq_mask */
-	and.	r5,r5,r4
-	beq+	2f
-	bl	do_softirq
-	.globl	do_bottom_half_ret
-do_bottom_half_ret:
-2:	lwz	r3,_MSR(r1)	/* Returning to user mode? */
+	lwz	r3,_MSR(r1)	/* Returning to user mode? */
 	andi.	r3,r3,MSR_PR
 	beq+	do_signal_ret	/* if so, check need_resched and signals */
 	lwz	r3,NEED_RESCHED(r2)
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/feature.c linux/arch/ppc/kernel/feature.c
--- v2.4.5/linux/arch/ppc/kernel/feature.c	Fri May 25 12:41:46 2001
+++ linux/arch/ppc/kernel/feature.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.feature.c 1.10 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.feature.c 1.14 06/17/01 09:33:37 trini
  */
 /*
  *  arch/ppc/kernel/feature.c
@@ -288,11 +288,11 @@
   {	"AAPL,PowerBook1998",	FTR_CAN_SLEEP			}, /* Wallstreet PowerBook */
   {	"PowerBook1,1",		FTR_CAN_SLEEP			}, /* 101 (Lombard) PowerBook */
   {	"PowerBook2,1",		FTR_CAN_SLEEP 			}, /* iBook */
+  {	"PowerBook4,1",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* iBook Dual USB */
   {	"PowerBook2,2",		FTR_CAN_SLEEP /*| FTR_CAN_NAP*/	}, /* iBook FireWire */
   {	"PowerBook3,1",		FTR_CAN_SLEEP|FTR_CAN_NAP|	   /* PowerBook 2000 (Pismo) */
   				FTR_HAS_FW_POWER		}, 
   {	"PowerBook3,2",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* PowerBook Titanium */
-  {	"PowerBook4,1",		FTR_CAN_NAP|FTR_CAN_SLEEP	}, /* New polycarbonate iBook */
   {	NULL, 0 }
 };
 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/hashtable.S linux/arch/ppc/kernel/hashtable.S
--- v2.4.5/linux/arch/ppc/kernel/hashtable.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/hashtable.S	Wed Dec 31 16:00:00 1969
@@ -1,724 +0,0 @@
-/*
- * BK Id: SCCS/s.hashtable.S 1.11 05/17/01 18:14:21 cort
- */
-/*
- *  arch/ppc/kernel/hashtable.S
- *
- *  PowerPC version 
- *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
- *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
- *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
- *  Adapted for Power Macintosh by Paul Mackerras.
- *  Low-level exception handlers and MMU support
- *  rewritten by Paul Mackerras.
- *    Copyright (C) 1996 Paul Mackerras.
- *
- *  This file contains low-level assembler routines for managing
- *  the PowerPC MMU hash table.  (PPC 8xx processors don't use a
- *  hash table, so this file is not used on them.)
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *	
- */
-
-#include "ppc_asm.h"
-#include <asm/processor.h>
-#include <asm/page.h>
-#include <linux/config.h>
-
-/*
- * Load a PTE into the hash table, if possible.
- * The address is in r3, and r4 contains access flags:
- * _PAGE_USER (4) if a user-mode access, ored with
- * _PAGE_RW (2) if a write.  r20 contains DSISR or SRR1,
- * so bit 1 (0x40000000) is set if the exception was due
- * to no matching PTE being found in the hash table.
- * SPRG3 contains the physical address of the current task's thread.
- *
- * Returns to the caller if the access is illegal or there is no
- * mapping for the address.  Otherwise it places an appropriate PTE
- * in the hash table and returns from the exception.
- * Uses r0, r2 - r6, ctr, lr.
- *
- * For speed, 4 of the instructions get patched once the size and
- * physical address of the hash table are known.  These definitions
- * of Hash_base and Hash_bits below are just an example.
- */
-Hash_base = 0x180000
-Hash_bits = 12				/* e.g. 256kB hash table */
-Hash_msk = (((1 << Hash_bits) - 1) * 64)
-	
-	.globl	hash_page
-hash_page:
-#ifdef CONFIG_PPC64BRIDGE
-	mfmsr	r0
-	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
-	MTMSRD(r0)
-	isync
-#endif
-#ifdef CONFIG_SMP
-	SAVE_2GPRS(7,r21)
-	eieio
-	lis	r2,hash_table_lock@h
-	ori	r2,r2,hash_table_lock@l
- 	tophys(r2,r2)
-	lis	r6,0x0fff0000@h
-	mtctr	r6
-	mfspr	r5,SPRG3
-	lwz	r0,PROCESSOR-THREAD(r5)
-	or	r0,r0,r6
-10:	lwarx	r6,0,r2
-	cmpi	0,r6,0
-	bne-	12f
-	stwcx.	r0,0,r2
-	beq+	11f
-	/* spin here a bit */
-12:	mfctr	r7
-	li	r8,1000
-	mtctr	r8
-13:
-	bdnz	13b
-	mtctr	r7
-	cmpw	r6,r0
-	bdnzf	2,10b
-	tw	31,31,31
-11:	eieio
-	REST_2GPRS(7, r21)
-#endif
-	/* Get PTE (linux-style) and check access */
-	lis	r0,KERNELBASE@h		/* check if kernel address */
-	cmplw	0,r3,r0
-	mfspr	r2,SPRG3		/* current task's THREAD (phys) */
-	lwz	r5,PGDIR(r2)		/* virt page-table root */
-	blt+	112f			/* assume user more likely */
-	lis	r5,swapper_pg_dir@ha	/* if kernel address, use */
-	addi	r5,r5,swapper_pg_dir@l	/* kernel page table */
-112:	tophys(r5,r5)			/* convert to phys addr */
-	rlwimi	r5,r3,12,20,29		/* insert top 10 bits of address */
-	lwz	r5,0(r5)		/* get pmd entry */
-	rlwinm.	r5,r5,0,0,19		/* extract address of pte page */
-#ifdef CONFIG_SMP
-	beq-	hash_page_out		/* return if no mapping */
-#else
-	/* XXX it seems like the 601 will give a machine fault on the
-	   rfi if its alignment is wrong (bottom 4 bits of address are
-	   8 or 0xc) and we have had a not-taken conditional branch
-	   to the address following the rfi. */
-	beqlr-
-#endif
-	tophys(r2,r5)
-	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	ori	r4,r4,1			/* set _PAGE_PRESENT bit in access */
-	rlwinm	r5,r4,5,24,24		/* _PAGE_RW access -> _PAGE_DIRTY */
-	rlwimi	r5,r4,7,22,22		/* _PAGE_RW -> _PAGE_HWWRITE */
-	ori	r5,r5,0x100		/* set _PAGE_ACCESSED */
-retry:
-	lwz	r6,0(r2)		/* get linux-style pte */
-	andc.	r0,r4,r6		/* check access & ~permission */
-#ifdef CONFIG_SMP
-	bne-	hash_page_out		/* return if access not permitted */
-#else
-	bnelr-
-#endif
-	andc.	r0,r5,r6		/* any bits not yet set? */
-	beq	2f
-
-	/* Update the linux PTE atomically */
-	lwarx	r0,0,r2			/* refetch the pte and check */
-	cmpw	0,r0,r6			/* that it hasn't been changed */
-	bne-	retry			/* retry if it has */
-	or	r6,r6,r5		/* set accessed/dirty bits */
-	stwcx.	r6,0,r2			/* attempt to update PTE */
-	bne-	retry			/* retry if someone got there first */
-
-	/* Convert linux-style PTE to low word of PPC-style PTE */
-2:	rlwinm	r4,r6,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r6,r6,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r4,r4,0xe04		/* clear out reserved bits */
-	andc	r6,r6,r4		/* PP=2 or 0, when _PAGE_HWWRITE */
-
-#ifdef CONFIG_POWER4
-	/*
-	 * XXX hack hack hack - translate 32-bit "physical" addresses
-	 * in the linux page tables to 42-bit real addresses in such
-	 * a fashion that we can get at the I/O we need to access.
-	 *	-- paulus
-	 */
-	cmpwi	0,r6,0
-	rlwinm	r4,r6,16,16,30
-	bge	57f
-	cmplwi	0,r4,0xfe00
-	li	r5,0x3fd
-	bne	56f
-	li	r5,0x3ff
-56:	sldi	r5,r5,32
-	or	r6,r6,r5
-57:
-#endif
-
-#ifdef CONFIG_PPC64BRIDGE
-	/* Construct the high word of the PPC-style PTE */
-	mfsrin	r5,r3			/* get segment reg for segment */
-	rlwinm	r5,r5,0,5,31
-	sldi	r5,r5,12
-	ori	r5,r5,1			/* set V (valid) bit */
-	rlwimi	r5,r3,16,20,24		/* put in API (abbrev page index) */
-	/* Get the address of the primary PTE group in the hash table */
-	.globl	hash_page_patch_A
-hash_page_patch_A:
-	lis	r4,Hash_base@h		/* base address of hash table */
-	rlwimi	r4,r5,32-5,25-Hash_bits,24	/* (VSID & hash_mask) << 7 */
-	rlwinm	r0,r3,32-5,25-Hash_bits,24	/* (PI & hash_mask) << 7 */
-	xor	r4,r4,r0		/* make primary hash */
-	li	r2,8			/* PTEs/group */
-
-#ifndef CONFIG_SMP
-	/* We don't do this for SMP - another cpu could have put in
-	   the appropriate PTE since we took the exception.  -- paulus. */
-	/* See whether it was a PTE not found exception or a
-	   protection violation. */
-	andis.	r0,r20,0x4000
-	bne	10f			/* no PTE: go look for an empty slot */
-#endif /* CONFIG_SMP */
-	tlbie	r3			/* invalidate TLB entry */
-
-	/* Search the primary PTEG for a PTE whose 1st dword matches r5 */
-	mtctr	r2
-	addi	r3,r4,-16
-1:	ldu	r0,16(r3)		/* get next PTE */
-	cmpd	0,r0,r5
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_slot
-
-	/* Search the secondary PTEG for a matching PTE */
-	ori	r5,r5,0x2		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_B
-hash_page_patch_B:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xff80
-	addi	r3,r3,-16
-	mtctr	r2
-2:	ldu	r0,16(r3)
-	cmpd	0,r0,r5
-	bdnzf	2,2b
-	beq+	found_slot
-	xori	r5,r5,0x2		/* clear H bit again */
-
-	/* Search the primary PTEG for an empty slot */
-10:	mtctr	r2
-	addi	r3,r4,-16		/* search primary PTEG */
-1:	ldu	r0,16(r3)		/* get next PTE */
-	andi.	r0,r0,1
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_empty
-
-	/* Search the secondary PTEG for an empty slot */
-	ori	r5,r5,0x2		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_C
-hash_page_patch_C:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xff80
-	addi	r3,r3,-16
-	mtctr	r2
-2:	ldu	r0,16(r3)
-	andi.	r0,r0,1
-	bdnzf	2,2b
-	beq+	found_empty
-
-	/*
-	 * Choose an arbitrary slot in the primary PTEG to overwrite.
-	 * Since both the primary and secondary PTEGs are full, and we
-	 * have no information that the PTEs in the primary PTEG are
-	 * more important or useful than those in the secondary PTEG,
-	 * and we know there is a definite (although small) speed
-	 * advantage to putting the PTE in the primary PTEG, we always
-	 * put the PTE in the primary PTEG.
-	 */
-	xori	r5,r5,0x2		/* clear H bit again */
-	lis	r3,next_slot@ha
-	tophys(r3,r3)
-	lwz	r2,next_slot@l(r3)
-	addi	r2,r2,16
-	andi.	r2,r2,0x70
-#ifdef CONFIG_POWER4
-	/*
-	 * Since we don't have BATs on POWER4, we rely on always having
-	 * PTEs in the hash table to map the hash table and the code
-	 * that manipulates it in virtual mode, namely flush_hash_page and
-	 * flush_hash_segments.  Otherwise we can get a DSI inside those
-	 * routines which leads to a deadlock on the hash_table_lock on
-	 * SMP machines.  We avoid this by never overwriting the first
-	 * PTE of each PTEG if it is already valid.
-	 *	-- paulus.
-	 */
-	bne	102f
-	li	r2,0x10
-102:
-#endif /* CONFIG_POWER4 */
-	stw	r2,next_slot@l(r3)
-	add	r3,r4,r2
-11:
-	/* update counter of evicted pages */
-	lis	r2,htab_evicts@ha
-	tophys(r2,r2)
-	lwz	r4,htab_evicts@l(r2)
-	addi	r4,r4,1
-	stw	r4,htab_evicts@l(r2)
-
-#ifndef CONFIG_SMP
-	/* Store PTE in PTEG */
-found_empty:
-	std	r5,0(r3)
-found_slot:
-	std	r6,8(r3)
-
-#else /* CONFIG_SMP */
-/*
- * Between the tlbie above and updating the hash table entry below,
- * another CPU could read the hash table entry and put it in its TLB.
- * There are 3 cases:
- * 1. using an empty slot
- * 2. updating an earlier entry to change permissions (i.e. enable write)
- * 3. taking over the PTE for an unrelated address
- *
- * In each case it doesn't really matter if the other CPUs have the old
- * PTE in their TLB.  So we don't need to bother with another tlbie here,
- * which is convenient as we've overwritten the register that had the
- * address. :-)  The tlbie above is mainly to make sure that this CPU comes
- * and gets the new PTE from the hash table.
- *
- * We do however have to make sure that the PTE is never in an invalid
- * state with the V bit set.
- */
-found_empty:
-found_slot:
-	li	r0,1
-	andc	r5,r5,r0	/* clear V (valid) bit in PTE */
-	std	r5,0(r3)
-	sync
-	tlbsync
-	sync
-	std	r6,8(r3)	/* put in correct RPN, WIMG, PP bits */
-	sync
-	ori	r5,r5,1
-	std	r5,0(r3)	/* finally set V bit in PTE */
-#endif /* CONFIG_SMP */
-
-#else /* CONFIG_PPC64BRIDGE */
-
-	/* Construct the high word of the PPC-style PTE */
-	mfsrin	r5,r3			/* get segment reg for segment */
-	rlwinm	r5,r5,7,1,24		/* put VSID in 0x7fffff80 bits */
-	oris	r5,r5,0x8000		/* set V (valid) bit */
-	rlwimi	r5,r3,10,26,31		/* put in API (abbrev page index) */
-	/* Get the address of the primary PTE group in the hash table */
-	.globl	hash_page_patch_A
-hash_page_patch_A:
-	lis	r4,Hash_base@h		/* base address of hash table */
-	rlwimi	r4,r5,32-1,26-Hash_bits,25	/* (VSID & hash_mask) << 6 */
-	rlwinm	r0,r3,32-6,26-Hash_bits,25	/* (PI & hash_mask) << 6 */
-	xor	r4,r4,r0		/* make primary hash */
-	li	r2,8			/* PTEs/group */
-
-#ifndef CONFIG_SMP
-	/* We don't do this for SMP - another cpu could have put in
-	   the appropriate PTE since we took the exception.  -- paulus. */
-	/* See whether it was a PTE not found exception or a
-	   protection violation. */
-	andis.	r0,r20,0x4000
-	bne	10f			/* no PTE: go look for an empty slot */
-#endif /* CONFIG_SMP */
-	tlbie	r3			/* invalidate TLB entry */
-
-	/* Search the primary PTEG for a PTE whose 1st word matches r5 */
-	mtctr	r2
-	addi	r3,r4,-8
-1:	lwzu	r0,8(r3)		/* get next PTE */
-	cmp	0,r0,r5
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_slot
-
-	/* Search the secondary PTEG for a matching PTE */
-	ori	r5,r5,0x40		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_B
-hash_page_patch_B:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xffc0
-	addi	r3,r3,-8
-	mtctr	r2
-2:	lwzu	r0,8(r3)
-	cmp	0,r0,r5
-	bdnzf	2,2b
-	beq+	found_slot
-	xori	r5,r5,0x40		/* clear H bit again */
-
-	/* Search the primary PTEG for an empty slot */
-10:	mtctr	r2
-	addi	r3,r4,-8		/* search primary PTEG */
-1:	lwzu	r0,8(r3)		/* get next PTE */
-	rlwinm.	r0,r0,0,0,0		/* only want to check valid bit */
-	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
-	beq+	found_empty
-
-	/* Search the secondary PTEG for an empty slot */
-	ori	r5,r5,0x40		/* set H (secondary hash) bit */
-	.globl	hash_page_patch_C
-hash_page_patch_C:
-	xoris	r3,r4,Hash_msk>>16	/* compute secondary hash */
-	xori	r3,r3,0xffc0
-	addi	r3,r3,-8
-	mtctr	r2
-2:
-	lwzu	r0,8(r3)
-	rlwinm.	r0,r0,0,0,0		/* only want to check valid bit */
-	bdnzf	2,2b
-	beq+	found_empty
-
-	/*
-	 * Choose an arbitrary slot in the primary PTEG to overwrite.
-	 * Since both the primary and secondary PTEGs are full, and we
-	 * have no information that the PTEs in the primary PTEG are
-	 * more important or useful than those in the secondary PTEG,
-	 * and we know there is a definite (although small) speed
-	 * advantage to putting the PTE in the primary PTEG, we always
-	 * put the PTE in the primary PTEG.
-	 */
-	xori	r5,r5,0x40		/* clear H bit again */
-	lis	r3,next_slot@ha
-	tophys(r3,r3)
-	lwz	r2,next_slot@l(r3)
-	addi	r2,r2,8
-	andi.	r2,r2,0x38
-	stw	r2,next_slot@l(r3)
-	add	r3,r4,r2
-11:		
-	/* update counter of evicted pages */
-	lis	r2,htab_evicts@ha
-	tophys(r2,r2)
-	lwz	r4,htab_evicts@l(r2)
-	addi	r4,r4,1
-	stw	r4,htab_evicts@l(r2)
-
-#ifndef CONFIG_SMP
-	/* Store PTE in PTEG */
-found_empty:
-	stw	r5,0(r3)
-found_slot:
-	stw	r6,4(r3)
-
-#else /* CONFIG_SMP */
-/*
- * Between the tlbie above and updating the hash table entry below,
- * another CPU could read the hash table entry and put it in its TLB.
- * There are 3 cases:
- * 1. using an empty slot
- * 2. updating an earlier entry to change permissions (i.e. enable write)
- * 3. taking over the PTE for an unrelated address
- *
- * In each case it doesn't really matter if the other CPUs have the old
- * PTE in their TLB.  So we don't need to bother with another tlbie here,
- * which is convenient as we've overwritten the register that had the
- * address. :-)  The tlbie above is mainly to make sure that this CPU comes
- * and gets the new PTE from the hash table.
- *
- * We do however have to make sure that the PTE is never in an invalid
- * state with the V bit set.
- */
-found_empty:
-found_slot:
-	rlwinm	r5,r5,0,1,31	/* clear V (valid) bit in PTE */
-	stw	r5,0(r3)
-	sync
-	tlbsync
-	sync
-	stw	r6,4(r3)	/* put in correct RPN, WIMG, PP bits */
-	sync
-	oris	r5,r5,0x8000
-	stw	r5,0(r3)	/* finally set V bit in PTE */
-#endif /* CONFIG_SMP */
-#endif /* CONFIG_PPC64BRIDGE */
-
-	sync		/* make sure pte updates get to memory */
-
-/*
- * Update the hash table miss count.  We only want misses here
- * that _are_ valid addresses and have a pte otherwise we don't
- * count it as a reload.  do_page_fault() takes care of bad addrs
- * and entries that need linux-style pte's created.
- *
- * safe to use r2 here since we're not using it as current yet 
- * update the htab misses count
- *   -- Cort
- */
-	lis	r2,htab_reloads@ha
-	tophys(r2,r2)
-	lwz	r3,htab_reloads@l(r2)
-	addi	r3,r3,1
-	stw	r3,htab_reloads@l(r2)
-
-#ifdef CONFIG_SMP
-	lis	r2,hash_table_lock@ha
-	tophys(r2,r2)
-	li	r0,0
-	stw	r0,hash_table_lock@l(r2)
-	eieio
-#endif
-
-	/* Return from the exception */
-	lwz	r3,_CCR(r21)
-	lwz	r4,_LINK(r21)
-	lwz	r5,_CTR(r21)
-	mtcrf	0xff,r3
-	mtlr	r4
-	mtctr	r5
-	lwz	r0,GPR0(r21)
-	lwz	r1,GPR1(r21)
-	lwz	r2,GPR2(r21)
-	lwz	r3,GPR3(r21)
-	lwz	r4,GPR4(r21)
-	lwz	r5,GPR5(r21)
-	lwz	r6,GPR6(r21)
-	/* we haven't used xer */
-	mtspr	SRR1,r23
-	mtspr	SRR0,r22
-	lwz	r20,GPR20(r21)
-	lwz	r22,GPR22(r21)
-	lwz	r23,GPR23(r21)
-	lwz	r21,GPR21(r21)
-	RFI
-	
-#ifdef CONFIG_SMP
-hash_page_out:
-	lis	r2,hash_table_lock@ha
-	tophys(r2,r2)
-	li	r0,0
-	stw	r0,hash_table_lock@l(r2)
-	eieio
-	blr
-
-	.data
-	.globl	hash_table_lock
-hash_table_lock:
-	.long	0
-#endif /* CONFIG_SMP */
-
-	.data
-next_slot:
-	.long	0
-
-	.text
-/*
- * Flush entries from the hash table with VSIDs in the range
- * given.
- */
-_GLOBAL(flush_hash_segments)
-	lis	r5,Hash@ha
-	lwz	r5,Hash@l(r5)		/* base of hash table */
-	cmpwi	0,r5,0
-	bne+	99f
-	tlbia
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-#endif
-	blr
-99:
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	/* Note - we had better not do anything which could generate
-	   a hash table miss while we have the hash table locked,
-	   or we'll get a deadlock.  -paulus */
-	mfmsr	r10
-	SYNC
-	rlwinm	r0,r10,0,17,15	/* clear bit 16 (MSR_EE) */
-	mtmsr	r0
-	SYNC
-#endif
-#ifdef CONFIG_SMP
-	lis	r9,hash_table_lock@h
-	ori	r9,r9,hash_table_lock@l
-	lwz	r8,PROCESSOR(r2)
-	oris	r8,r8,8
-10:	lwarx	r6,0,r9
-	cmpi	0,r6,0
-	bne-	10b
-	stwcx.	r8,0,r9
-	bne-	10b
-	eieio
-#endif
-#ifndef CONFIG_PPC64BRIDGE
-	rlwinm	r3,r3,7,1,24		/* put VSID lower limit in position */
-	oris	r3,r3,0x8000		/* set V bit */
-	rlwinm	r4,r4,7,1,24		/* put VSID upper limit in position */
-	oris	r4,r4,0x8000
-	ori	r4,r4,0x7f
-	lis	r6,Hash_size@ha
-	lwz	r6,Hash_size@l(r6)	/* size in bytes */
-	srwi	r6,r6,3			/* # PTEs */
-	mtctr	r6
-	addi	r5,r5,-8
-	li	r0,0
-1:	lwzu	r6,8(r5)		/* get next tag word */
-	cmplw	0,r6,r3
-	cmplw	1,r6,r4
-	cror	0,0,5			/* set cr0.lt if out of range */
-	blt	2f			/* branch if out of range */
-	stw	r0,0(r5)		/* invalidate entry */
-2:	bdnz	1b			/* continue with loop */
-#else /* CONFIG_PPC64BRIDGE */
-	rldic	r3,r3,12,20		/* put VSID lower limit in position */
-	ori	r3,r3,1			/* set V bit */
-	rldic	r4,r4,12,20		/* put VSID upper limit in position */
-	ori	r4,r4,0xfff		/* set V bit, API etc. */
-	lis	r6,Hash_size@ha
-	lwz	r6,Hash_size@l(r6)	/* size in bytes */
-	srwi	r6,r6,4			/* # PTEs */
-	mtctr	r6
-	addi	r5,r5,-16
-	li	r0,0
-1:	ldu	r6,16(r5)		/* get next tag word */
-	cmpld	0,r6,r3
-	cmpld	1,r6,r4
-	cror	0,0,5			/* set cr0.lt if out of range */
-	blt	2f			/* branch if out of range */
-	std	r0,0(r5)		/* invalidate entry */
-2:	bdnz	1b			/* continue with loop */
-#endif /* CONFIG_PPC64BRIDGE */
-
-	sync
-	tlbia
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-	lis	r3,hash_table_lock@ha
-	stw	r0,hash_table_lock@l(r3)
-#endif
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	mtmsr	r10
-	SYNC
-#endif
-	blr
-
-/*
- * Flush the entry for a particular page from the hash table.
- *
- * flush_hash_page(unsigned context, unsigned long va)
- */
-_GLOBAL(flush_hash_page)
-	lis	r6,Hash@ha
-	lwz	r6,Hash@l(r6)		/* hash table base */
-	cmpwi	0,r6,0			/* hash table in use? */
-	bne+	99f
-	tlbie	r4			/* in hw tlb too */
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-#endif
-	blr
-99:
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	/* Note - we had better not do anything which could generate
-	   a hash table miss while we have the hash table locked,
-	   or we'll get a deadlock.  -paulus */
-	mfmsr	r10
-	SYNC
-	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
-	mtmsr	r0
-	SYNC
-#endif
-#ifdef CONFIG_SMP
-	lis	r9,hash_table_lock@h
-	ori	r9,r9,hash_table_lock@l
-	lwz	r8,PROCESSOR(r2)
-	oris	r8,r8,9
-10:	lwarx	r7,0,r9
-	cmpi	0,r7,0
-	bne-	11f
-	stwcx.	r8,0,r9
-	beq+	12f
-11:	lwz	r7,0(r9)
-	cmpi	0,r7,0
-	beq	10b
-	b	11b
-12:	eieio
-#endif
-#ifndef CONFIG_PPC64BRIDGE
-	rlwinm	r3,r3,11,1,20		/* put context into vsid */
-	rlwimi	r3,r4,11,21,24		/* put top 4 bits of va into vsid */
-	oris	r3,r3,0x8000		/* set V (valid) bit */
-	rlwimi	r3,r4,10,26,31		/* put in API (abbrev page index) */
-	rlwinm	r7,r4,32-6,10,25	/* get page index << 6 */
-	rlwinm	r5,r3,32-1,7,25		/* vsid << 6 */
-	xor	r7,r7,r5		/* primary hash << 6 */
-	lis	r5,Hash_mask@ha
-	lwz	r5,Hash_mask@l(r5)	/* hash mask */
-	slwi	r5,r5,6			/*  << 6 */
-	and	r7,r7,r5
-	add	r6,r6,r7		/* address of primary PTEG */
-	li	r8,8
-	mtctr	r8
-	addi	r7,r6,-8
-1:	lwzu	r0,8(r7)		/* get next PTE */
-	cmpw	0,r0,r3			/* see if tag matches */
-	bdnzf	2,1b			/* while --ctr != 0 && !cr0.eq */
-	beq	3f			/* if we found it */
-	ori	r3,r3,0x40		/* set H (alt. hash) bit */
-	xor	r6,r6,r5		/* address of secondary PTEG */
-	mtctr	r8
-	addi	r7,r6,-8
-2:	lwzu	r0,8(r7)		/* get next PTE */
-	cmpw	0,r0,r3			/* see if tag matches */
-	bdnzf	2,2b			/* while --ctr != 0 && !cr0.eq */
-	bne	4f			/* if we didn't find it */
-3:	li	r0,0
-	stw	r0,0(r7)		/* invalidate entry */
-#else /* CONFIG_PPC64BRIDGE */
-	rldic	r3,r3,16,16		/* put context into vsid (<< 12) */
-	rlwimi	r3,r4,16,16,24		/* top 4 bits of va and API */
-	ori	r3,r3,1			/* set V (valid) bit */
-	rlwinm	r7,r4,32-5,9,24		/* get page index << 7 */
-	srdi	r5,r3,5			/* vsid << 7 */
-	rlwinm	r5,r5,0,1,24		/* vsid << 7 (limited to 24 bits) */
-	xor	r7,r7,r5		/* primary hash << 7 */
-	lis	r5,Hash_mask@ha
-	lwz	r5,Hash_mask@l(r5)	/* hash mask */
-	slwi	r5,r5,7			/*  << 7 */
-	and	r7,r7,r5
-	add	r6,r6,r7		/* address of primary PTEG */
-	li	r8,8
-	mtctr	r8
-	addi	r7,r6,-16
-1:	ldu	r0,16(r7)		/* get next PTE */
-	cmpd	0,r0,r3			/* see if tag matches */
-	bdnzf	2,1b			/* while --ctr != 0 && !cr0.eq */
-	beq	3f			/* if we found it */
-	ori	r3,r3,2			/* set H (alt. hash) bit */
-	xor	r6,r6,r5		/* address of secondary PTEG */
-	mtctr	r8
-	addi	r7,r6,-16
-2:	ldu	r0,16(r7)		/* get next PTE */
-	cmpd	0,r0,r3			/* see if tag matches */
-	bdnzf	2,2b			/* while --ctr != 0 && !cr0.eq */
-	bne	4f			/* if we didn't find it */
-3:	li	r0,0
-	std	r0,0(r7)		/* invalidate entry */
-#endif /* CONFIG_PPC64BRIDGE */
-4:	sync
-	tlbie	r4			/* in hw tlb too */
-	sync
-#ifdef CONFIG_SMP
-	tlbsync
-	sync
-	li	r0,0
-	stw	r0,0(r9)		/* clear hash_table_lock */
-#endif
-#if defined(CONFIG_SMP) || defined(CONFIG_PPC64BRIDGE)
-	mtmsr	r10
-	SYNC
-#endif
-	blr
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.4.5/linux/arch/ppc/kernel/head.S	Thu May 24 15:03:05 2001
+++ linux/arch/ppc/kernel/head.S	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.head.S 1.21 05/23/01 00:38:42 cort
+ * BK Id: SCCS/s.head.S 1.23 06/28/01 15:50:16 paulus
  */
 /*
  *  PowerPC version 
@@ -25,11 +25,12 @@
  *	
  */
 
+#include <linux/config.h>
 #include "ppc_asm.h"
 #include <asm/processor.h>
 #include <asm/page.h>
-#include <linux/config.h>
 #include <asm/mmu.h>
+#include <asm/pgtable.h>
 
 #ifdef CONFIG_APUS
 #include <asm/amigappc.h>
@@ -177,7 +178,7 @@
 	mtspr	SDR1,r4
 	slbia
 	lis	r5,0x2000		/* set pseudo-segment reg 12 */
-	ori	r5,r5,12
+	ori	r5,r5,0x0ccc
 	mtsr	12,r5
 #endif /* CONFIG_POWER4 */
 
@@ -312,9 +313,8 @@
 	mfspr	r20,DSISR
 	andis.	r0,r20,0xa470		/* weird error? */
 	bne	1f			/* if not, try to put a PTE */
-	mfspr	r3,DAR			/* into the hash table */
-	rlwinm	r4,r23,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	rlwimi	r4,r20,32-23,29,29	/* DSISR_STORE -> _PAGE_RW */
+	mfspr	r4,DAR			/* into the hash table */
+	rlwinm	r3,r20,32-15,21,21	/* DSISR_STORE -> _PAGE_RW */
 	bl	hash_page
 1:	stw	r20,_DSISR(r21)
 	mr	r5,r20
@@ -354,9 +354,8 @@
 #endif /* CONFIG_PPC64BRIDGE */
 	andis.	r0,r23,0x4000		/* no pte found? */
 	beq	1f			/* if so, try to put a PTE */
-	mr	r3,r22			/* into the hash table */
-	rlwinm	r4,r23,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	mr	r20,r23			/* SRR1 has reason bits */
+	li	r3,0			/* into the hash table */
+	mr	r4,r22			/* SRR0 is fault address */
 	bl	hash_page
 1:	addi	r3,r1,STACK_FRAME_OVERHEAD
 	mr	r4,r22
@@ -505,10 +504,13 @@
 	lis	r1,KERNELBASE@h		/* check if kernel address */
 	cmplw	0,r3,r1
 	mfspr	r2,SPRG3
+	li	r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
 	lwz	r2,PGDIR(r2)
 	blt+	112f
 	lis	r2,swapper_pg_dir@ha	/* if kernel address, use */
 	addi	r2,r2,swapper_pg_dir@l	/* kernel page table */
+	mfspr	r1,SRR1			/* and MSR_PR bit from SRR1 */
+	rlwinm	r1,r1,32-12,29,29	/* shift MSR_PR to _PAGE_USER posn */
 112:	tophys(r2,r2)
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -516,21 +518,23 @@
 	beq-	InstructionAddressInvalid	/* return if no mapping */
 	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r1,0(r2)		/* get linux-style pte */
-	/* setup access flags in r3 */
-	mfmsr	r3
-	rlwinm	r3,r3,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	ori	r3,r3,1			/* set _PAGE_PRESENT bit in access */
-	andc.	r3,r3,r1		/* check access & ~permission */
+	lwz	r3,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r3		/* check access & ~permission */
 	bne-	InstructionAddressInvalid /* return if access not permitted */
-	ori	r1,r1,0x100		/* set _PAGE_ACCESSED in pte */
-	stw	r1,0(r2)		/* update PTE (accessed bit) */
+	ori	r3,r3,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
+	/*
+	 * NOTE! We are assuming this is not an SMP system, otherwise
+	 * we would need to update the pte atomically with lwarx/stwcx.
+	 */
+	stw	r3,0(r2)		/* update PTE (accessed bit) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	/* this computation could be done better -- Cort */
-	rlwinm	r3,r1,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r1,r1,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r3,r3,0xe04		/* clear out reserved bits */
-	andc	r1,r1,r3		/* PP=2 or 0, when _PAGE_HWWRITE */
+	rlwinm	r1,r3,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r2,r3,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	and	r1,r1,r2		/* writable if _RW and _DIRTY */
+	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
+	ori	r1,r1,0xe14		/* clear out reserved bits and M */
+	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
 	mtspr	RPA,r1
 	mfspr	r3,IMISS
 	tlbli	r3
@@ -555,7 +559,6 @@
 	mfmsr	r0		/* Restore "normal" registers */
 	xoris	r0,r0,MSR_TGPR>>16
 	mtcrf	0x80,r3		/* Restore CR0 */
-	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	InstructionAccess
 
@@ -576,10 +579,13 @@
 	lis	r1,KERNELBASE@h		/* check if kernel address */
 	cmplw	0,r3,r1
 	mfspr	r2,SPRG3
+	li	r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */
 	lwz	r2,PGDIR(r2)
 	blt+	112f
 	lis	r2,swapper_pg_dir@ha	/* if kernel address, use */
 	addi	r2,r2,swapper_pg_dir@l	/* kernel page table */
+	mfspr	r1,SRR1			/* and MSR_PR bit from SRR1 */
+	rlwinm	r1,r1,32-12,29,29	/* shift MSR_PR to _PAGE_USER posn */
 112:	tophys(r2,r2)
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -587,22 +593,23 @@
 	beq-	DataAddressInvalid	/* return if no mapping */
 	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r1,0(r2)		/* get linux-style pte */
-	/* setup access flags in r3 */
-	mfmsr	r3
-	rlwinm	r3,r3,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	ori	r3,r3,1			/* set _PAGE_PRESENT bit in access */
-	/* save r2 and use it as scratch for the andc. */	
-	andc.	r3,r3,r1		/* check access & ~permission */
+	lwz	r3,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r3		/* check access & ~permission */
 	bne-	DataAddressInvalid	/* return if access not permitted */
-	ori	r1,r1,0x100		/* set _PAGE_ACCESSED in pte */
-	stw	r1,0(r2)		/* update PTE (accessed bit) */
+	ori	r3,r3,_PAGE_ACCESSED	/* set _PAGE_ACCESSED in pte */
+	/*
+	 * NOTE! We are assuming this is not an SMP system, otherwise
+	 * we would need to update the pte atomically with lwarx/stwcx.
+	 */
+	stw	r3,0(r2)		/* update PTE (accessed bit) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	/* this computation could be done better -- Cort */
-	rlwinm	r3,r1,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r1,r1,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r3,r3,0xe04		/* clear out reserved bits */
-	andc	r1,r1,r3		/* PP=2 or 0, when _PAGE_HWWRITE */
+	rlwinm	r1,r3,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r2,r3,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	and	r1,r1,r2		/* writable if _RW and _DIRTY */
+	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r3,r3,32-1,31,31	/* _PAGE_USER -> PP lsb */
+	ori	r1,r1,0xe14		/* clear out reserved bits and M */
+	andc	r1,r3,r1		/* PP = user? (rw&dirty? 2: 3): 0 */
 	mtspr	RPA,r1
 	mfspr	r3,DMISS
 	tlbld	r3
@@ -625,7 +632,6 @@
 	mfmsr	r0		/* Restore "normal" registers */
 	xoris	r0,r0,MSR_TGPR>>16
 	mtcrf	0x80,r3		/* Restore CR0 */
-	SYNC			/* Some chip revs have problems here... */
 	mtmsr	r0
 	b	DataAccess
 	
@@ -646,10 +652,13 @@
 	lis	r1,KERNELBASE@h		/* check if kernel address */
 	cmplw	0,r3,r1
 	mfspr	r2,SPRG3
+	li	r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */
 	lwz	r2,PGDIR(r2)
 	blt+	112f
 	lis	r2,swapper_pg_dir@ha	/* if kernel address, use */
 	addi	r2,r2,swapper_pg_dir@l	/* kernel page table */
+	mfspr	r1,SRR1			/* and MSR_PR bit from SRR1 */
+	rlwinm	r1,r1,32-12,29,29	/* shift MSR_PR to _PAGE_USER posn */
 112:	tophys(r2,r2)
 	rlwimi	r2,r3,12,20,29		/* insert top 10 bits of address */
 	lwz	r2,0(r2)		/* get pmd entry */
@@ -657,22 +666,19 @@
 	beq-	DataAddressInvalid	/* return if no mapping */
 	tophys(r2,r2)
 	rlwimi	r2,r3,22,20,29		/* insert next 10 bits of address */
-	lwz	r1,0(r2)		/* get linux-style pte */
-	/* setup access flags in r3 */
-	mfmsr	r3
-	rlwinm	r3,r3,32-13,30,30	/* MSR_PR -> _PAGE_USER */
-	ori	r3,r3,0x5		/* _PAGE_PRESENT|_PAGE_RW */
-	/* save r2 and use it as scratch for the andc. */	
-	andc.	r3,r3,r1		/* check access & ~permission */
+	lwz	r3,0(r2)		/* get linux-style pte */
+	andc.	r1,r1,r3		/* check access & ~permission */
 	bne-	DataAddressInvalid	/* return if access not permitted */
-	ori	r1,r1,0x384		/* set _PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_RW|_PAGE_HWWRITE in pte */
-	stw	r1,0(r2)		/* update PTE (accessed bit) */
+	ori	r3,r3,_PAGE_ACCESSED|_PAGE_DIRTY
+	/*
+	 * NOTE! We are assuming this is not an SMP system, otherwise
+	 * we would need to update the pte atomically with lwarx/stwcx.
+	 */
+	stw	r3,0(r2)		/* update PTE (accessed/dirty bits) */
 	/* Convert linux-style PTE to low word of PPC-style PTE */
-	/* this computation could be done better -- Cort */
-	rlwinm	r3,r1,32-9,31,31	/* _PAGE_HWWRITE -> PP lsb */
-	rlwimi	r1,r1,32-1,31,31	/* _PAGE_USER -> PP (both bits now) */
-	ori	r3,r3,0xe04		/* clear out reserved bits */
-	andc	r1,r1,r3		/* PP=2 or 0, when _PAGE_HWWRITE */
+	rlwimi	r3,r3,32-1,30,30	/* _PAGE_USER -> PP msb */
+	li	r1,0xe15		/* clear out reserved bits and M */
+	andc	r1,r3,r1		/* PP = user? 2: 0 */
 	mtspr	RPA,r1
 	mfspr	r3,DMISS
 	tlbld	r3
@@ -901,7 +907,6 @@
  */
 	mfmsr	r5
 	oris	r5,r5,MSR_VEC@h
-	SYNC
 	mtmsr	r5			/* enable use of AltiVec now */
 	isync
 /*
@@ -1028,6 +1033,7 @@
 	ori	r5,r5,MSR_FP
 	SYNC
 	mtmsr	r5			/* enable use of fpu now */
+	SYNC
 	isync
 	cmpi	0,r3,0
 	beqlr-				/* if no previous owner, done */
@@ -1384,7 +1390,7 @@
 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
 	li	r4,0
 3:	mtsrin	r3,r4
-	addi	r3,r3,1		/* increment VSID */
+	addi	r3,r3,0x111	/* increment VSID */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
 #ifndef CONFIG_POWER4
@@ -1490,7 +1496,8 @@
  * Set up the segment registers for a new context.
  */
 _GLOBAL(set_context)
-	rlwinm	r3,r3,4,8,27	/* VSID = context << 4 */
+	mulli	r3,r3,897	/* multiply context by skew factor */
+	rlwinm	r3,r3,4,8,27	/* VSID = (context & 0xfffff) << 4 */
 	addis	r3,r3,0x6000	/* Set Ks, Ku bits */
 	li	r0,12		/* TASK_SIZE / SEGMENT_SIZE */
 	mtctr	r0
@@ -1500,7 +1507,8 @@
 	slbie	r4
 #endif /* CONFIG_PPC64BRIDGE */
 	mtsrin	r3,r4
-	addi	r3,r3,1		/* next VSID */
+	addi	r3,r3,0x111	/* next VSID */
+	rlwinm	r3,r3,0,8,3	/* clear out any overflow from VSID field */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
 	SYNC
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/head_8xx.S linux/arch/ppc/kernel/head_8xx.S
--- v2.4.5/linux/arch/ppc/kernel/head_8xx.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/head_8xx.S	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.head_8xx.S 1.11 05/21/01 11:50:00 paulus
+ * BK Id: SCCS/s.head_8xx.S 1.14 06/28/01 15:50:16 paulus
  */
 /*
  *  arch/ppc/kernel/except_8xx.S
@@ -500,6 +500,11 @@
 #endif
 	mtspr	MD_TWC, r21
 
+	/* Set PP0 to PP1 (== _PAGE_USER) & ~_PAGE_RW */
+	rlwimi	r20, r20, 32-1, 21, 21
+	rlwinm	r21, r20, 4, 21, 21
+	andc	r20, r20, r21
+
 	/* Set four subpage valid bits (24, 25, 26, and 27).
 	 * Clear bit 28 (which should be in the PTE, but we do this anyway).
 	 */
@@ -602,7 +607,7 @@
 
 	/* Update 'changed', among others.
 	*/
-	ori	r20, r20, _PAGE_DIRTY|_PAGE_HWWRITE|_PAGE_ACCESSED
+	ori	r20, r20, _PAGE_DIRTY|_PAGE_ACCESSED
 	mfspr	r21, MD_TWC		/* Get pte address again */
 	stw	r20, 0(r21)		/* and update pte in table */
 
@@ -939,6 +944,12 @@
  * ASID compare register with the new "context".
  */
 _GLOBAL(set_context)
+	/* fetch the pgd from the context_mm array */
+	lis	r5, context_mm@ha
+	slwi	r6, r3, 2
+	add	r5, r5, r6
+	lwz	r5, context_mm@l(r5)	/* get the mm */
+	lwz	r4, MM_PGD(r5)		/* get the pgd from the mm */
 #ifdef CONFIG_8xx_CPU6
 	lis	r6, cpu6_errata_word@h
 	ori	r6, r6, cpu6_errata_word@l
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.4.5/linux/arch/ppc/kernel/irq.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/irq.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.irq.c 1.23 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.irq.c 1.28 06/28/01 16:15:56 paulus
  */
 /*
  *  arch/ppc/kernel/irq.c
@@ -531,26 +531,25 @@
 {
 	int cpu = smp_processor_id();
 	int irq;
-        hardirq_enter( cpu );
+        hardirq_enter(cpu);
 
 	/* every arch is required to have a get_irq -- Cort */
-	irq = ppc_md.get_irq( regs );
+	irq = ppc_md.get_irq(regs);
 
-	if ( irq < 0 )
-	{
+	if (irq >= 0) {
+		ppc_irq_dispatch_handler( regs, irq );
+	} else if (irq != -2) {
 		/* -2 means ignore, already handled */
-		if (irq != -2)
-		{
+		if (ppc_spurious_interrupts < 10)
 			printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
 			       irq, regs->nip);
-			/* That's not SMP safe ... but who cares ? */
-			ppc_spurious_interrupts++;
-		}
-		goto out;
+		/* That's not SMP safe ... but who cares ? */
+		ppc_spurious_interrupts++;
 	}
-	ppc_irq_dispatch_handler( regs, irq );
-out:	
         hardirq_exit( cpu );
+
+	if (softirq_pending(cpu))
+		do_softirq();
 	return 1; /* lets ret_from_int know we can do checks */
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- v2.4.5/linux/arch/ppc/kernel/m8xx_setup.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.m8xx_setup.c 1.17 05/18/01 07:54:04 patch
+ * BK Id: SCCS/s.m8xx_setup.c 1.20 06/27/01 14:49:58 trini
  */
 /*
  *  linux/arch/ppc/kernel/setup.c
@@ -124,12 +124,6 @@
 extern unsigned long find_available_memory(void);
 extern void m8xx_cpm_reset(uint);
 
-static void ide_interrupt_handler(void* dev_id);
-
-void __init adbdev_init(void)
-{
-}
-
 void __init
 m8xx_setup_arch(void)
 {
@@ -359,6 +353,12 @@
 /*
  * IDE stuff.
  */
+#ifdef CONFIG_BLK_DEV_MPC8xx_IDE
+void ide_interrupt_handler (void *dev)
+{
+}
+#endif
+
 void
 m8xx_ide_insw(ide_ioreg_t port, void *buf, int ns)
 {
@@ -512,12 +512,7 @@
 
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 }
-#endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
-
-
-/* -------------------------------------------------------------------- */
 
-#if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE)
 #ifdef CONFIG_BLK_DEV_MPC8xx_IDE
 
 /* PCMCIA Timing */
@@ -577,13 +572,9 @@
 	if ((reg = pcmp->pcmc_por7 & mask) != 0)
 		pcmp->pcmc_por7 = reg | timing;
 }
-
-void ide_interrupt_handler (void *dev)
-{
-}
-
 #endif	/* CONFIG_BLK_DEV_MPC8xx_IDE */
 #endif	/* CONFIG_BLK_DEV_IDE || CONFIG_BLK_DEV_IDE_MODULE */
+
 /* -------------------------------------------------------------------- */
 
 /*
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.4.5/linux/arch/ppc/kernel/misc.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/misc.S	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.misc.S 1.16 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.misc.S 1.19 06/15/01 13:56:56 paulus
  */
 /*
  * This file contains miscellaneous low-level functions.
@@ -263,10 +263,13 @@
  * This is a no-op on the 601.
  */
 _GLOBAL(flush_instruction_cache)
-#ifdef CONFIG_8xx
+#if defined(CONFIG_8xx)
 	isync
 	lis	r5, IDC_INVALL@h
 	mtspr	IC_CST, r5
+#elif defined(CONFIG_4xx)
+	lis	r3, KERNELBASE@h
+	iccci	0,r3
 #else
 	mfspr	r3,PVR
 	rlwinm	r3,r3,16,16,31
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
--- v2.4.5/linux/arch/ppc/kernel/mk_defs.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/mk_defs.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.mk_defs.c 1.5 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.mk_defs.c 1.8 06/28/01 15:50:16 paulus
  */
 /*
  * This program is used to generate definitions needed by
@@ -117,5 +117,6 @@
 	DEFINE(RESULT, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, result));
 	DEFINE(TRAP, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, trap));
 	DEFINE(CLONE_VM, CLONE_VM);
+	DEFINE(MM_PGD, offsetof(struct mm_struct, pgd));
 	return 0;
 }
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.4.5/linux/arch/ppc/kernel/pci.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/pci.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pci.c 1.21 05/21/01 01:31:30 cort
+ * BK Id: SCCS/s.pci.c 1.26 06/28/01 08:02:41 trini
  */
 /*
  * Common pmac/prep/chrp pci routines. -- Cort
@@ -40,11 +40,10 @@
 unsigned long isa_mem_base    = 0;
 unsigned long pci_dram_offset = 0;
 
-static u8* pci_to_OF_bus_map;
-
 static void pcibios_fixup_resources(struct pci_dev* dev);
 #ifdef CONFIG_ALL_PPC
 static void pcibios_fixup_cardbus(struct pci_dev* dev);
+static u8* pci_to_OF_bus_map;
 #endif
 
 /* By default, we don't re-assign bus numbers. We do this only on
@@ -73,8 +72,13 @@
 	u32 new, check;
 	int reg;
 	struct pci_controller* hose = dev->sysdata;
+	unsigned long io_offset;
 	
 	new = res->start;
+	if (hose && res->flags & IORESOURCE_IO) {
+		io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+		new -= io_offset;
+	}
 	if (hose && res->flags & IORESOURCE_MEM)
 		new -= hose->pci_mem_offset;
 	new |= (res->flags & PCI_REGION_FLAG_MASK);
@@ -98,40 +102,43 @@
 }
 
 static void
-pcibios_fixup_resources(struct pci_dev* dev)
+pcibios_fixup_resources(struct pci_dev *dev)
 {
-	struct pci_controller* hose =
-		(struct pci_controller *)dev->sysdata;
+	struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
 	int i;
+	unsigned long offset;
+
 	if (!hose) {
-		printk("No hose for PCI dev %x.%x !\n", dev->bus->number, dev->devfn >> 3);
+		printk(KERN_ERR "No hose for PCI dev %s!\n", dev->slot_name);
 		return;
 	}
 	for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
 		struct resource *res = dev->resource + i;
-		if (!res->start)
+		if (!res->start || !res->flags)
 			continue;
-		if ((res->flags & IORESOURCE_MEM) && hose->pci_mem_offset) {
-			res->start += hose->pci_mem_offset;
-			res->end += hose->pci_mem_offset;
+		if (res->end == 0xffffffff) {
+			DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+			    dev->slot_name, i, res->start, res->end);
+			res->end -= res->start;
+			res->start = 0;
+			continue;
+		}
+		offset = 0;
+		if (res->flags & IORESOURCE_MEM) {
+			offset = hose->pci_mem_offset;
+		} else if (res->flags & IORESOURCE_IO) {
+			offset = (unsigned long) hose->io_base_virt
+				- isa_io_base;
+		}
+		if (offset != 0) {
+			res->start += offset;
+			res->end += offset;
 #ifdef DEBUG
-			printk("Fixup mem res, dev: %x.%x, res_start: %lx->%lx\n",
-			       dev->bus->number, dev->devfn>>3, res->start-hose->pci_mem_offset,
-			       res->start);
+			printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+			       i, res->flags, dev->slot_name,
+			       res->start - offset, res->start);
 #endif
 		}
-
-		if ((res->flags & IORESOURCE_IO)
-		    && (unsigned long) hose->io_base_virt != isa_io_base) {
-			unsigned long offs;
-
-			offs = (unsigned long)hose->io_base_virt - isa_io_base;
-			res->start += offs;
-			res->end += offs;
-			printk("Fixup IO res, dev: %x.%x, res_start: %lx->%lx\n",
-			       dev->bus->number, dev->devfn>>3,
-			       res->start - offs, res->start);
-		}
 	}
 }
 
@@ -228,22 +235,27 @@
 {
 	struct list_head *ln;
 	struct pci_bus *bus;
-	struct pci_dev *dev;
-	int idx;
-	struct resource *r, *pr;
+	int i;
+	struct resource *res, *pr;
 
 	/* Depth-First Search on bus tree */
-	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+	for (ln = bus_list->next; ln != bus_list; ln=ln->next) {
 		bus = pci_bus_b(ln);
-		if ((dev = bus->self)) {
-			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
-				r = &dev->resource[idx];
-				if (!r->start)
-					continue;
-				pr = pci_find_parent_resource(dev, r);
-				if (!pr || request_resource(pr, r) < 0)
-					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
-			}
+		for (i = 0; i < 4; ++i) {
+			if ((res = bus->resource[i]) == NULL || !res->flags)
+				continue;
+			if (bus->parent == NULL)
+				pr = (res->flags & IORESOURCE_IO)?
+					&ioport_resource: &iomem_resource;
+			else
+				pr = pci_find_parent_resource(bus->self, res);
+
+			if (pr && request_resource(pr, res) == 0)
+				continue;
+			printk(KERN_ERR "PCI: Cannot allocate resource region "
+			       "%d of PCI bridge %d\n", i, bus->number);
+			DBG("PCI: resource is %lx..%lx (%lx), parent %p\n",
+			    res->start, res->end, res->flags, pr);
 		}
 		pcibios_allocate_bus_resources(&bus->children);
 	}
@@ -253,13 +265,15 @@
 {
 	struct resource *pr, *r = &dev->resource[idx];
 
-	DBG("PCI:%x:%x:%x: Resource %08lx-%08lx (f=%lx)\n",
-	    dev->bus->number, dev->devfn >> 3, dev->devfn & 7,
-	    r->start, r->end, r->flags);
+	DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",
+	    dev->slot_name, idx, r->start, r->end, r->flags);
 	pr = pci_find_parent_resource(dev, r);
 	if (!pr || request_resource(pr, r) < 0) {
 		printk(KERN_ERR "PCI: Cannot allocate resource region %d"
 		       " of device %s\n", idx, dev->slot_name);
+		if (pr)
+			DBG("PCI:  parent is %p: %08lx-%08lx (f=%lx)\n",
+			    pr, pr->start, pr->end, pr->flags);
 		/* We'll assign a new address later */
 		r->end -= r->start;
 		r->start = 0;
@@ -276,20 +290,12 @@
 
 	pci_for_each_dev(dev) {
 		pci_read_config_word(dev, PCI_COMMAND, &command);
-		for(idx = 0; idx < 6; idx++) {
+		for (idx = 0; idx < 6; idx++) {
 			r = &dev->resource[idx];
 			if (r->parent)		/* Already allocated */
 				continue;
 			if (!r->start)		/* Not assigned at all */
 				continue;
-			if (r->end == 0xffffffff) {
-				/* LongTrail OF quirk: unassigned */
-				DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end);
-				r->end -= r->start;
-				r->start = 0;
-				continue;
-			}
-
 			if (r->flags & IORESOURCE_IO)
 				disabled = !(command & PCI_COMMAND_IO);
 			else
@@ -306,7 +312,8 @@
 			DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
 			r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
 			pci_read_config_dword(dev, dev->rom_base_reg, &reg);
-			pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+			pci_write_config_dword(dev, dev->rom_base_reg,
+					       reg & ~PCI_ROM_ADDRESS_ENABLE);
 		}
 	}
 }
@@ -325,21 +332,14 @@
 		if (!class || class == PCI_CLASS_BRIDGE_HOST)
 			continue;
 
-		for(idx=0; idx<6; idx++) {
+		for (idx = 0; idx < 6; idx++) {
 			r = &dev->resource[idx];
-#if 0	/* we don't need this PC-ism */
-			/*
-			 *  Don't touch IDE controllers and I/O ports of video cards!
-			 */
-			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
-			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
-				continue;
-#endif
 
 			/*
-			 *  We shall assign a new address to this resource, either because
-			 *  the BIOS (sic) forgot to do so or because we have decided the old
-			 *  address was unusable for some reason.
+			 * We shall assign a new address to this resource,
+			 * either because the BIOS (sic) forgot to do so
+			 * or because we have decided the old address was
+			 * unusable for some reason.
 			 */
 			if (!r->start && r->end &&
 			    (!ppc_md.pcibios_enable_device_hook ||
@@ -347,13 +347,13 @@
 				pci_assign_resource(dev, idx);
 		}
 
-		if (0) { /* don't assign ROMs */
-			r = &dev->resource[PCI_ROM_RESOURCE];
-			r->end -= r->start;
-			r->start = 0;
-			if (r->end)
-				pci_assign_resource(dev, PCI_ROM_RESOURCE);
-		}
+#if 0 /* don't assign ROMs */
+		r = &dev->resource[PCI_ROM_RESOURCE];
+		r->end -= r->start;
+		r->start = 0;
+		if (r->end)
+			pci_assign_resource(dev, PCI_ROM_RESOURCE);
+#endif
 	}
 }
 
@@ -496,10 +496,15 @@
 			&& ((reg[0] >> 16) & 0xff) == bus)
 			return node;
 
-		/* For PCI<->PCI bridges or CardBus bridges, we go down */
+		/* For PCI<->PCI bridges or CardBus bridges, we go down
+		 * Note: some OFs create a parent node "multifunc-device" as
+		 * a fake root for all functions of a multi-function device,
+		 * we go down them as well.
+		 */
 		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))
+		if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+			(*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
+			strcmp(node->name, "multifunc-device"))
 			continue;
 		sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn);
 		if (sub_node)
@@ -682,9 +687,9 @@
 {
 	struct pci_controller *hose;
 	struct pci_bus *bus;
-	int next_busno, i;
+	int next_busno;
 
-	printk("PCI: Probing PCI hardware\n");
+	printk(KERN_INFO "PCI: Probing PCI hardware\n");
 
 	/* Scan all of the recorded PCI controllers.  */
 	for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
@@ -692,18 +697,6 @@
 			hose->first_busno = next_busno;
 		hose->last_busno = 0xff;
 		bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
-		if (hose->io_resource.flags) {
-			unsigned long offs;
-
-			offs = (unsigned long)hose->io_base_virt - isa_io_base;
-			hose->io_resource.start += offs;
-			hose->io_resource.end += offs;
-			bus->resource[0] = &hose->io_resource;
-		}
-		for (i = 0; i < 3; ++i)
-			if (hose->mem_resources[i].flags)
-				bus->resource[i+1] = &hose->mem_resources[i];
-		hose->bus = bus;
 		hose->last_busno = bus->subordinate;
 		if (pci_assign_all_busses || next_busno <= hose->last_busno)
 			next_busno = hose->last_busno+1;
@@ -716,7 +709,7 @@
 	 */
 	if (pci_assign_all_busses && have_of)
 		pcibios_make_OF_bus_map();
-		
+
 	/* Call machine dependant fixup */
 	if (ppc_md.pcibios_fixup)
 		ppc_md.pcibios_fixup();
@@ -727,27 +720,7 @@
 	pcibios_allocate_resources(1);
 	pcibios_assign_resources();
 
-#ifdef CONFIG_BLK_DEV_IDE
-	/* 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
-	 */
-	if (_machine == _MACH_Pmac) {
-		struct pci_dev *dev;
-		pci_for_each_dev(dev)
-		{
-			if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
-				pci_enable_device(dev);
-		}
-	}
-#endif /* CONFIG_BLK_DEV_IDE */
-
+	/* Call machine dependent post-init code */
 	if (ppc_md.pcibios_after_init)
 		ppc_md.pcibios_after_init();
 }
@@ -775,21 +748,62 @@
 
 void __init pcibios_fixup_bus(struct pci_bus *bus)
 {
-	struct pci_controller *hose;
+	struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+	unsigned long io_offset;
+	struct resource *res;
+	int i;
+
+	io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+	if (bus->parent == NULL) {
+		/* This is a host bridge - fill in its resources */
+		hose->bus = bus;
 
-	pci_read_bridge_bases(bus);
+		bus->resource[0] = res = &hose->io_resource;
+		if (!res->flags) {
+			if (io_offset)
+				printk(KERN_ERR "I/O resource not set for host"
+				       " bridge %d\n", hose->index);
+			res->start = 0;
+			res->end = IO_SPACE_LIMIT;
+			res->flags = IORESOURCE_IO;
+		}
+		res->start += io_offset;
+		res->end += io_offset;
 
-	hose = pci_bus_to_hose(bus->number);
+		for (i = 0; i < 3; ++i) {
+			res = &hose->mem_resources[i];
+			if (!res->flags) {
+				if (i > 0)
+					continue;
+				printk(KERN_ERR "Memory resource not set for "
+				       "host bridge %d\n", hose->index);
+				res->start = hose->pci_mem_offset;
+				res->end = ~0U;
+				res->flags = IORESOURCE_MEM;
+			}
+			bus->resource[i+1] = res;
+		}
+	} else {
+		/* This is a subordinate bridge */
+		pci_read_bridge_bases(bus);
 
-	/* Apply pci_mem_offset to bridge mem resource */
-	if (hose->first_busno != bus->number)
-		if (bus->resource[1]->start && (bus->resource[1]->end != -1))
-		{
-			bus->resource[1]->start += hose->pci_mem_offset;
-			bus->resource[1]->end += hose->pci_mem_offset;
+		for (i = 0; i < 4; ++i) {
+			if ((res = bus->resource[i]) == NULL)
+				continue;
+			if (!res->flags)
+				continue;
+			if (io_offset && (res->flags & IORESOURCE_IO)) {
+				res->start += io_offset;
+				res->end += io_offset;
+			} else if (hose->pci_mem_offset
+				   && (res->flags & IORESOURCE_MEM)) {
+				res->start += hose->pci_mem_offset;
+				res->end += hose->pci_mem_offset;
+			}
 		}
+	}
 
-	if ( ppc_md.pcibios_fixup_bus )
+	if (ppc_md.pcibios_fixup_bus)
 		ppc_md.pcibios_fixup_bus(bus);
 }
 
@@ -881,26 +895,17 @@
 	return hose->pci_mem_offset;
 }
 
-#ifdef CONFIG_POWER4
-extern unsigned long pci_address_offset(int, unsigned int);
-#endif /* CONFIG_POWER4 */
-
 unsigned long
 pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
 {
 	/* Hack alert again ! See comments in chrp_pci.c
 	 */
-#ifdef CONFIG_POWER4
-	unsigned long offset = pci_address_offset(pdev->bus->number, res->flags);
-	return res->start - offset;
-#else /* CONFIG_POWER4 */
 	struct pci_controller* hose =
 		(struct pci_controller *)pdev->sysdata;
 	if (hose && res->flags & IORESOURCE_MEM)
 		return res->start - hose->pci_mem_offset;
 	/* We may want to do something with IOs here... */
 	return res->start;
-#endif	
 }
 
 /*
@@ -1072,27 +1077,19 @@
 unsigned long
 pci_phys_to_bus(unsigned long pa, int busnr)
 {
-#ifdef CONFIG_POWER4
-	return pa - pci_address_offset(busnr, IORESOURCE_MEM);
-#else /* CONFIG_POWER4 */
 	struct pci_controller* hose = pci_bus_to_hose(busnr);
 	if (!hose)
 		return pa;
 	return pa - hose->pci_mem_offset;
-#endif
 }
 
 unsigned long
 pci_bus_to_phys(unsigned int ba, int busnr)
 {
-#ifdef CONFIG_POWER4
-	return ba + pci_address_offset(dev->bus->number, IORESOURCE_MEM);
-#else /* CONFIG_POWER4 */
 	struct pci_controller* hose = pci_bus_to_hose(busnr);
 	if (!hose)
 		return ba;
 	return ba + hose->pci_mem_offset;
-#endif
 }
 
 /* Provide information on locations of various I/O regions in physical
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/pmac_pci.c linux/arch/ppc/kernel/pmac_pci.c
--- v2.4.5/linux/arch/ppc/kernel/pmac_pci.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/pmac_pci.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.pmac_pci.c 1.14 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.pmac_pci.c 1.18 07/01/01 12:23:31 trini
  */
 /*
  * Support for PCI bridges found on Power Macintoshes.
@@ -42,8 +42,6 @@
 /*
  * Magic constants for enabling cache coherency in the bandit/PSX bridge.
  */
-#define APPLE_VENDID	0x106b
-#define BANDIT_DEVID	1
 #define BANDIT_DEVID_2	8
 #define BANDIT_REVID	3
 
@@ -97,12 +95,17 @@
 }
 
 /*
- * Apple MacRISC (UniNorth, Bandit) PCI controllers.
+ * 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.
@@ -124,10 +127,6 @@
 {
 	unsigned int caddr;
 	
-#ifdef DEBUG
-//	printk("macrisc_config_access(hose: 0x%08lx, bus: 0x%x, devfb: 0x%x, offset: 0x%x)\n",
-//		hose, bus, dev_fn, offset);
-#endif
 	if (bus == hose->first_busno) {
 		if (dev_fn < (11 << 3))
 			return 0;
@@ -189,55 +188,50 @@
 	macrisc_write_config_dword
 };
 
-
 /*
- * Apple "Chaos" PCI controller.
- * 
- * This controller is present on some first generation "PowerSurge"
- * machines (8500, 8600, ...). It's a very weird beast and will die
- * in flames if we try to probe the config space.
- * The long-term solution is to provide a config space "emulation"
- * based on what we find in OF device tree
+ * Verifiy that a specific (bus, dev_fn) exists on chaos
  */
- 
-static int chaos_config_read_byte(struct pci_dev *dev, int offset, u8 *val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_read_word(struct pci_dev *dev, int offset, u16 *val)
+static int __pmac
+chaos_validate_dev(struct pci_dev *dev, int offset)
 {
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_read_dword(struct pci_dev *dev, int offset, u32 *val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_write_byte(struct pci_dev *dev, int offset, u8 val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int chaos_config_write_word(struct pci_dev *dev, int offset, u16 val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
+	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;
 }
 
-static int chaos_config_write_dword(struct pci_dev *dev, int offset, u32 val)
-{
-	return PCIBIOS_DEVICE_NOT_FOUND;
-}
+#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_config_read_byte,
-	chaos_config_read_word,
-	chaos_config_read_dword,
-	chaos_config_write_byte,
-	chaos_config_write_word,
-	chaos_config_write_dword
+	chaos_read_config_byte,
+	chaos_read_config_word,
+	chaos_read_config_dword,
+	chaos_write_config_byte,
+	chaos_write_config_word,
+	chaos_write_config_dword
 };
 
 
@@ -245,7 +239,8 @@
  * 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)
+static void __init
+init_bandit(struct pci_controller *bp)
 {
 	unsigned int vendev, magic;
 	int rev;
@@ -254,7 +249,8 @@
 	out_le32(bp->cfg_addr, (1UL << BANDIT_DEVNUM) + PCI_VENDOR_ID);
 	udelay(2);
 	vendev = in_le32((volatile unsigned int *)bp->cfg_data);
-	if (vendev == (BANDIT_DEVID << 16) + APPLE_VENDID) {
+	if (vendev == (PCI_VENDOR_ID_APPLE_BANDIT << 16) + 
+			PCI_VENDOR_ID_APPLE) {
 		/* read the revision id */
 		out_le32(bp->cfg_addr,
 			 (1UL << BANDIT_DEVNUM) + PCI_REVISION_ID);
@@ -264,7 +260,7 @@
 			printk(KERN_WARNING
 			       "Unknown revision %d for bandit at %08lx\n",
 			       rev, bp->io_base_phys);
-	} else if (vendev != (BANDIT_DEVID_2 << 16) + APPLE_VENDID) {
+	} else if (vendev != (BANDIT_DEVID_2 << 16) + PCI_VENDOR_ID_APPLE) {
 		printk(KERN_WARNING "bandit isn't? (%x)\n", vendev);
 		return;
 	}
@@ -426,7 +422,8 @@
  * "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)
+static void __init
+add_bridges(struct device_node *dev)
 {
 	int len;
 	struct pci_controller *hose;
@@ -490,17 +487,11 @@
 	}
 }
 
-static void
+static void __init
 pcibios_fixup_OF_interrupts(void)
 {	
 	struct pci_dev* dev;
 	
-	/*
-	 * FIXME: This is broken: We should not assign IRQ's to IRQless
-	 *	  devices (look at PCI_INTERRUPT_PIN) and we also should
-	 *	  honor the existence of multi-function devices where
-	 *	  different functions have different interrupt pins. [mj]
-	 */
 	pci_for_each_dev(dev)
 	{
 		/*
@@ -533,7 +524,7 @@
 	pcibios_fixup_OF_interrupts();
 }
 
-int
+int __pmac
 pmac_pci_enable_device_hook(struct pci_dev *dev, int initial)
 {
 	struct device_node* node;
@@ -563,10 +554,29 @@
 /* We power down some devices after they have been probed. They'll
  * be powered back on later on
  */
-void
+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) {
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/ppc4xx_pic.h linux/arch/ppc/kernel/ppc4xx_pic.h
--- v2.4.5/linux/arch/ppc/kernel/ppc4xx_pic.h	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/ppc4xx_pic.h	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc4xx_pic.h 1.5 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.ppc4xx_pic.h 1.8 06/15/01 13:56:56 paulus
  */
 /*
  *
@@ -14,12 +14,8 @@
 #ifndef	__PPC4XX_PIC_H__
 #define	__PPC4XX_PIC_H__
 
-#include <asm/ptrace.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <linux/config.h>
+#include "local_irq.h"
 
 /* External Global Variables */
 
@@ -30,10 +26,5 @@
 
 extern void	 ppc4xx_pic_init(void);
 extern int	 ppc4xx_pic_get_irq(struct pt_regs *regs);
-
-
-#ifdef __cplusplus
-}
-#endif
 
 #endif /* __PPC4XX_PIC_H__ */
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.4.5/linux/arch/ppc/kernel/ppc_htab.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/ppc_htab.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc_htab.c 1.8 05/17/01 18:14:21 cort
+ * BK Id: SCCS/s.ppc_htab.c 1.11 06/28/01 15:50:16 paulus
  */
 /*
  * PowerPC hash table management proc entry.  Will show information
@@ -41,9 +41,12 @@
 extern unsigned long Hash_size, Hash_mask;
 extern unsigned long _SDR1;
 extern unsigned long htab_reloads;
+extern unsigned long htab_preloads;
 extern unsigned long htab_evicts;
 extern unsigned long pte_misses;
 extern unsigned long pte_errors;
+extern unsigned int primary_pteg_full;
+extern unsigned int htab_hash_searches;
 
 /* these will go into processor.h when I'm done debugging -- Cort */
 #define MMCR0 952
@@ -110,7 +113,7 @@
 {
 	unsigned long mmcr0 = 0, pmc1 = 0, pmc2 = 0;
 	int n = 0, valid;
-	unsigned int kptes = 0, overflow = 0, uptes = 0, zombie_ptes = 0;
+	unsigned int kptes = 0, uptes = 0, zombie_ptes = 0;
 	PTE *ptr;
 	struct task_struct *p;
 	char buffer[512];
@@ -150,41 +153,34 @@
 		n += sprintf( buffer + n, "No Hash Table used\n");
 		goto return_string;
 	}
-	
-	/*
-	 * compute user/kernel pte's table this info can be
-	 * misleading since there can be valid (v bit set) entries
-	 * in the table but their vsid is used by no process (mm->context)
-	 * due to the way tlb invalidation is handled on the ppc
-	 * -- Cort
-	 */
+
+#if !defined(CONFIG_8xx) && !defined(CONFIG_4xx)
 	for ( ptr = Hash ; ptr < Hash_end ; ptr++)
 	{
-		if (ptr->v)
-		{
-			/* make sure someone is using this context/vsid */
-			valid = 0;
-			for_each_task(p)
-			{
-				if (p->mm && (ptr->vsid >> 4) == p->mm->context)
-				{
-					valid = 1;
-					break;
-				}
-			}
-			if ( !valid )
-			{
-				zombie_ptes++;
-				continue;
-			}
-			/* user not allowed read or write */
-			if (ptr->pp == PP_RWXX)
-				kptes++;
-			else
+		unsigned int ctx, mctx, vsid;
+
+		if (!ptr->v)
+			continue;
+		/* make sure someone is using this context/vsid */
+		/* first undo the esid skew */
+		vsid = ptr->vsid;
+		mctx = ((vsid - (vsid & 0xf) * 0x111) >> 4) & 0xfffff;
+		if (mctx == 0) {
+			kptes++;
+			continue;
+		}
+		/* now undo the context skew; 801921 * 897 == 1 mod 2^20 */
+		ctx = (mctx * 801921) & 0xfffff;
+		valid = 0;
+		for_each_task(p) {
+			if (p->mm != NULL && ctx == p->mm->context) {
+				valid = 1;
 				uptes++;
-			if (ptr->h == 1)
-				overflow++;
+				break;
+			}
 		}
+		if (!valid)
+			zombie_ptes++;
 	}
 	
 	n += sprintf( buffer + n,
@@ -195,29 +191,32 @@
 		      "Entries\t\t: %lu\n"
 		      "User ptes\t: %u\n"
 		      "Kernel ptes\t: %u\n"
-		      "Overflows\t: %u\n"
 		      "Zombies\t\t: %u\n"
-		      "Percent full\t: %%%lu\n",
+		      "Percent full\t: %lu%%\n",
                       (unsigned long)(Hash_size>>10),
 		      (Hash_size/(sizeof(PTE)*8)),
 		      (unsigned long)Hash,
 		      Hash_size/sizeof(PTE),
                       uptes,
 		      kptes,
-		      overflow,
 		      zombie_ptes,
 		      ((kptes+uptes)*100) / (Hash_size/sizeof(PTE))
 		);
 
 	n += sprintf( buffer + n,
-		      "Reloads\t\t: %08lx\n"
-		      "Evicts\t\t: %08lx\n",
-		      htab_reloads, htab_evicts);
+		      "Reloads\t\t: %lu\n"
+		      "Preloads\t: %lu\n"
+		      "Searches\t: %u\n"
+		      "Overflows\t: %u\n"
+		      "Evicts\t\t: %lu\n",
+		      htab_reloads, htab_preloads, htab_hash_searches,
+		      primary_pteg_full, htab_evicts);
+#endif /* !8xx && !4xx */
 	
 return_string:
 	n += sprintf( buffer + n,
-		      "Non-error misses: %08lx\n"
-		      "Error misses\t: %08lx\n",
+		      "Non-error misses: %lu\n"
+		      "Error misses\t: %lu\n",
 		      pte_misses, pte_errors);
 	if (*ppos >= strlen(buffer))
 		return 0;
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.4.5/linux/arch/ppc/kernel/ppc_ksyms.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.ppc_ksyms.c 1.31 05/18/01 08:18:10 patch
+ * BK Id: SCCS/s.ppc_ksyms.c 1.36 06/28/01 15:50:16 paulus
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -357,14 +357,12 @@
 #endif /* CONFIG_8xx */
 
 EXPORT_SYMBOL(ret_to_user_hook);
-EXPORT_SYMBOL(do_softirq);
 EXPORT_SYMBOL(next_mmu_context);
 EXPORT_SYMBOL(set_context);
-EXPORT_SYMBOL(mmu_context_overflow);
-EXPORT_SYMBOL(flush_hash_page); /* For MOL */
 EXPORT_SYMBOL(handle_mm_fault); /* For MOL */
 EXPORT_SYMBOL_NOVERS(disarm_decr);
 #if !defined(CONFIG_8xx) && !defined(CONFIG_4xx)
+EXPORT_SYMBOL(flush_hash_page); /* For MOL */
 extern long *intercept_table;
 EXPORT_SYMBOL(intercept_table);
 #endif
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.4.5/linux/arch/ppc/kernel/prep_pci.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/prep_pci.c	Wed Jun 20 11:16:01 2001
@@ -939,17 +939,6 @@
 				pci_write_config_byte(dev, 0x44, reg);
 			}
 		}
-		if ((dev = pci_find_device(PCI_VENDOR_ID_VIA,
-						PCI_DEVICE_ID_VIA_82C586_2,
-						dev)))
-		{
-			/* Force correct USB function interrupt */
-			dev->irq = 11;
-			pcibios_write_config_byte(dev->bus->number,
-					dev->devfn,
-					PCI_INTERRUPT_LINE,
-					dev->irq);
-		}
 	}
 	if ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND,
 				   PCI_DEVICE_ID_WINBOND_82C105, dev))){
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.4.5/linux/arch/ppc/kernel/process.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/process.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.process.c 1.15 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.process.c 1.19 06/15/01 13:56:56 paulus
  */
 /*
  *  linux/arch/ppc/kernel/process.c
@@ -267,6 +267,15 @@
 	printk("Last syscall: %ld ", current->thread.last_syscall);
 	printk("\nlast math %p last altivec %p", last_task_used_math,
 	       last_task_used_altivec);
+
+#ifdef CONFIG_4xx
+	printk("\nPLB0: bear= 0x%8.8x acr=   0x%8.8x besr=  0x%8.8x\n",
+	    mfdcr(DCRN_POB0_BEAR), mfdcr(DCRN_PLB0_ACR),
+	    mfdcr(DCRN_PLB0_BESR));
+	printk("PLB0 to OPB: bear= 0x%8.8x besr0= 0x%8.8x besr1= 0x%8.8x\n",
+	    mfdcr(DCRN_PLB0_BEAR), mfdcr(DCRN_POB0_BESR0),
+	    mfdcr(DCRN_POB0_BESR1));
+#endif
 	
 #ifdef CONFIG_SMP
 	printk(" CPU: %d", current->processor);
@@ -289,7 +298,8 @@
 			printk("\n");
 		}
 	}
-out: ;
+out:
+	print_backtrace((unsigned long *)regs->gpr[1]);
 }
 
 void exit_thread(void)
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/prom.c linux/arch/ppc/kernel/prom.c
--- v2.4.5/linux/arch/ppc/kernel/prom.c	Thu May 24 15:03:05 2001
+++ linux/arch/ppc/kernel/prom.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.prom.c 1.20 05/23/01 00:38:42 cort
+ * BK Id: SCCS/s.prom.c 1.26 06/28/01 15:50:16 paulus
  */
 /*
  * Procedures for interfacing to the Open Firmware PROM on
@@ -42,9 +42,11 @@
 /*
  * Properties whose value is longer than this get excluded from our
  * copy of the device tree.  This way we don't waste space storing
- * things like "driver,AAPL,MacOS,PowerPC" properties.
+ * things like "driver,AAPL,MacOS,PowerPC" properties.  But this value
+ * does need to be big enough to ensure that we don't lose things
+ * like the interrupt-map property on a PCI-PCI bridge.
  */
-#define MAX_PROPERTY_LENGTH	1024
+#define MAX_PROPERTY_LENGTH	4096
 
 struct prom_args {
 	const char *service;
@@ -172,7 +174,6 @@
 #endif
 
 extern void enter_rtas(void *);
-extern unsigned long reloc_offset(void);
 void phys_call_rtas(int, int, int, ...);
 
 extern char cmd_line[512];	/* XXX */
@@ -190,6 +191,14 @@
 #define BOOT_INFO_IS_V2_COMPATIBLE(bi)	((bi)->version >= 2)
 #define BOOT_INFO_IS_V4_COMPATIBLE(bi)	((bi)->version >= 4)
 
+/*
+ * Note that prom_init() and anything called from prom_init() must
+ * use the RELOC/PTRRELOC macros to access any static data in
+ * memory, since the kernel may be running at an address that is
+ * different from the address that it was linked at.
+ * (Note that strings count as static variables.)
+ */
+
 __init
 static void
 prom_exit()
@@ -478,13 +487,14 @@
 			    unsigned int va, unsigned int pa, int mode)
 {
 	unsigned int *pteg;
-	unsigned int hash, i;
+	unsigned int hash, i, vsid;
 
-	hash = ((va >> 5) ^ (va >> 21)) & 0x7fff80;
+	vsid = ((va >> 28) * 0x111) << 12;
+	hash = ((va ^ vsid) >> 5) & 0x7fff80;
 	pteg = (unsigned int *)(htab + (hash & (hsize - 1)));
 	for (i = 0; i < 8; ++i, pteg += 4) {
 		if ((pteg[1] & 1) == 0) {
-			pteg[1] = ((va >> 16) & 0xff80) | 1;
+			pteg[1] = vsid | ((va >> 16) & 0xf80) | 1;
 			pteg[3] = pa | mode;
 			break;
 		}
@@ -670,16 +680,16 @@
 	prom_alloc_htab();
 #endif
 
-#ifdef CONFIG_SMP
-	prom_hold_cpus(mem);
-#endif
-
 	mem = check_display(mem);
 
 	prom_print(RELOC("copying OF device tree..."));
 	mem = copy_device_tree(mem, mem + (1<<20));
 	prom_print(RELOC("done\n"));
 
+#ifdef CONFIG_SMP
+	prom_hold_cpus(mem);
+#endif
+
 	RELOC(klimit) = (char *) (mem - offset);
 
 	/* If we are already running at 0xc0000000, we assume we were loaded by
@@ -1190,7 +1200,7 @@
 	if ((_machine == _MACH_chrp) || (boot_infos == 0 && pmac_newworld))
 		use_of_interrupt_tree = 1;
 
-	mem = finish_node(allnodes, mem, NULL, 0, 0);
+	mem = finish_node(allnodes, mem, NULL, 1, 1);
 	dev_tree_size = mem - (unsigned long) allnodes;
 	klimit = (char *) mem;
 }
@@ -1225,10 +1235,7 @@
 
 	np->name = get_property(np, "name", 0);
 	np->type = get_property(np, "device_type", 0);
-#if 0
-	np->n_addr_cells = naddrc;
-	np->n_size_cells = nsizec;
-#endif
+
 	/* get the device addresses and interrupts */
 	if (ifunc != NULL) {
 		mem_start = ifunc(np, mem_start, naddrc, nsizec);
@@ -1244,16 +1251,6 @@
 	ip = (int *) get_property(np, "#size-cells", 0);
 	if (ip != NULL)
 		nsizec = *ip;
-#if 0
-	if (np->parent == NULL) {
-		/*
-		 * Set the n_addr/size_cells on the root to its
-		 * own values, rather than 0.
-		 */
-		np->n_addr_cells = naddrc;
-		np->n_size_cells = nsizec;
-	}
-#endif	
 
 	/* the f50 sets the name to 'display' and 'compatible' to what we
 	 * expect for the name -- Cort
@@ -1479,7 +1476,8 @@
 		if (ip != NULL)
 			return *ip;
 	} while(np->parent);
-	return 0;
+	/* No #address-cells property for the root node, default to 1 */
+	return 1;
 }
 
 int
@@ -1493,7 +1491,8 @@
 		if (ip != NULL)
 			return *ip;
 	} while(np->parent);
-	return 0;
+	/* No #size-cells property for the root node, default to 1 */
+	return 1;
 }
 
 __init
@@ -1980,7 +1979,7 @@
 	struct property *pp;
 
 	for (pp = np->properties; pp != 0; pp = pp->next) {
-		if (name && strcmp(pp->name, name) == 0) {
+		if (pp->name != NULL && strcmp(pp->name, name) == 0) {
 			if (lenp != 0)
 				*lenp = pp->length;
 			return pp->value;
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.4.5/linux/arch/ppc/kernel/setup.c	Thu May 24 15:03:05 2001
+++ linux/arch/ppc/kernel/setup.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.setup.c 1.32 05/23/01 00:38:42 cort
+ * BK Id: SCCS/s.setup.c 1.44 06/28/01 08:01:06 trini
  */
 /*
  * Common prep/pmac/chrp boot and setup code.
@@ -36,16 +36,16 @@
 #include <asm/mpc8260.h>
 #include <asm/immap_8260.h>
 #endif
+#ifdef CONFIG_4xx
+#include <asm/ppc4xx.h>
+#endif
 #include <asm/bootx.h>
 #include <asm/machdep.h>
 #include <asm/feature.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_OAK
-#include "oak_setup.h"
-#endif /* CONFIG_OAK */
 
-extern void pmac_init(unsigned long r3,
+extern void apus_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
@@ -57,7 +57,7 @@
                       unsigned long r6,
                       unsigned long r7);
 
-extern void prep_init(unsigned long r3,
+extern void gemini_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
@@ -69,19 +69,24 @@
 		     unsigned long r6,
 		     unsigned long r7);
 
-extern void apus_init(unsigned long r3,
+extern void m8260_init(unsigned long r3,
+		     unsigned long r4,
+		     unsigned long r5,
+		     unsigned long r6,
+		     unsigned long r7);
+
+extern void pmac_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
                       unsigned long r7);
 
-extern void gemini_init(unsigned long r3,
+extern void prep_init(unsigned long r3,
                       unsigned long r4,
                       unsigned long r5,
                       unsigned long r6,
                       unsigned long r7);
 
-
 extern void bootx_init(unsigned long r4, unsigned long phys);
 extern unsigned long reloc_offset(void);
 
@@ -332,7 +337,7 @@
 		 * Assume here that all clock rates are the same in a
 		 * smp system.  -- Cort
 		 */
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx) && !defined(CONFIG_8260)
+#if defined(CONFIG_ALL_PPC)
 		if ( have_of )
 		{
 			struct device_node *cpu_node;
@@ -356,7 +361,7 @@
 			len += sprintf(len+buffer, "clock\t\t: %dMHz\n",
 				       *fp / 1000000);
 		}
-#endif /* !CONFIG_4xx && !CONFIG_8xx */
+#endif /* CONFIG_ALL_PPC */
 
 		if (ppc_md.setup_residual != NULL)
 		{
@@ -379,11 +384,12 @@
 			break;
 		}
 
-		len += sprintf(len+buffer, "revision\t: %hd.%hd\n", maj, min);
+		len += sprintf(len+buffer, "revision\t: %hd.%hd (pvr %04x %04x)\n", 
+				maj, min, PVR_VER(pvr), PVR_REV(pvr));
 
 		len += sprintf(buffer+len, "bogomips\t: %lu.%02lu\n",
-			       (CD(loops_per_jiffy)+2500)/(500000/HZ),
-			       (CD(loops_per_jiffy)+2500)/(5000/HZ) % 100);
+			       CD(loops_per_jiffy)/(500000/HZ),
+			       CD(loops_per_jiffy)/(5000/HZ) % 100);
 		bogosum += CD(loops_per_jiffy);
 	}
 
@@ -391,8 +397,8 @@
 	if ( i )
 		len += sprintf(buffer+len, "\n");
 	len += sprintf(buffer+len,"total bogomips\t: %lu.%02lu\n",
-		       (bogosum+2500)/(500000/HZ),
-		       (bogosum+2500)/(5000/HZ) % 100);
+		       bogosum/(500000/HZ),
+		       bogosum/(5000/HZ) % 100);
 #endif /* CONFIG_SMP */
 
 	/*
@@ -441,11 +447,15 @@
 }
 #endif /* CONFIG_ALL_PPC */
 
-#ifdef CONFIG_6xx
+#if defined(CONFIG_6xx) || defined(CONFIG_PPC64BRIDGE)
 /*
  * We're called here very early in the boot.  We determine the machine
  * type and call the appropriate low-level setup functions.
  *  -- Cort <cort@fsmlabs.com>
+ *
+ * Note that the kernel may be running at an address which is different
+ * from the address that it was linked at, so we must use RELOC/PTRRELOC
+ * to access static data (including strings).  -- paulus
  */
 __init
 unsigned long
@@ -454,65 +464,36 @@
 	extern char __bss_start, _end;
  	unsigned long phys;
 	unsigned long offset = reloc_offset();
-	unsigned long local_have_of = 1, local_machine;
-	struct bi_record *rec;
-	
+
  	/* Default */
  	phys = offset + KERNELBASE;
-	
-#if defined(CONFIG_APUS)
-	return phys;
-#endif	
-	
+
 	/* First zero the BSS -- use memset, some arches don't have
 	 * caches on yet */
-	memset_io(PTRRELOC(&__bss_start),0 , &_end - &__bss_start);
+	memset_io(PTRRELOC(&__bss_start), 0, &_end - &__bss_start);
 
-#if defined(CONFIG_ALL_PPC) || defined(CONFIG_GEMINI)
+#if defined(CONFIG_ALL_PPC)
 	/* If we came here from BootX, clear the screen,
 	 * set up some pointers and return. */
-#if defined(CONFIG_ALL_PPC)	
 	if ((r3 == 0x426f6f58) && (r5 == 0)) {
 		bootx_init(r4, phys);
 		return phys;
 	}
-#endif
 
 	/* check if we're prep, return if we are */
 	if ( *(unsigned long *)(0) == 0xdeadc0de )
 		return phys;
-	
-	/*
-	 * See if we have any bootloader info passed along.  If we do,
-	 * get the machine type and find out if we have OF.
-	 *
-	 * The strategy here is to assume that we want to call prom_init()
-	 * unless the bootinfo data passed to us tell us that we don't
-	 * have OF.
-	 * -- Cort <cort@fsmlabs.com>
+
+	/* 
+	 * for now, don't use bootinfo because it breaks yaboot 0.5
+	 * and assume that if we didn't find a magic number, we have OF
 	 */
-	rec = (struct bi_record *)_ALIGN((ulong)PTRRELOC(&__bss_start)+(1<<20)-1,(1<<20));
-	if ( rec->tag == BI_FIRST )
-	{
-		for ( ; rec->tag != BI_LAST ;
-		      rec = (struct bi_record *)((ulong)rec + rec->size) )
-		{
-			ulong *data = rec->data;
-			if ( rec->tag == BI_MACHTYPE )
-			{
-				local_machine = data[0];
-				local_have_of = data[1];
-			}
-		}
-	}
+	phys = prom_init(r3, r4, (prom_entry)r5);
+#endif
 
-	if ( local_have_of )
-		phys = prom_init( r3, r4, (prom_entry)r5);
-#endif	
-	
 	return phys;
 }
-#endif /* CONFIG_6xx */
+#endif /* CONFIG_6xx || CONFIG_PPC64BRIDGE */
 
 /*
  * Find out what kind of machine we're on and save any data we need
@@ -522,6 +503,10 @@
 identify_machine(unsigned long r3, unsigned long r4, unsigned long r5,
 		 unsigned long r6, unsigned long r7)
 {
+#ifdef CONFIG_CMDLINE
+	strcpy(cmd_line, CONFIG_CMDLINE);
+#endif /* CONFIG_CMDLINE */
+
 	parse_bootinfo();
 
 	if ( ppc_md.progress ) ppc_md.progress("id mach(): start", 0x100);
@@ -809,7 +794,7 @@
 	ppc_md.setup_arch();
 	if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab);
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && defined(CONFIG_ALL_PPC)
 	/* We create the "pci-OF-bus-map" property now so it appear in the
 	 * /proc device tree
 	 */
@@ -825,7 +810,7 @@
 			prom_add_property(find_path_device("/"), of_prop);
 		}
 	}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI && CONFIG_ALL_PPC */
 
 	paging_init();
 	sort_exception_table();
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/sleep.S linux/arch/ppc/kernel/sleep.S
--- v2.4.5/linux/arch/ppc/kernel/sleep.S	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/sleep.S	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.sleep.S 1.7 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.sleep.S 1.10 06/28/01 15:50:17 paulus
  */
 /*
  * This file contains sleep low-level functions for PowerBook G3.
@@ -194,7 +194,7 @@
 	lis	r3,0x2000	/* Ku = 1, VSID = 0 */
 	li	r4,0
 3:	mtsrin	r3,r4
-	addi	r3,r3,1		/* increment VSID */
+	addi	r3,r3,0x111	/* increment VSID */
 	addis	r4,r4,0x1000	/* address of next segment */
 	bdnz	3b
 	
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.4.5/linux/arch/ppc/kernel/smp.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/smp.c	Mon Jun 11 19:15:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.smp.c 1.23 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.smp.c 1.25 05/23/01 00:38:42 cort
  */
 /*
  * Smp support for ppc.
@@ -670,12 +670,12 @@
 static void
 smp_gemini_kick_cpu(int nr)
 {
-	openpic_init_processor( 1<<i );
+	openpic_init_processor( 1<<nr );
 	openpic_init_processor( 0 );
 }
 
 static void
-smp_gemini_setup_cpu(void)
+smp_gemini_setup_cpu(int cpu_nr)
 {
 	if (OpenPIC_Addr)
 		do_openpic_setup_cpu();
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.4.5/linux/arch/ppc/kernel/time.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/time.c	Mon Jun 11 19:15:27 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.time.c 1.15 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.time.c 1.18 06/06/01 22:33:09 paulus
  */
 /*
  * Common time routines among all ppc machines.
@@ -210,6 +210,10 @@
 		ppc_md.heartbeat();
 	
 	hardirq_exit(cpu);
+
+	if (softirq_pending(cpu))
+		do_softirq();
+
 	return 1; /* lets ret_from_int know we can do checks */
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.4.5/linux/arch/ppc/kernel/traps.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/kernel/traps.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.traps.c 1.11 05/17/01 18:14:22 cort
+ * BK Id: SCCS/s.traps.c 1.14 06/15/01 13:00:20 paulus
  */
 /*
  *  linux/arch/ppc/kernel/traps.c
@@ -82,7 +82,6 @@
 	spin_lock_irq(&oops_lock);
 	printk("Oops: %s, sig: %ld\n", str, err);
 	show_regs(fp);
-	print_backtrace((unsigned long *)fp->gpr[1]);
 	spin_unlock_irq(&oops_lock);
 	/* do_exit() should take care of panic'ing from an interrupt
 	 * context so we don't handle it here
@@ -186,7 +185,6 @@
 	}
 #endif
 	show_regs(regs);
-	print_backtrace((unsigned long *)regs->gpr[1]);
 	panic("System Management Interrupt");
 }
 
@@ -334,7 +332,6 @@
 	debugger(regs);
 #endif
 	show_regs(regs);
-	print_backtrace((unsigned long *)regs->gpr[1]);
 	panic("kernel stack overflow");
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/Makefile linux/arch/ppc/mm/Makefile
--- v2.4.5/linux/arch/ppc/mm/Makefile	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/mm/Makefile	Mon Jul  2 14:34:57 2001
@@ -1,4 +1,4 @@
-# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+# BK Id: SCCS/s.Makefile 1.6 06/28/01 15:50:17 paulus
 #
 #
 # Makefile for the linux ppc-specific parts of the memory manager.
@@ -9,8 +9,20 @@
 #
 # Note 2! The CFLAGS definition is now in the main makefile...
 
+USE_STANDARD_AS_RULE	:= true
+
+ifdef CONFIG_PPC64BRIDGE
+EXTRA_AFLAGS		:= -Wa,-mppc64bridge
+endif
+
 O_TARGET		:= mm.o
 obj-y			:= fault.o init.o mem_pieces.o extable.o
+
+ifneq ($(CONFIG_8xx),y)
+ifneq ($(CONFIG_4xx),y)
+obj-y			+= hashtable.o
+endif
+endif
 
 obj-$(CONFIG_4xx)	+= 4xx_tlb.o
 
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/fault.c linux/arch/ppc/mm/fault.c
--- v2.4.5/linux/arch/ppc/mm/fault.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/mm/fault.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.fault.c 1.10 05/17/01 18:14:23 cort
+ * BK Id: SCCS/s.fault.c 1.13 06/28/01 15:50:17 paulus
  */
 /*
  *  arch/ppc/mm/fault.c
@@ -44,11 +44,12 @@
 int debugger_kernel_faults = 1;
 #endif
 
-unsigned long htab_reloads = 0; /* updated by head.S:hash_page() */
-unsigned long htab_evicts = 0;  /* updated by head.S:hash_page() */
-unsigned long pte_misses = 0; /* updated by do_page_fault() */
-unsigned long pte_errors = 0; /* updated by do_page_fault() */
-unsigned int probingmem = 0;
+unsigned long htab_reloads;	/* updated by hashtable.S:hash_page() */
+unsigned long htab_evicts; 	/* updated by hashtable.S:hash_page() */
+unsigned long htab_preloads;	/* updated by hashtable.S:add_hash_page() */
+unsigned long pte_misses;	/* updated by do_page_fault() */
+unsigned long pte_errors;	/* updated by do_page_fault() */
+unsigned int probingmem;
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
 void bad_page_fault(struct pt_regs *, unsigned long, int sig);
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/hashtable.S linux/arch/ppc/mm/hashtable.S
--- v2.4.5/linux/arch/ppc/mm/hashtable.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/ppc/mm/hashtable.S	Mon Jul  2 14:34:57 2001
@@ -0,0 +1,627 @@
+/*
+ * BK Id: SCCS/s.hashtable.S 1.16 06/29/01 08:51:52 paulus
+ */
+/*
+ *  arch/ppc/kernel/hashtable.S
+ *
+ *  $Id: hashtable.S,v 1.6 1999/10/08 01:56:15 paulus Exp $
+ *
+ *  PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP
+ *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu>
+ *  Adapted for Power Macintosh by Paul Mackerras.
+ *  Low-level exception handlers and MMU support
+ *  rewritten by Paul Mackerras.
+ *    Copyright (C) 1996 Paul Mackerras.
+ *
+ *  This file contains low-level assembler routines for managing
+ *  the PowerPC MMU hash table.  (PPC 8xx processors don't use a
+ *  hash table, so this file is not used on them.)
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *	
+ */
+
+#include <linux/config.h>
+#include "../kernel/ppc_asm.h"
+#include <asm/processor.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+
+#ifdef CONFIG_SMP
+	.comm	hash_table_lock,4
+#endif /* CONFIG_SMP */
+
+/*
+ * Load a PTE into the hash table, if possible.
+ * The address is in r4, and r3 contains an access flag:
+ * _PAGE_RW (0x400) if a write.
+ * r23 contains the SRR1 value, from which we use the MSR_PR bit.
+ * SPRG3 contains the physical address of the current task's thread.
+ *
+ * Returns to the caller if the access is illegal or there is no
+ * mapping for the address.  Otherwise it places an appropriate PTE
+ * in the hash table and returns from the exception.
+ * Uses r0, r2 - r7, ctr, lr.
+ */
+	.text
+	.globl	hash_page
+hash_page:
+#ifdef CONFIG_PPC64BRIDGE
+	mfmsr	r0
+	clrldi	r0,r0,1		/* make sure it's in 32-bit mode */
+	MTMSRD(r0)
+	isync
+#endif
+	tophys(r7,0)			/* gets -KERNELBASE into r7 */
+#ifdef CONFIG_SMP
+	addis	r2,r7,hash_table_lock@h
+	ori	r2,r2,hash_table_lock@l
+	mfspr	r5,SPRG3
+	lwz	r0,PROCESSOR-THREAD(r5)
+	oris	r0,r0,0x0fff
+	b	10f
+11:	lwz	r6,0(r2)
+	cmpwi	0,r6,0
+	bne	11b
+10:	lwarx	r6,0,r2
+	cmpwi	0,r6,0
+	bne-	11b
+	stwcx.	r0,0,r2
+	bne-	10b
+	isync
+#endif
+	/* Get PTE (linux-style) and check access */
+	lis	r0,KERNELBASE@h		/* check if kernel address */
+	cmplw	0,r4,r0
+	mfspr	r2,SPRG3		/* current task's THREAD (phys) */
+	ori	r3,r3,_PAGE_USER|_PAGE_PRESENT /* test low addresses as user */
+	lwz	r5,PGDIR(r2)		/* virt page-table root */
+	blt+	112f			/* assume user more likely */
+	lis	r5,swapper_pg_dir@ha	/* if kernel address, use */
+	addi	r5,r5,swapper_pg_dir@l	/* kernel page table */
+	rlwimi	r3,r23,32-12,29,29	/* MSR_PR -> _PAGE_USER */
+112:	add	r5,r5,r7		/* convert to phys addr */
+	rlwimi	r5,r4,12,20,29		/* insert top 10 bits of address */
+	lwz	r5,0(r5)		/* get pmd entry */
+	rlwinm.	r5,r5,0,0,19		/* extract address of pte page */
+#ifdef CONFIG_SMP
+	beq-	hash_page_out		/* return if no mapping */
+#else
+	/* XXX it seems like the 601 will give a machine fault on the
+	   rfi if its alignment is wrong (bottom 4 bits of address are
+	   8 or 0xc) and we have had a not-taken conditional branch
+	   to the address following the rfi. */
+	beqlr-
+#endif
+	add	r2,r5,r7		/* convert to phys addr */
+	rlwimi	r2,r4,22,20,29		/* insert next 10 bits of address */
+	rlwinm	r0,r3,32-3,24,24	/* _PAGE_RW access -> _PAGE_DIRTY */
+	ori	r0,r0,_PAGE_ACCESSED|_PAGE_HASHPTE
+
+	/*
+	 * Update the linux PTE atomically.  We do the lwarx up-front
+	 * because almost always, there won't be a permission violation
+	 * and there won't already be an HPTE, and thus we will have
+	 * to update the PTE to set _PAGE_HASHPTE.  -- paulus.
+	 */
+retry:
+	lwarx	r6,0,r2			/* get linux-style pte */
+	andc.	r5,r3,r6		/* check access & ~permission */
+#ifdef CONFIG_SMP
+	bne-	hash_page_out		/* return if access not permitted */
+#else
+	bnelr-
+#endif
+	or	r5,r0,r6		/* set accessed/dirty bits */
+	stwcx.	r5,0,r2			/* attempt to update PTE */
+	bne-	retry			/* retry if someone got there first */
+
+	mfsrin	r3,r4			/* get segment reg for segment */
+	mr	r2,r8			/* we have saved r2 but not r8 */
+	bl	create_hpte		/* add the hash table entry */
+	mr	r8,r2
+
+/*
+ * htab_reloads counts the number of times we have to fault an
+ * HPTE into the hash table.  This should only happen after a
+ * fork (because fork does a flush_tlb_mm) or a vmalloc or ioremap.
+ * Where a page is faulted into a process's address space,
+ * update_mmu_cache gets called to put the HPTE into the hash table
+ * and those are counted as preloads rather than reloads.
+ */
+	addis	r2,r7,htab_reloads@ha
+	lwz	r3,htab_reloads@l(r2)
+	addi	r3,r3,1
+	stw	r3,htab_reloads@l(r2)
+
+#ifdef CONFIG_SMP
+	eieio
+	addis	r2,r7,hash_table_lock@ha
+	li	r0,0
+	stw	r0,hash_table_lock@l(r2)
+#endif
+
+	/* Return from the exception */
+	lwz	r3,_CCR(r21)
+	lwz	r4,_LINK(r21)
+	lwz	r5,_CTR(r21)
+	mtcrf	0xff,r3
+	mtlr	r4
+	mtctr	r5
+	lwz	r0,GPR0(r21)
+	lwz	r1,GPR1(r21)
+	lwz	r2,GPR2(r21)
+	lwz	r3,GPR3(r21)
+	lwz	r4,GPR4(r21)
+	lwz	r5,GPR5(r21)
+	lwz	r6,GPR6(r21)
+	lwz	r7,GPR7(r21)
+	/* we haven't used xer */
+	mtspr	SRR1,r23
+	mtspr	SRR0,r22
+	lwz	r20,GPR20(r21)
+	lwz	r22,GPR22(r21)
+	lwz	r23,GPR23(r21)
+	lwz	r21,GPR21(r21)
+	RFI
+	
+#ifdef CONFIG_SMP
+hash_page_out:
+	eieio
+	addis	r2,r7,hash_table_lock@ha
+	li	r0,0
+	stw	r0,hash_table_lock@l(r2)
+	blr
+#endif /* CONFIG_SMP */
+
+/*
+ * Add an entry for a particular page to the hash table.
+ *
+ * add_hash_page(unsigned context, unsigned long va, pte_t pte)
+ *
+ * We assume any necessary modifications to the pte (e.g. setting
+ * the accessed bit) have already been done and that there is actually
+ * a hash table in use (i.e. we're not on a 603).
+ */
+_GLOBAL(add_hash_page)
+	mflr	r0
+	stw	r0,4(r1)
+
+	/* Convert context and va to VSID */
+	mulli	r3,r3,897*16		/* multiply context by context skew */
+	rlwinm	r0,r4,4,28,31		/* get ESID (top 4 bits of va) */
+	mulli	r0,r0,0x111		/* multiply by ESID skew */
+	add	r3,r3,r0		/* note create_hpte trims to 24 bits */
+
+	/*
+	 * We disable interrupts here, even on UP, because we don't
+	 * want to race with hash_page, and because we want the
+	 * _PAGE_HASHPTE bit to be a reliable indication of whether
+	 * the HPTE exists (or at least whether one did once).  -- paulus
+	 */
+	mfmsr	r10
+	SYNC
+	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
+	mtmsr	r0
+	SYNC
+
+#ifdef CONFIG_SMP
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+	lwz	r8,PROCESSOR(r2)
+	oris	r8,r8,10
+10:	lwarx	r7,0,r9
+	cmpi	0,r7,0
+	bne-	11f
+	stwcx.	r8,0,r9
+	beq+	12f
+11:	lwz	r7,0(r9)
+	cmpi	0,r7,0
+	beq	10b
+	b	11b
+12:	isync
+#endif
+
+	/*
+	 * Fetch the linux pte and test and set _PAGE_HASHPTE atomically.
+	 * If _PAGE_HASHPTE was already set, we don't replace the existing
+	 * HPTE, so we just unlock and return.
+	 */
+	mr	r7,r5
+1:	lwarx	r6,0,r7
+	andi.	r0,r6,_PAGE_HASHPTE
+	bne	9f			/* if HASHPTE already set, done */
+	ori	r5,r6,_PAGE_ACCESSED|_PAGE_HASHPTE
+	stwcx.	r5,0,r7
+	bne-	1b
+
+	li	r7,0			/* no address offset needed */
+	bl	create_hpte
+
+	lis	r8,htab_preloads@ha
+	lwz	r3,htab_preloads@l(r8)
+	addi	r3,r3,1
+	stw	r3,htab_preloads@l(r8)
+
+9:
+#ifdef CONFIG_SMP
+	eieio
+	li	r0,0
+	stw	r0,0(r9)		/* clear hash_table_lock */
+#endif
+
+	lwz	r0,4(r1)
+	mtlr	r0
+
+	/* reenable interrupts */
+	mtmsr	r10
+	SYNC
+	blr
+
+/*
+ * This routine adds a hardware PTE to the hash table.
+ * It is designed to be called with the MMU either on or off.
+ * r3 contains the VSID, r4 contains the virtual address,
+ * r5 contains the linux PTE, r6 contains the old value of the
+ * linux PTE (before setting _PAGE_HASHPTE) and r7 contains the
+ * offset to be added to addresses (0 if the MMU is on,
+ * -KERNELBASE if it is off).
+ * On SMP, the caller should have the hash_table_lock held.
+ * We assume that the caller has (or will) set the _PAGE_HASHPTE
+ * bit in the linux PTE in memory.  The value passed in r6 should
+ * be the old linux PTE value; if it doesn't have _PAGE_HASHPTE set
+ * this routine will skip the search for an existing HPTE.
+ * This procedure modifies r0, r3 - r6, r8, cr0.
+ *  -- paulus.
+ *
+ * For speed, 4 of the instructions get patched once the size and
+ * physical address of the hash table are known.  These definitions
+ * of Hash_base and Hash_bits below are just an example.
+ */
+Hash_base = 0xc0180000
+Hash_bits = 12				/* e.g. 256kB hash table */
+Hash_msk = (((1 << Hash_bits) - 1) * 64)
+
+#ifndef CONFIG_PPC64BRIDGE
+/* defines for the PTE format for 32-bit PPCs */
+#define PTE_SIZE	8
+#define PTEG_SIZE	64
+#define LG_PTEG_SIZE	6
+#define LDPTEu		lwzu
+#define STPTE		stw
+#define CMPPTE		cmpw
+#define PTE_H		0x40
+#define PTE_V		0x80000000
+#define TST_V(r)	rlwinm. r,r,0,0,0
+#define SET_V(r)	oris r,r,PTE_V@h
+#define CLR_V(r,t)	rlwinm r,r,0,1,31
+
+#else
+/* defines for the PTE format for 64-bit PPCs */
+#define PTE_SIZE	16
+#define PTEG_SIZE	128
+#define LG_PTEG_SIZE	7
+#define LDPTEu		ldu
+#define STPTE		std
+#define CMPPTE		cmpd
+#define PTE_H		2
+#define PTE_V		1
+#define TST_V(r)	andi. r,r,PTE_V
+#define SET_V(r)	ori r,r,PTE_V
+#define CLR_V(r,t)	li t,PTE_V; andc r,r,t
+#endif /* CONFIG_PPC64BRIDGE */
+
+#define HASH_LEFT	31-(LG_PTEG_SIZE+Hash_bits-1)
+#define HASH_RIGHT	31-LG_PTEG_SIZE
+
+_GLOBAL(create_hpte)
+	/* Convert linux-style PTE (r5) to low word of PPC-style PTE (r8) */
+	rlwinm	r8,r5,32-10,31,31	/* _PAGE_RW -> PP lsb */
+	rlwinm	r0,r5,32-7,31,31	/* _PAGE_DIRTY -> PP lsb */
+	and	r8,r8,r0		/* writable if _RW & _DIRTY */
+	rlwimi	r5,r5,32-1,30,30	/* _PAGE_USER -> PP msb */
+	rlwimi	r5,r5,32-2,31,31	/* _PAGE_USER -> PP lsb */
+	ori	r8,r8,0xe14		/* clear out reserved bits and M */
+	andc	r8,r5,r8		/* PP = user? (rw&dirty? 2: 3): 0 */
+#ifdef CONFIG_SMP
+	ori	r8,r8,_PAGE_COHERENT	/* set M (coherence required) */
+#endif
+
+#ifdef CONFIG_POWER4
+	/*
+	 * XXX hack hack hack - translate 32-bit "physical" addresses
+	 * in the linux page tables to 42-bit real addresses in such
+	 * a fashion that we can get at the I/O we need to access.
+	 *	-- paulus
+	 */
+	cmpwi	r8,0
+	rlwinm	r0,r8,16,16,30
+	bge	57f
+	cmplwi	r0,0xfe00
+	li	r0,0x3fd
+	bne	56f
+	li	r0,0x3ff
+56:	sldi	r0,r0,32
+	or	r8,r8,r0
+57:
+#endif
+
+	/* Construct the high word of the PPC-style PTE (r5) */
+#ifndef CONFIG_PPC64BRIDGE
+	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
+	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
+	sldi	r5,r3,12		/* shift vsid into position */
+	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+	SET_V(r5)			/* set V (valid) bit */
+
+	/* Get the address of the primary PTE group in the hash table (r3) */
+	.globl	hash_page_patch_A
+hash_page_patch_A:
+	addis	r0,r7,Hash_base@h	/* base address of hash table */
+	rlwimi	r0,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
+	rlwinm	r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+	xor	r3,r3,r0		/* make primary hash */
+	li	r0,8			/* PTEs/group */
+
+	/*
+	 * Test the _PAGE_HASHPTE bit in the old linux PTE, and skip the search
+	 * if it is clear, meaning that the HPTE isn't there already...
+	 */
+	andi.	r6,r6,_PAGE_HASHPTE
+	beq+	10f			/* no PTE: go look for an empty slot */
+	tlbie	r4
+
+	addis	r4,r7,htab_hash_searches@ha
+	lwz	r6,htab_hash_searches@l(r4)
+	addi	r6,r6,1			/* count how many searches we do */
+	stw	r6,htab_hash_searches@l(r4)
+
+	/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
+	mtctr	r0
+	addi	r4,r3,-PTE_SIZE
+1:	LDPTEu	r6,PTE_SIZE(r4)		/* get next PTE */
+	CMPPTE	0,r6,r5
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	found_slot
+
+	/* Search the secondary PTEG for a matching PTE */
+	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
+	.globl	hash_page_patch_B
+hash_page_patch_B:
+	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
+	xori	r4,r4,(-PTEG_SIZE & 0xffff)
+	addi	r4,r4,-PTE_SIZE
+	mtctr	r0
+2:	LDPTEu	r6,PTE_SIZE(r4)
+	CMPPTE	0,r6,r5
+	bdnzf	2,2b
+	beq+	found_slot
+	xori	r5,r5,PTE_H		/* clear H bit again */
+
+	/* Search the primary PTEG for an empty slot */
+10:	mtctr	r0
+	addi	r4,r3,-PTE_SIZE		/* search primary PTEG */
+1:	LDPTEu	r6,PTE_SIZE(r4)		/* get next PTE */
+	TST_V(r6)			/* test valid bit */
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	found_empty
+
+	/* update counter of times that the primary PTEG is full */
+	addis	r4,r7,primary_pteg_full@ha
+	lwz	r6,primary_pteg_full@l(r4)
+	addi	r6,r6,1
+	stw	r6,primary_pteg_full@l(r4)
+
+	/* Search the secondary PTEG for an empty slot */
+	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
+	.globl	hash_page_patch_C
+hash_page_patch_C:
+	xoris	r4,r3,Hash_msk>>16	/* compute secondary hash */
+	xori	r4,r4,(-PTEG_SIZE & 0xffff)
+	addi	r4,r4,-PTE_SIZE
+	mtctr	r0
+2:	LDPTEu	r6,PTE_SIZE(r4)
+	TST_V(r6)
+	bdnzf	2,2b
+	beq+	found_empty
+	xori	r5,r5,PTE_H		/* clear H bit again */
+
+	/*
+	 * Choose an arbitrary slot in the primary PTEG to overwrite.
+	 * Since both the primary and secondary PTEGs are full, and we
+	 * have no information that the PTEs in the primary PTEG are
+	 * more important or useful than those in the secondary PTEG,
+	 * and we know there is a definite (although small) speed
+	 * advantage to putting the PTE in the primary PTEG, we always
+	 * put the PTE in the primary PTEG.
+	 */
+	addis	r4,r7,next_slot@ha
+	lwz	r6,next_slot@l(r4)
+	addi	r6,r6,PTE_SIZE
+	andi.	r6,r6,7*PTE_SIZE
+#ifdef CONFIG_POWER4
+	/*
+	 * Since we don't have BATs on POWER4, we rely on always having
+	 * PTEs in the hash table to map the hash table and the code
+	 * that manipulates it in virtual mode, namely flush_hash_page and
+	 * flush_hash_segments.  Otherwise we can get a DSI inside those
+	 * routines which leads to a deadlock on the hash_table_lock on
+	 * SMP machines.  We avoid this by never overwriting the first
+	 * PTE of each PTEG if it is already valid.
+	 *	-- paulus.
+	 */
+	bne	102f
+	li	r6,PTE_SIZE
+102:
+#endif /* CONFIG_POWER4 */
+	stw	r6,next_slot@l(r4)
+	add	r4,r3,r6
+
+	/* update counter of evicted pages */
+	addis	r6,r7,htab_evicts@ha
+	lwz	r3,htab_evicts@l(r6)
+	addi	r3,r3,1
+	stw	r3,htab_evicts@l(r6)
+
+#ifndef CONFIG_SMP
+	/* Store PTE in PTEG */
+found_empty:
+	STPTE	r5,0(r4)
+found_slot:
+	STPTE	r8,PTE_SIZE/2(r4)
+
+#else /* CONFIG_SMP */
+/*
+ * Between the tlbie above and updating the hash table entry below,
+ * another CPU could read the hash table entry and put it in its TLB.
+ * There are 3 cases:
+ * 1. using an empty slot
+ * 2. updating an earlier entry to change permissions (i.e. enable write)
+ * 3. taking over the PTE for an unrelated address
+ *
+ * In each case it doesn't really matter if the other CPUs have the old
+ * PTE in their TLB.  So we don't need to bother with another tlbie here,
+ * which is convenient as we've overwritten the register that had the
+ * address. :-)  The tlbie above is mainly to make sure that this CPU comes
+ * and gets the new PTE from the hash table.
+ *
+ * We do however have to make sure that the PTE is never in an invalid
+ * state with the V bit set.
+ */
+found_empty:
+found_slot:
+	CLR_V(r5,r0)		/* clear V (valid) bit in PTE */
+	STPTE	r5,0(r4)
+	sync
+	TLBSYNC
+	STPTE	r8,PTE_SIZE/2(r4) /* put in correct RPN, WIMG, PP bits */
+	sync
+	SET_V(r5)
+	STPTE	r5,0(r4)	/* finally set V bit in PTE */
+#endif /* CONFIG_SMP */
+
+	sync		/* make sure pte updates get to memory */
+	blr
+
+	.comm	next_slot,4
+	.comm	primary_pteg_full,4
+	.comm	htab_hash_searches,4
+
+/*
+ * Flush the entry for a particular page from the hash table.
+ *
+ * flush_hash_page(unsigned context, unsigned long va, pte_t *ptep)
+ *
+ * We assume that there is a hash table in use (Hash != 0).
+ */
+_GLOBAL(flush_hash_page)
+	/* Convert context and va to VSID */
+	mulli	r3,r3,897*16		/* multiply context by context skew */
+	rlwinm	r0,r4,4,28,31		/* get ESID (top 4 bits of va) */
+	mulli	r0,r0,0x111		/* multiply by ESID skew */
+	add	r3,r3,r0		/* note code below trims to 24 bits */
+
+	/*
+	 * We disable interrupts here, even on UP, because we want
+	 * the _PAGE_HASHPTE bit to be a reliable indication of
+	 * whether the HPTE exists.  -- paulus
+	 */
+	mfmsr	r10
+	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */
+	SYNC
+	mtmsr	r0
+	SYNC
+
+#ifdef CONFIG_SMP
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+	lwz	r8,PROCESSOR(r2)
+	oris	r8,r8,9
+10:	lwarx	r7,0,r9
+	cmpi	0,r7,0
+	bne-	11f
+	stwcx.	r8,0,r9
+	beq+	12f
+11:	lwz	r7,0(r9)
+	cmpi	0,r7,0
+	beq	10b
+	b	11b
+12:	isync
+#endif
+
+	/*
+	 * Check the _PAGE_HASHPTE bit in the linux PTE.  If it is
+	 * already clear, we're done.  If not, clear it (atomically)
+	 * and proceed.  -- paulus.
+	 */
+1:	lwarx	r6,0,r5			/* fetch the pte */
+	andi.	r0,r6,_PAGE_HASHPTE
+	beq	9f			/* done if HASHPTE is already clear */
+	rlwinm	r6,r6,0,31,29		/* clear HASHPTE bit */
+	stwcx.	r6,0,r5			/* update the pte */
+	bne-	1b
+
+	/* Construct the high word of the PPC-style PTE (r5) */
+#ifndef CONFIG_PPC64BRIDGE
+	rlwinm	r5,r3,7,1,24		/* put VSID in 0x7fffff80 bits */
+	rlwimi	r5,r4,10,26,31		/* put in API (abbrev page index) */
+#else /* CONFIG_PPC64BRIDGE */
+	clrlwi	r3,r3,8			/* reduce vsid to 24 bits */
+	sldi	r5,r3,12		/* shift vsid into position */
+	rlwimi	r5,r4,16,20,24		/* put in API (abbrev page index) */
+#endif /* CONFIG_PPC64BRIDGE */
+	SET_V(r5)			/* set V (valid) bit */
+
+	/* Get the address of the primary PTE group in the hash table (r3) */
+	.globl	flush_hash_patch_A
+flush_hash_patch_A:
+	lis	r8,Hash_base@h		/* base address of hash table */
+	rlwimi	r8,r3,LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT    /* VSID -> hash */
+	rlwinm	r3,r4,20+LG_PTEG_SIZE,HASH_LEFT,HASH_RIGHT /* PI -> hash */
+	xor	r3,r3,r8		/* make primary hash */
+	li	r8,8			/* PTEs/group */
+
+	/* Search the primary PTEG for a PTE whose 1st (d)word matches r5 */
+	mtctr	r8
+	addi	r7,r3,-PTE_SIZE
+1:	LDPTEu	r0,PTE_SIZE(r7)		/* get next PTE */
+	CMPPTE	0,r0,r5
+	bdnzf	2,1b			/* loop while ctr != 0 && !cr0.eq */
+	beq+	3f
+
+	/* Search the secondary PTEG for a matching PTE */
+	ori	r5,r5,PTE_H		/* set H (secondary hash) bit */
+	.globl	flush_hash_patch_B
+flush_hash_patch_B:
+	xoris	r7,r3,Hash_msk>>16	/* compute secondary hash */
+	xori	r7,r7,(-PTEG_SIZE & 0xffff)
+	addi	r7,r7,-PTE_SIZE
+	mtctr	r8
+2:	LDPTEu	r0,PTE_SIZE(r7)
+	CMPPTE	0,r0,r5
+	bdnzf	2,2b
+	bne-	4f			/* should never fail to find it */
+
+3:	li	r0,0
+	STPTE	r0,0(r7)		/* invalidate entry */
+4:	sync
+	tlbie	r4			/* in hw tlb too */
+	sync
+
+#ifdef CONFIG_SMP
+	TLBSYNC
+9:	li	r0,0
+	stw	r0,0(r9)		/* clear hash_table_lock */
+#endif
+
+9:	mtmsr	r10
+	SYNC
+	blr
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.4.5/linux/arch/ppc/mm/init.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/mm/init.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.init.c 1.22 05/17/01 18:14:23 cort
+ * BK Id: SCCS/s.init.c 1.27 06/28/01 15:50:17 paulus
  */
 /*
  *  PowerPC version 
@@ -73,9 +73,15 @@
 
 #define	PGTOKB(pages)	(((pages) * PAGE_SIZE) >> 10)
 
+mm_context_t next_mmu_context;
+unsigned long context_map[(LAST_CONTEXT+1) / (8*sizeof(unsigned long))];
+#ifdef FEW_CONTEXTS
+atomic_t nr_free_contexts;
+struct mm_struct *context_mm[LAST_CONTEXT+1];
+void steal_context(void);
+#endif /* FEW_CONTEXTS */
+
 int prom_trashed;
-atomic_t next_mmu_context;
-rwlock_t context_overflow_lock __cacheline_aligned = RW_LOCK_UNLOCKED;
 unsigned long *end_of_DRAM;
 unsigned long total_memory;
 unsigned long total_lowmem;
@@ -187,12 +193,6 @@
 /* max amount of low RAM to map in */
 unsigned long __max_low_memory = MAX_LOW_MEM;
 
-void __bad_pte(pmd_t *pmd)
-{
-	printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
-	pmd_val(*pmd) = (unsigned long) BAD_PAGETABLE;
-}
-
 int do_check_pgt_cache(int low, int high)
 {
 	int freed = 0;
@@ -211,35 +211,6 @@
 	return freed;
 }
 
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a 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 *empty_bad_page_table;
-
-pte_t * __bad_pagetable(void)
-{
-	clear_page(empty_bad_page_table);
-	return empty_bad_page_table;
-}
-
-void *empty_bad_page;
-
-pte_t __bad_page(void)
-{
-	clear_page(empty_bad_page);
-	return pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED));
-}
-
 void show_mem(void)
 {
 	int i,free = 0,total = 0,reserved = 0;
@@ -319,21 +290,10 @@
 
 void si_meminfo(struct sysinfo *val)
 {
-	int i;
-
-	i = max_mapnr;
-	val->totalram = 0;
+	val->totalram = totalram_pages;
 	val->sharedram = 0;
 	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
-	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->totalhigh = totalhigh_pages;
 	val->freehigh = nr_free_highpages();
 	val->mem_unit = PAGE_SIZE;
@@ -482,14 +442,16 @@
 	if (pg != 0) {
 		err = 0;
 		set_pte(pg, mk_pte_phys(pa & PAGE_MASK, __pgprot(flags)));
-		if (mem_init_done)
-			flush_hash_page(0, va);
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+		if (mem_init_done && Hash != 0)
+			flush_hash_page(0, va, pg);
+#endif /* !4xx && !8xx */
 	}
 	spin_unlock(&init_mm.page_table_lock);
 	return err;
 }
 
-#ifndef CONFIG_8xx
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 /*
  * TLB flushing:
  *
@@ -510,19 +472,14 @@
 void
 local_flush_tlb_all(void)
 {
-#ifdef CONFIG_PPC64BRIDGE
-	/* XXX this assumes that the vmalloc arena starts no lower than
-	 * 0xd0000000 on 64-bit machines. */
-	flush_hash_segments(0xd, 0xffffff);
-#else
-	/* this could cause problems on SMP with nobats  -- paulus */
-	/* XXX no hash_table_lock?  interesting  -- paulus */
-	__clear_user(Hash, Hash_size);
-	_tlbia();
+	/* aargh!!! */
+	/* just flush the kernel part of the address space, that's
+	   all that the current callers of this require.  -- paulus. */
+	local_flush_tlb_range(&init_mm, TASK_SIZE, ~0UL);
+
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif /* CONFIG_SMP */
-#endif /* CONFIG_PPC64BRIDGE */
 }
 
 /*
@@ -533,30 +490,18 @@
 void
 local_flush_tlb_mm(struct mm_struct *mm)
 {
-	if (mm->context == 0) {
-		/* don't try to reassign a new context to the kernel */
-		/*
-		 * This could cause problems on SMP if we aren't using
-		 * the BATs (e.g. on POWER4 or if the nobats option is used).
-		 * The problem scenario is that one cpu is doing
-		 * flush_hash_page or similar when another cpu clears
-		 * out the HPTEs which map the flush_hash_page text
-		 * and the hash table.  hash_page will then deadlock.
-		 * We need some way to have "protected" HPTEs or else
-		 * do all hash-table manipulation with the MMU off.
-		 *  -- paulus.
-		 */
-#ifdef CONFIG_PPC64BRIDGE
-		flush_hash_segments(0xd, 0xf);
-#else
-		flush_hash_segments(0xc, 0xf);
-#endif CONFIG_PPC64BRIDGE
+	if (Hash == 0) {
 		_tlbia();
 		return;
 	}
-	mm->context = NO_CONTEXT;
-	if (mm == current->mm)
-		activate_mm(mm, mm);
+
+	if (mm->map_count) {
+		struct vm_area_struct *mp;
+		for (mp = mm->mmap; mp != NULL; mp = mp->vm_next)
+			local_flush_tlb_range(mm, mp->vm_start, mp->vm_end);
+	} else
+		local_flush_tlb_range(mm, 0, TASK_SIZE);
+
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif	
@@ -565,10 +510,21 @@
 void
 local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
 {
-	if (vmaddr < TASK_SIZE)
-		flush_hash_page(vma->vm_mm->context, vmaddr);
-	else
-		flush_hash_page(0, vmaddr);
+	struct mm_struct *mm;
+	pmd_t *pmd;
+	pte_t *pte;
+
+	if (Hash == 0) {
+		_tlbie(vmaddr);
+		return;
+	}
+	mm = (vmaddr < TASK_SIZE)? vma->vm_mm: &init_mm;
+	pmd = pmd_offset(pgd_offset(mm, vmaddr), vmaddr);
+	if (!pmd_none(*pmd)) {
+		pte = pte_offset(pmd, vmaddr);
+		if (pte_val(*pte) & _PAGE_HASHPTE)
+			flush_hash_page(mm->context, vmaddr, pte);
+	}
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
 #endif	
@@ -576,28 +532,43 @@
 
 
 /*
- * for each page addr in the range, call MMU_invalidate_page()
- * if the range is very large and the hash table is small it might be
- * faster to do a search of the hash table and just invalidate pages
- * that are in the range but that's for study later.
- * -- Cort
+ * For each address in the range, find the pte for the address
+ * and check _PAGE_HASHPTE bit; if it is set, find and destroy
+ * the corresponding HPTE.
  */
 void
 local_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
 {
-	start &= PAGE_MASK;
+	pmd_t *pmd;
+	pte_t *pte;
+	unsigned long pmd_end;
+	unsigned int ctx = mm->context;
 
-	if (mm->context != 0) {
-		if (end > TASK_SIZE)
-			end = TASK_SIZE;
-		if (end - start > 20 * PAGE_SIZE) {
-			flush_tlb_mm(mm);
-			return;
-		}
+	if (Hash == 0) {
+		_tlbia();
+		return;
 	}
-
-	for (; start < end; start += PAGE_SIZE)
-		flush_hash_page(mm->context, start);
+	start &= PAGE_MASK;
+	if (start >= end)
+		return;
+	pmd = pmd_offset(pgd_offset(mm, start), start);
+	do {
+		pmd_end = (start + PGDIR_SIZE) & PGDIR_MASK;
+		if (!pmd_none(*pmd)) {
+			if (!pmd_end || pmd_end > end)
+				pmd_end = end;
+			pte = pte_offset(pmd, start);
+			do {
+				if ((pte_val(*pte) & _PAGE_HASHPTE) != 0)
+					flush_hash_page(ctx, start, pte);
+				start += PAGE_SIZE;
+				++pte;
+			} while (start && start < pmd_end);
+		} else {
+			start = pmd_end;
+		}
+		++pmd;
+	} while (start && start < end);
 
 #ifdef CONFIG_SMP
 	smp_send_tlb_invalidate(0);
@@ -605,59 +576,6 @@
 }
 
 /*
- * The context counter has overflowed.
- * We set mm->context to NO_CONTEXT for all mm's in the system.
- * We assume we can get to all mm's by looking as tsk->mm for
- * all tasks in the system.
- */
-void
-mmu_context_overflow(void)
-{
-	struct task_struct *tsk;
-
-	printk(KERN_DEBUG "mmu_context_overflow\n");
-	/* acquire the write lock for context overflow */
-	write_lock (&context_overflow_lock);
-	/* recheck if overflow still exists */
-	if (atomic_read(&next_mmu_context) == LAST_CONTEXT) {
-		read_lock(&tasklist_lock);
-		for_each_task(tsk) {
-			if (tsk->mm)
-				tsk->mm->context = NO_CONTEXT;
-		}
-		read_unlock(&tasklist_lock);
-		flush_hash_segments(0x10, 0xffffff);
-#ifdef CONFIG_SMP
-		smp_send_tlb_invalidate(0);
-#endif	
-		atomic_set(&next_mmu_context, 0);
-	}
-	write_unlock (&context_overflow_lock);
-	/* make sure current always has a context */
-	/* need to check to assure current task has an mm */
-	/*   - idle thread does not have an MM */
-	if (current->mm) {
-		current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
-		set_context(current->mm->context, current->mm->pgd);
-	}
-}
-#else /* CONFIG_8xx */
-void
-mmu_context_overflow(void)
-{
-	atomic_set(&next_mmu_context, -1);
-}
-#endif /* CONFIG_8xx */
-
-void flush_page_to_ram(struct page *page)
-{
-	unsigned long vaddr = (unsigned long) kmap(page);
-	__flush_page_to_ram(vaddr);
-	kunmap(page);
-}
-
-#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
-/*
  * Set up one of the I/D BAT (block address translation) register pairs.
  * The parameters are not checked; in particular size must be a power
  * of 2 between 128k and 256M.
@@ -717,8 +635,6 @@
 /*
  * Map in all of physical memory starting at KERNELBASE.
  */
-#define PAGE_KERNEL_RO	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-
 static void __init mapin_ram(void)
 {
 	unsigned long v, p, s, f;
@@ -768,10 +684,10 @@
 		f = _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_SHARED;
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON)
 		/* Allows stub to set breakpoints everywhere */
-		f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+		f |= _PAGE_RW | _PAGE_DIRTY;
 #else
 		if ((char *) v < _stext || (char *) v >= etext)
-			f |= _PAGE_RW | _PAGE_DIRTY | _PAGE_HWWRITE;
+			f |= _PAGE_RW | _PAGE_DIRTY;
 #ifndef CONFIG_8xx
 		else
 			/* On the powerpc (not 8xx), no user access
@@ -839,16 +755,59 @@
 #ifdef CONFIG_BLK_DEV_INITRD
 void free_initrd_mem(unsigned long start, unsigned long end)
 {
+	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+
 	for (; start < end; start += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(start));
 		set_page_count(virt_to_page(start), 1);
 		free_page(start);
 		totalram_pages++;
 	}
-	printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
 }
 #endif
 
+/*
+ * Initialize the context management stuff.
+ */
+static void mmu_context_init(void)
+{
+	context_map[0] = 1;	/* init_mm uses context 0 */
+	next_mmu_context = 1;
+#ifdef FEW_CONTEXTS
+	atomic_set(&nr_free_contexts, LAST_CONTEXT);
+	context_mm[0] = &init_mm;
+#endif /* FEW_CONTEXTS */
+}
+
+#ifdef FEW_CONTEXTS
+/*
+ * Steal a context from a task that has one at the moment.
+ * This is only used on 8xx and 4xx and we presently assume that
+ * they don't do SMP.  If they do then this will have to check
+ * whether the MM we steal is in use.
+ * We also assume that this is only used on systems that don't
+ * use an MMU hash table - this is true for 8xx and 4xx.
+ * This isn't an LRU system, it just frees up each context in
+ * turn (sort-of pseudo-random replacement :).  This would be the
+ * place to implement an LRU scheme if anyone was motivated to do it.
+ *  -- paulus
+ */
+void steal_context(void)
+{
+	struct mm_struct *mm;
+
+	/* free up context `next_mmu_context' */
+	/* if we shouldn't free context 0, don't... */
+#ifdef CONFIG_4xx
+	if (next_mmu_context == 0)
+		next_mmu_context = 1;
+#endif /* CONFIG_4xx */
+	mm = context_mm[next_mmu_context];
+	flush_tlb_mm(mm);
+	destroy_context(mm);
+}
+#endif /* FEW_CONTEXTS */
+
 extern boot_infos_t *disp_bi;
 
 /*
@@ -903,6 +862,8 @@
 
         mtspr(SPRN_DCCR, 0x80000000);	/* 128 MB of data space at 0x0. */
         mtspr(SPRN_ICCR, 0x80000000);	/* 128 MB of instr. space at 0x0. */
+
+	mmu_context_init();
 }
 
 #else /* !CONFIG_4xx */
@@ -938,11 +899,7 @@
 	/* Map in all of RAM starting at KERNELBASE */
 	mapin_ram();
 
-#if defined(CONFIG_POWER4)
-	ioremap_base = ioremap_bot = 0xfffff000;
-	isa_io_base = (unsigned long) ioremap(0xffd00000, 0x200000) + 0x100000;
-
-#elif defined(CONFIG_8xx)
+#if defined(CONFIG_8xx)
         /* Now map in some of the I/O space that is generically needed
          * or shared with multiple devices.
          * All of this fits into the same 4Mbyte region, so it only
@@ -974,7 +931,7 @@
 #ifdef CONFIG_PCI
         ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
 #endif
-#else /* !CONFIG_POWER4 && !CONFIG_8xx */
+#else /* !CONFIG_8xx */
 	/*
 	 * Setup the bat mappings we're going to load that cover
 	 * the io areas.  RAM was mapped by mapin_ram().
@@ -1024,7 +981,7 @@
 		break;
 	}
 	ioremap_bot = ioremap_base;
-#endif /* CONFIG_POWER4 || CONFIG_8xx */
+#endif /* CONFIG_8xx */
 
 	if ( ppc_md.progress ) ppc_md.progress("MMU:exit", 0x211);
 #ifdef CONFIG_BOOTX_TEXT
@@ -1032,6 +989,8 @@
 	if (_machine == _MACH_Pmac || _machine == _MACH_chrp)
 		map_bootx_text();
 #endif
+
+	mmu_context_init();
 }
 #endif /* CONFIG_4xx */
 
@@ -1095,12 +1054,6 @@
 #endif /* CONFIG_HIGHMEM */
 
 	/*
-	 * Grab some memory for bad_page and bad_pagetable to use.
-	 */
-	empty_bad_page = alloc_bootmem_pages(PAGE_SIZE);
-	empty_bad_page_table = alloc_bootmem_pages(PAGE_SIZE);
-
-	/*
 	 * All pages are DMA-able so we put them all in the DMA zone.
 	 */
 	zones_size[ZONE_DMA] = total_lowmem >> PAGE_SHIFT;
@@ -1128,7 +1081,6 @@
 	highmem_mapnr = total_lowmem >> PAGE_SHIFT;
 	highmem_start_page = mem_map + highmem_mapnr;
 	max_mapnr = total_memory >> PAGE_SHIFT;
-	totalram_pages += max_mapnr - highmem_mapnr;
 #else
 	max_mapnr = max_low_pfn;
 #endif /* CONFIG_HIGHMEM */
@@ -1201,15 +1153,17 @@
 
 #if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
 /*
- * Initialize the hash table and patch the instructions in head.S.
+ * Initialize the hash table and patch the instructions in hashtable.S.
  */
 static void __init hash_init(void)
 {
 	int Hash_bits, mb, mb2;
 	unsigned int hmask, h;
 
-	extern unsigned int hash_page_patch_A[], hash_page_patch_B[],
-		hash_page_patch_C[], hash_page[];
+	extern unsigned int hash_page_patch_A[];
+	extern unsigned int hash_page_patch_B[], hash_page_patch_C[];
+	extern unsigned int hash_page[];
+	extern unsigned int flush_hash_patch_A[], flush_hash_patch_B[];
 
 #ifdef CONFIG_PPC64BRIDGE
 	/* The hash table has already been allocated and initialized
@@ -1259,6 +1213,7 @@
 	if ( Hash_size ) {
 		Hash = mem_pieces_find(Hash_size, Hash_size);
 		cacheable_memzero(Hash, Hash_size);
+		_SDR1 = __pa(Hash) | (Hash_mask >> 10);
 	} else
 		Hash = 0;
 #endif /* CONFIG_PPC64BRIDGE */
@@ -1271,10 +1226,10 @@
 		Hash_end = (PTE *) ((unsigned long)Hash + Hash_size);
 
 		/*
-		 * Patch up the instructions in head.S:hash_page
+		 * Patch up the instructions in hashtable.S:create_hpte
 		 */
 		hash_page_patch_A[0] = (hash_page_patch_A[0] & ~0xffff)
-			| (__pa(Hash) >> 16);
+			| ((unsigned int)(Hash) >> 16);
 		hash_page_patch_A[1] = (hash_page_patch_A[1] & ~0x7c0)
 			| (mb << 6);
 		hash_page_patch_A[2] = (hash_page_patch_A[2] & ~0x7c0)
@@ -1283,10 +1238,6 @@
 			| hmask;
 		hash_page_patch_C[0] = (hash_page_patch_C[0] & ~0xffff)
 			| hmask;
-#if 0	/* see hash_page in head.S, note also patch_C ref below */
-		hash_page_patch_D[0] = (hash_page_patch_D[0] & ~0xffff)
-			| hmask;
-#endif
 		/*
 		 * Ensure that the locations we've patched have been written
 		 * out from the data cache and invalidated in the instruction
@@ -1294,6 +1245,19 @@
 		 */
 		flush_icache_range((unsigned long) &hash_page_patch_A[0],
 				   (unsigned long) &hash_page_patch_C[1]);
+		/*
+		 * Patch up the instructions in hashtable.S:flush_hash_page
+		 */
+		flush_hash_patch_A[0] = (flush_hash_patch_A[0] & ~0xffff)
+			| ((unsigned int)(Hash) >> 16);
+		flush_hash_patch_A[1] = (flush_hash_patch_A[1] & ~0x7c0)
+			| (mb << 6);
+		flush_hash_patch_A[2] = (flush_hash_patch_A[2] & ~0x7c0)
+			| (mb2 << 6);
+		flush_hash_patch_B[0] = (flush_hash_patch_B[0] & ~0xffff)
+			| hmask;
+		flush_icache_range((unsigned long) &flush_hash_patch_A[0],
+				   (unsigned long) &flush_hash_patch_B[1]);
 	}
 	else {
 		Hash_end = 0;
@@ -1306,6 +1270,7 @@
 		flush_icache_range((unsigned long) &hash_page[0],
 				   (unsigned long) &hash_page[1]);
 	}
+
 	if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205);
 }
 #endif /* !CONFIG_4xx && !CONFIG_8xx */
@@ -1320,7 +1285,7 @@
 	unsigned long kstart, ksize;
 
 	/*
-	 * Initially, available phyiscal memory is equivalent to all
+	 * Initially, available physical memory is equivalent to all
 	 * physical memory.
 	 */
 
@@ -1356,4 +1321,51 @@
 	if (Hash)
 		mem_pieces_remove(&phys_avail, __pa(Hash), Hash_size, 1);
 #endif /* CONFIG_PPC64BRIDGE */
+}
+
+void flush_page_to_ram(struct page *page)
+{
+	unsigned long vaddr = (unsigned long) kmap(page);
+	__flush_page_to_ram(vaddr);
+	kunmap(page);
+}
+
+#if !defined(CONFIG_4xx) && !defined(CONFIG_8xx)
+/*
+ * This is called at the end of handling a user page fault, when the
+ * fault has been handled by updating a PTE in the linux page tables.
+ * We use it to preload an HPTE into the hash table corresponding to
+ * the updated linux PTE.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
+		      pte_t pte)
+{
+	struct mm_struct *mm;
+	pmd_t *pmd;
+	pte_t *ptep;
+	static int nopreload;
+
+	if (Hash == 0 || nopreload)
+		return;
+	mm = (address < TASK_SIZE)? vma->vm_mm: &init_mm;
+	pmd = pmd_offset(pgd_offset(mm, address), address);
+	if (!pmd_none(*pmd)) {
+		ptep = pte_offset(pmd, address);
+		add_hash_page(mm->context, address, ptep);
+	}
+}
+#endif /* !4xx && !8xx */
+
+/*
+ * set_pte stores a linux PTE into the linux page table.
+ * On machines which use an MMU hash table we avoid changing the
+ * _PAGE_HASHPTE bit.
+ */
+void set_pte(pte_t *ptep, pte_t pte)
+{
+#if _PAGE_HASHPTE != 0
+	pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte) & ~_PAGE_HASHPTE);
+#else
+	*ptep = pte;
+#endif
 }
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/vmlinux.lds linux/arch/ppc/vmlinux.lds
--- v2.4.5/linux/arch/ppc/vmlinux.lds	Fri Aug  4 11:23:37 2000
+++ linux/arch/ppc/vmlinux.lds	Mon Jul  2 14:40:58 2001
@@ -39,6 +39,7 @@
   .rodata    :
   {
     *(.rodata)
+    *(.rodata.*)
     *(.rodata1)
   }
   .kstrtab   : { *(.kstrtab) }
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/xmon/Makefile linux/arch/ppc/xmon/Makefile
--- v2.4.5/linux/arch/ppc/xmon/Makefile	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/xmon/Makefile	Mon Jul  2 14:34:57 2001
@@ -1,13 +1,14 @@
-# BK Id: SCCS/s.Makefile 1.3 05/17/01 18:14:23 cort
+# BK Id: SCCS/s.Makefile 1.6 06/27/01 14:49:58 trini
 #
 # Makefile for xmon
 
 O_TARGET	:= x.o
 
-ifeq ($(CONFIG_8xx),y)
-obj-y		:= start_8xx.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+ifdef CONFIG_8xx
+obj-y		:= start_8xx.o
 else
-obj-y		:= start.o xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
+obj-y		:= start.o
 endif
+obj-y		+= xmon.o ppc-dis.o ppc-opc.o subr_prf.o setjmp.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/xmon/xmon.c linux/arch/ppc/xmon/xmon.c
--- v2.4.5/linux/arch/ppc/xmon/xmon.c	Mon May 21 17:04:47 2001
+++ linux/arch/ppc/xmon/xmon.c	Mon Jul  2 14:34:57 2001
@@ -1,5 +1,5 @@
 /*
- * BK Id: SCCS/s.xmon.c 1.9 05/17/01 18:14:24 cort
+ * BK Id: SCCS/s.xmon.c 1.14 06/28/01 15:50:17 paulus
  */
 /*
  * Routines providing a simple monitor for use on the PowerMac.
@@ -661,8 +661,7 @@
 	unsigned stack[2];
 	struct pt_regs regs;
 	extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
-	extern char do_bottom_half_ret, do_signal_ret;
-	extern char ret_from_except;
+	extern char do_signal_ret, ret_from_except;
 
 	printf("backtrace:\n");
 	
@@ -680,7 +679,6 @@
 		    || stack[1] == (unsigned) &ret_from_except
 		    || stack[1] == (unsigned) &ret_from_syscall_1
 		    || stack[1] == (unsigned) &ret_from_syscall_2
-		    || stack[1] == (unsigned) &do_bottom_half_ret
 		    || stack[1] == (unsigned) &do_signal_ret) {
 			if (mread(sp+16, &regs, sizeof(regs)) != sizeof(regs))
 				break;
@@ -1019,7 +1017,8 @@
 		seg_end = (seg << 28) | 0x0ffff000;
 		if (seg_end > hash_end)
 			seg_end = hash_end;
-		dump_hash_table_seg((hash_ctx << 4) + seg, seg_start, seg_end);
+		dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
+				    seg_start, seg_end);
 		seg_start = seg_end + 0x1000;
 	}
 }
diff -u --recursive --new-file v2.4.5/linux/arch/s390/vmlinux.lds linux/arch/s390/vmlinux.lds
--- v2.4.5/linux/arch/s390/vmlinux.lds	Tue Feb 13 14:13:44 2001
+++ linux/arch/s390/vmlinux.lds	Mon Jul  2 14:40:58 2001
@@ -14,7 +14,7 @@
 	*(.gnu.warning)
 	} = 0x0700
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/s390x/vmlinux.lds linux/arch/s390x/vmlinux.lds
--- v2.4.5/linux/arch/s390x/vmlinux.lds	Wed Apr 11 19:02:29 2001
+++ linux/arch/s390x/vmlinux.lds	Mon Jul  2 14:40:58 2001
@@ -14,7 +14,7 @@
 	*(.gnu.warning)
 	} = 0x0700
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/sh/config.in linux/arch/sh/config.in
--- v2.4.5/linux/arch/sh/config.in	Tue Apr 17 17:19:25 2001
+++ linux/arch/sh/config.in	Wed Jun 27 13:55:29 2001
@@ -29,7 +29,9 @@
 choice 'SuperH system type'					\
 	"Generic		CONFIG_SH_GENERIC		\
 	 SolutionEngine		CONFIG_SH_SOLUTION_ENGINE	\
-	 Overdrive		CONFIG_SH_OVERDRIVE		\
+	 SolutionEngine7751	CONFIG_SH_7751_SOLUTION_ENGINE	\
+	 STB1_Harp		CONFIG_SH_STB1_HARP		\
+	 STB1_Overdrive		CONFIG_SH_STB1_OVERDRIVE	\
 	 HP620			CONFIG_SH_HP620			\
 	 HP680			CONFIG_SH_HP680			\
 	 HP690			CONFIG_SH_HP690			\
@@ -37,9 +39,17 @@
 	 DMIDA			CONFIG_SH_DMIDA    		\
 	 EC3104			CONFIG_SH_EC3104		\
 	 Dreamcast		CONFIG_SH_DREAMCAST		\
+	 CAT68701		CONFIG_SH_CAT68701		\
+	 BigSur			CONFIG_SH_BIGSUR		\
+	 SH2000			CONFIG_SH_SH2000		\
 	 BareCPU		CONFIG_SH_UNKNOWN" Generic
 
-define_bool CONFIG_SH_RTC y
+# The SH7750 RTC module is disabled in the Dreamcast
+if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
+   define_bool CONFIG_SH_RTC n
+else
+   define_bool CONFIG_SH_RTC y
+fi
 
 if [ "$CONFIG_SH_HP620" = "y" -o "$CONFIG_SH_HP680" = "y" -o \
      "$CONFIG_SH_HP690" = "y" ]; then
@@ -50,7 +60,9 @@
    "SH7707 CONFIG_CPU_SUBTYPE_SH7707 \
     SH7708 CONFIG_CPU_SUBTYPE_SH7708 \
     SH7709 CONFIG_CPU_SUBTYPE_SH7709 \
-    SH7750 CONFIG_CPU_SUBTYPE_SH7750" SH7708
+    SH7750 CONFIG_CPU_SUBTYPE_SH7750 \
+    SH7751 CONFIG_CPU_SUBTYPE_SH7751 \
+    ST40STB1 CONFIG_CPU_SUBTYPE_ST40STB1" SH7708
 if [ "$CONFIG_CPU_SUBTYPE_SH7707" = "y" ]; then
    define_bool CONFIG_CPU_SH3 y
    define_bool CONFIG_CPU_SH4 n
@@ -67,12 +79,30 @@
    define_bool CONFIG_CPU_SH3 n
    define_bool CONFIG_CPU_SH4 y
 fi
+if [ "$CONFIG_CPU_SUBTYPE_SH7751" = "y" ]; then
+   define_bool CONFIG_CPU_SH3 n
+   define_bool CONFIG_CPU_SH4 y
+fi
+if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then
+   define_bool CONFIG_CPU_SH3 n
+   define_bool CONFIG_CPU_SH4 y
+fi
 bool 'Little Endian' CONFIG_CPU_LITTLE_ENDIAN
 if [ "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_HP600" = "y" -o \
-     "$CONFIG_SH_OVERDRIVE" = "y" ]; then
+     "$CONFIG_SH_BIGSUR" = "y" -o "$CONFIG_SH_7751_SOLUTION_ENGINE" = "y" -o \
+     "$CONFIG_SH_DREAMCAST" = "y" -o "$CONFIG_SH_SH2000" = "y" ]; then
   define_hex CONFIG_MEMORY_START 0c000000
 else
-  hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
+  if [ "$CONFIG_CPU_SUBTYPE_ST40STB1" = "y" ]; then
+    bool 'Memory on LMI' CONFIG_ST40_LMI_MEMORY
+    if [ "$CONFIG_ST40_LMI_MEMORY" = "y" ] ; then
+      define_hex CONFIG_MEMORY_START 08000000
+    else
+      hex 'EMI physical memory start address' CONFIG_MEMORY_START 08000000
+    fi
+  else
+    hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
+  fi
 fi
 endmenu
 
@@ -89,7 +119,8 @@
 
 bool 'Networking support' CONFIG_NET
 
-if [ "$CONFIG_SH_GENERIC" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o "$CONFIG_SH_UNKNOWN" = "y" ]; then
+if [ "$CONFIG_SH_GENERIC" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" -o \
+     "$CONFIG_SH_UNKNOWN" = "y" -o "$CONFIG_SH_CAT68701" = "y" ]; then
   bool 'Compact Flash Enabler support' CONFIG_CF_ENABLER
 fi
 
@@ -101,6 +132,7 @@
 
 bool 'Hitachi HD64465 companion chip support' CONFIG_HD64465
 if [ "$CONFIG_HD64465" = "y" ]; then
+   hex 'HD64465 start address' CONFIG_HD64465_IOBASE b0000000
    int 'HD64465 IRQ' CONFIG_HD64465_IRQ 5
 fi
 
@@ -197,6 +229,10 @@
 #
 source drivers/input/Config.in
 
+if [ "$CONFIG_SH_DREAMCAST" = "y" ]; then
+source drivers/maple/Config.in
+fi
+
 mainmenu_option next_comment
 comment 'Character devices'
 
@@ -217,10 +253,29 @@
 fi
 
 if [ "$CONFIG_SH_GENERIC" = "y" -o \
-     "$CONFIG_SH_OVERDRIVE" = "y" -o "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
+     "$CONFIG_SH_CAT68701" = "y" -o \
+     "$CONFIG_SH_STB1_HARP" = "y" -o \
+     "$CONFIG_SH_STB1_OVERDRIVE" = "y" -o \
+     "$CONFIG_SH_BIGSUR" = "y" -o \
+     "$CONFIG_SH_7751_SOLUTION_ENGINE" = "y" -o \
+     "$CONFIG_SH_SOLUTION_ENGINE" = "y" ]; then
   bool 'Heartbeat LED' CONFIG_HEARTBEAT
 fi
 
+if [ "$CONFIG_SH_DREAMCAST" = "y" -a "$CONFIG_MAPLE" != "n" ]; then
+   mainmenu_option next_comment
+   comment 'Maple Bus input peripherals'
+   if [ "$CONFIG_INPUT" != "n" ]; then
+      dep_tristate '  Maple Bus keyboard support' CONFIG_MAPLE_KEYBOARD $CONFIG_INPUT
+      dep_tristate '  Maple Bus mouse support' CONFIG_MAPLE_MOUSE $CONFIG_INPUT
+   else
+      comment 'Input core support is required for Maple input peripherals'
+   fi
+   endmenu
+fi
+
+source drivers/char/joystick/Config.in
+
 if [ "$CONFIG_PARPORT" != "n" ]; then
    dep_tristate 'Parallel printer support' CONFIG_PRINTER $CONFIG_PARPORT
    if [ "$CONFIG_PRINTER" != "n" ]; then
@@ -228,13 +283,16 @@
    fi
    dep_tristate 'Support for user-space parallel port device drivers' CONFIG_PPDEV $CONFIG_PARPORT
 fi
-endmenu
-
+bool 'PS/2 mouse (aka "auxiliary device") support' CONFIG_PSMOUSE
+tristate 'Enhanced Real Time Clock Support' CONFIG_RTC
 if [ "$CONFIG_HOTPLUG" = "y" -a "$CONFIG_PCMCIA" != "n" ]; then
    source drivers/char/pcmcia/Config.in
 fi
+endmenu
 
 source fs/Config.in
+
+source drivers/media/Config.in
 
 if [ "$CONFIG_VT" = "y" ]; then
    mainmenu_option next_comment
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/Makefile linux/arch/sh/kernel/Makefile
--- v2.4.5/linux/arch/sh/kernel/Makefile	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/Makefile	Wed Jun 27 13:55:29 2001
@@ -24,8 +24,15 @@
 obj-$(CONFIG_SH_STANDARD_BIOS)	+= sh_bios.o
 
 ifeq ($(CONFIG_PCI),y)
-obj-y				+= pci-sh.o 
+ifeq ($(CONFIG_SH_DREAMCAST),y)
+obj-y 				+= pci-dc.o
+else
+obj-y                           += pci-dma.o 
 obj-$(CONFIG_CPU_SUBTYPE_ST40STB1)+= pci_st40.o
+obj-$(CONFIG_CPU_SUBTYPE_SH7751)+= pci-sh7751.o 
+obj-$(CONFIG_SH_BIGSUR)+= pci-bigsur.o
+obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= pci-7751se.o
+endif
 endif
 
 obj-$(CONFIG_SH_HP600)		+= mach_hp600.o
@@ -33,6 +40,15 @@
 
 obj-$(CONFIG_SH_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o
 machine-specific-objs		+= mach_se.o setup_se.o io_se.o led_se.o
+
+obj-$(CONFIG_SH_7751_SOLUTION_ENGINE)+= mach_se.o setup_se.o io_se.o led_se.o pci-7751se.o
+machine-specific-objs           += mach_se.o setup_se.o io_se.o led_se.o pci-7751se.o
+
+obj-$(CONFIG_SH_BIGSUR)		+= mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o
+machine-specific-objs		+= mach_bigsur.o setup_bigsur.o io_bigsur.o led_bigsur.o
+
+obj-$(CONFIG_SH_SH2000)		+= setup_sh2000.o io_sh2000.o
+machine-specific-objs		+= setup_sh2000.o io_sh2000.o
 
 obj-$(CONFIG_SH_CAT68701) 	+= mach_cat68701.o io_cat68701.o
 machine-specific-objs		+= mach_cat68701.o io_cat68701.o
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
--- v2.4.5/linux/arch/sh/kernel/entry.S	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/entry.S	Wed Jun 27 13:55:29 2001
@@ -489,8 +489,9 @@
 __syscall_ret_trace:
 	.long	syscall_ret_trace
 __syscall_ret:
-	.long	SYMBOL_NAME(syscall_ret)
-
+	.long	syscall_ret
+__INV_IMASK:
+	.long	0xffffff0f	! ~(IMASK)
 
 
 	.align	2
@@ -502,30 +503,16 @@
 	.align	2
 1:	.long	SYMBOL_NAME(schedule)
 
-ENTRY(ret_from_irq)
-	mov	#OFF_SR, r0
-	mov.l	@(r0,r15), r0	! get status register
-	shll	r0
-	shll	r0		! kernel space?
-	bt	restore_all	! Yes, it's from kernel, go back soon
-	!
-	STI()
-	bra	ret_with_reschedule
-	 nop
-
-ENTRY(ret_from_exception)
+ret_from_irq:
+ret_from_exception:
 	mov	#OFF_SR, r0
 	mov.l	@(r0,r15), r0	! get status register
 	shll	r0
 	shll	r0		! kernel space?
 	bt	restore_all	! Yes, it's from kernel, go back soon
 	!
-	STI()
 	bra	ret_from_syscall
 	 nop
-	.align	2
-__INV_IMASK:
-	.long	0xffffff0f	! ~(IMASK)
 
 	.align 2
 #ifdef COMPAT_OLD_SYSCALL_ABI
@@ -538,16 +525,11 @@
 	/* fall through */
 
 ENTRY(ret_from_syscall)
-	mov.l	__irq_stat, r0	! softirq_active
-	mov.l	@r0, r1
-	mov.l	@(4,r0), r2	! softirq_mask
-	tst	r2, r1
-	bt	ret_with_reschedule
-handle_softirq:
-	mov.l	__do_softirq, r0
-	jsr	@r0
-	 nop
-ret_with_reschedule:
+	/* CLI */
+	stc	sr, r0
+	or	#0xf0, r0
+	ldc	r0, sr
+	!
 	stc	k_current, r1
 	mov.l	@(need_resched,r1), r0
 	tst	r0, r0
@@ -567,8 +549,6 @@
 	.long	SYMBOL_NAME(do_signal)
 __irq_stat:
 	.long	SYMBOL_NAME(irq_stat)
-__do_softirq:
-	.long	SYMBOL_NAME(do_softirq)
 
 	.align 2
 restore_all:
@@ -707,7 +687,7 @@
 	bra	handle_exception
 	 mov.l	@k2, k2
 	.align	2
-2:	.long	SYMBOL_NAME(ret_from_exception)
+2:	.long	ret_from_exception
 1:	.long	EXPEVT
 !
 !
@@ -728,8 +708,8 @@
 	.align	2
 1:	.long	EXPEVT
 2:	.long	INTEVT
-3:	.long	SYMBOL_NAME(ret_from_irq)
-4:	.long	SYMBOL_NAME(ret_from_exception)
+3:	.long	ret_from_irq
+4:	.long	ret_from_exception
 
 !
 !
@@ -941,24 +921,143 @@
 	.long   SYMBOL_NAME(do_IRQ)	! 63      pcc1i
 #endif
 #elif defined(__SH4__)
-	.long	SYMBOL_NAME(do_IRQ)	! Hitachi UDI
-	.long	SYMBOL_NAME(do_IRQ)	! GPIO
-	.long	SYMBOL_NAME(do_IRQ)	! DMAC dmte0
-	.long	SYMBOL_NAME(do_IRQ)	!      dmte1
-	.long	SYMBOL_NAME(do_IRQ)	!      dmte2
-	.long	SYMBOL_NAME(do_IRQ)	!      dmte3
-	.long	SYMBOL_NAME(do_IRQ)	!      dmae
-	.long	SYMBOL_NAME(do_IRQ)
-	.long	SYMBOL_NAME(do_IRQ)	! SCIF eri
-	.long	SYMBOL_NAME(do_IRQ)	!      rxi
-	.long	SYMBOL_NAME(do_IRQ)	!      bri
-	.long	SYMBOL_NAME(do_IRQ)	!      txi
+	.long	SYMBOL_NAME(do_IRQ)	! 32 Hitachi UDI
+	.long	SYMBOL_NAME(do_IRQ)	! 33 GPIO
+	.long	SYMBOL_NAME(do_IRQ)	! 34 DMAC dmte0
+	.long	SYMBOL_NAME(do_IRQ)	! 35      dmte1
+	.long	SYMBOL_NAME(do_IRQ)	! 36      dmte2
+	.long	SYMBOL_NAME(do_IRQ)	! 37      dmte3
+	.long	SYMBOL_NAME(do_IRQ)	! 38      dmae
+	.long	error			! 39
+	.long	SYMBOL_NAME(do_IRQ)	! 40 SCIF eri
+	.long	SYMBOL_NAME(do_IRQ)	! 41      rxi
+	.long	SYMBOL_NAME(do_IRQ)	! 42      bri
+	.long	SYMBOL_NAME(do_IRQ)	! 43      txi
+	.long	error			! 44
+	.long	error			! 45
+	.long	error			! 46
+	.long	error			! 47
+	.long	SYMBOL_NAME(do_fpu_state_restore)	! 48
+	.long	SYMBOL_NAME(do_fpu_state_restore)	! 49
+#endif
+#if defined(CONFIG_CPU_SUBTYPE_SH7751)
+	.long	error
+	.long	error
+	.long	error
+	.long	error
+	.long	error
+	.long	error
+	.long	error
+	.long	error
+	.long	error
+	.long	error
 	.long	error
 	.long	error
 	.long	error
 	.long	error
-	.long	SYMBOL_NAME(do_fpu_state_restore)
-	.long	SYMBOL_NAME(do_fpu_state_restore)
+	.long	SYMBOL_NAME(do_IRQ)	! PCI serr
+	.long	SYMBOL_NAME(do_IRQ)	!     dma3
+	.long	SYMBOL_NAME(do_IRQ)	!     dma2
+	.long	SYMBOL_NAME(do_IRQ)	!     dma1
+	.long	SYMBOL_NAME(do_IRQ)	!     dma0
+	.long	SYMBOL_NAME(do_IRQ)	!     pwon
+	.long	SYMBOL_NAME(do_IRQ)	!     pwdwn
+	.long	SYMBOL_NAME(do_IRQ)	!     err
+#elif defined(CONFIG_CPU_SUBTYPE_ST40STB1)
+	.long	error			!  50 0x840
+	.long	error			!  51 0x860
+	.long	error			!  52 0x880
+	.long	error			!  53 0x8a0
+	.long	error			!  54 0x8c0
+	.long	error			!  55 0x8e0
+	.long	error			!  56 0x900
+	.long	error			!  57 0x920
+	.long	error			!  58 0x940
+	.long	error			!  59 0x960
+	.long	error			!  60 0x980
+	.long	error			!  61 0x9a0
+	.long	error			!  62 0x9c0
+	.long	error			!  63 0x9e0
+	.long	SYMBOL_NAME(do_IRQ)	!  64 0xa00 PCI serr
+	.long	SYMBOL_NAME(do_IRQ)	!  65 0xa20     err
+	.long	SYMBOL_NAME(do_IRQ)	!  66 0xa40     ad
+	.long	SYMBOL_NAME(do_IRQ)	!  67 0xa60     pwr_dwn
+	.long	error			!  68 0xa80
+	.long	error			!  69 0xaa0
+	.long	error			!  70 0xac0
+	.long	error			!  71 0xae0
+	.long	SYMBOL_NAME(do_IRQ)	!  72 0xb00 DMA INT0
+	.long	SYMBOL_NAME(do_IRQ)	!  73 0xb20     INT1
+	.long	SYMBOL_NAME(do_IRQ)	!  74 0xb40     INT2
+	.long	SYMBOL_NAME(do_IRQ)	!  75 0xb60     INT3
+	.long	SYMBOL_NAME(do_IRQ)	!  76 0xb80     INT4
+	.long	error			!  77 0xba0
+	.long	SYMBOL_NAME(do_IRQ)	!  78 0xbc0 DMA ERR
+	.long	error			!  79 0xbe0
+	.long	SYMBOL_NAME(do_IRQ)	!  80 0xc00 PIO0
+	.long	SYMBOL_NAME(do_IRQ)	!  81 0xc20 PIO1
+	.long	SYMBOL_NAME(do_IRQ)	!  82 0xc40 PIO2
+	.long	error			!  83 0xc60
+	.long	error			!  84 0xc80
+	.long	error			!  85 0xca0
+	.long	error			!  86 0xcc0
+	.long	error			!  87 0xce0
+	.long	error			!  88 0xd00
+	.long	error			!  89 0xd20
+	.long	error			!  90 0xd40
+	.long	error			!  91 0xd60
+	.long	error			!  92 0xd80
+	.long	error			!  93 0xda0
+	.long	error			!  94 0xdc0
+	.long	error			!  95 0xde0
+	.long	error			!  96 0xe00
+	.long	error			!  97 0xe20
+	.long	error			!  98 0xe40
+	.long	error			!  99 0xe60
+	.long	error			! 100 0xe80
+	.long	error			! 101 0xea0
+	.long	error			! 102 0xec0
+	.long	error			! 103 0xee0
+	.long	error			! 104 0xf00
+	.long	error			! 105 0xf20
+	.long	error			! 106 0xf40
+	.long	error			! 107 0xf60
+	.long	error			! 108 0xf80
+	.long	error			! 109 0xfa0
+	.long	error			! 110 0xfc0
+	.long	error			! 111 0xfe0
+	.long	SYMBOL_NAME(do_IRQ)	! 112 0x1000 Mailbox
+	.long	error			! 113 0x1020
+	.long	error			! 114 0x1040
+	.long	error			! 115 0x1060
+	.long	error			! 116 0x1080
+	.long	error			! 117 0x10a0
+	.long	error			! 118 0x10c0
+	.long	error			! 119 0x10e0
+	.long	error			! 120 0x1100
+	.long	error			! 121 0x1120
+	.long	error			! 122 0x1140
+	.long	error			! 123 0x1160
+	.long	error			! 124 0x1180
+	.long	error			! 125 0x11a0
+	.long	error			! 126 0x11c0
+	.long	error			! 127 0x11e0
+	.long	error			! 128 0x1200
+	.long	error			! 129 0x1220
+	.long	error			! 130 0x1240
+	.long	error			! 131 0x1260
+	.long	error			! 132 0x1280
+	.long	error			! 133 0x12a0
+	.long	error			! 134 0x12c0
+	.long	error			! 135 0x12e0
+	.long	error			! 136 0x1300
+	.long	error			! 137 0x1320
+	.long	error			! 138 0x1340
+	.long	error			! 139 0x1360
+	.long	SYMBOL_NAME(do_IRQ)	! 140 0x1380 EMPI INV_ADDR
+	.long	error			! 141 0x13a0
+	.long	error			! 142 0x13c0
+	.long	error			! 143 0x13e0
 #endif
 
 ENTRY(sys_call_table)
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/hd64465_gpio.c linux/arch/sh/kernel/hd64465_gpio.c
--- v2.4.5/linux/arch/sh/kernel/hd64465_gpio.c	Sun May 20 12:11:38 2001
+++ linux/arch/sh/kernel/hd64465_gpio.c	Wed Jun 27 13:55:29 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: hd64465_gpio.c,v 1.1 2001/01/02 15:35:22 mjd Exp $
+ * $Id: hd64465_gpio.c,v 1.2 2001/05/24 00:13:47 gniibe Exp $
  * by Greg Banks <gbanks@pocketpenguins.com>
  * (c) 2000 PocketPenguins Inc
  *
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_bigsur.c linux/arch/sh/kernel/io_bigsur.c
--- v2.4.5/linux/arch/sh/kernel/io_bigsur.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/io_bigsur.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,249 @@
+/*
+ * include/asm-sh/io_bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from io_hd64465.h, which bore the message:
+ * By Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc. 
+ * and from io_hd64461.h, which bore the message:
+ * Copyright 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * IO functions for a Hitachi Big Sur Evaluation Board.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/bigsur.h>
+
+//#define BIGSUR_DEBUG 2
+#undef BIGSUR_DEBUG
+
+#ifdef BIGSUR_DEBUG
+#define DPRINTK(args...)	printk(args)
+#define DIPRINTK(n, args...)	if (BIGSUR_DEBUG>(n)) printk(args)
+#else
+#define DPRINTK(args...)
+#define DIPRINTK(n, args...)
+#endif
+
+
+/* Low iomap maps port 0-1K to addresses in 8byte chunks */
+#define BIGSUR_IOMAP_LO_THRESH 0x400
+#define BIGSUR_IOMAP_LO_SHIFT	3
+#define BIGSUR_IOMAP_LO_MASK	((1<<BIGSUR_IOMAP_LO_SHIFT)-1)
+#define BIGSUR_IOMAP_LO_NMAP	(BIGSUR_IOMAP_LO_THRESH>>BIGSUR_IOMAP_LO_SHIFT)
+static u32 bigsur_iomap_lo[BIGSUR_IOMAP_LO_NMAP];
+static u8 bigsur_iomap_lo_shift[BIGSUR_IOMAP_LO_NMAP];
+
+/* High iomap maps port 1K-64K to addresses in 1K chunks */
+#define BIGSUR_IOMAP_HI_THRESH 0x10000
+#define BIGSUR_IOMAP_HI_SHIFT	10
+#define BIGSUR_IOMAP_HI_MASK	((1<<BIGSUR_IOMAP_HI_SHIFT)-1)
+#define BIGSUR_IOMAP_HI_NMAP	(BIGSUR_IOMAP_HI_THRESH>>BIGSUR_IOMAP_HI_SHIFT)
+static u32 bigsur_iomap_hi[BIGSUR_IOMAP_HI_NMAP];
+static u8 bigsur_iomap_hi_shift[BIGSUR_IOMAP_HI_NMAP];
+
+#ifndef MAX
+#define MAX(a,b)    ((a)>(b)?(a):(b))
+#endif
+
+#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+
+void bigsur_port_map(u32 baseport, u32 nports, u32 addr, u8 shift)
+{
+    u32 port, endport = baseport + nports;
+
+    DPRINTK("bigsur_port_map(base=0x%0x, n=0x%0x, addr=0x%08x)\n",
+	    baseport, nports, addr);
+	    
+	for (port = baseport ;
+	     port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
+	     port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
+	    	DPRINTK("    maplo[0x%x] = 0x%08x\n", port, addr);
+    	    bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = addr;
+    	    bigsur_iomap_lo_shift[port>>BIGSUR_IOMAP_LO_SHIFT] = shift;
+	    	addr += (1<<(BIGSUR_IOMAP_LO_SHIFT));
+	}
+
+	for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+	     port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
+	     port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
+	    	DPRINTK("    maphi[0x%x] = 0x%08x\n", port, addr);
+    	    bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = addr;
+    	    bigsur_iomap_hi_shift[port>>BIGSUR_IOMAP_HI_SHIFT] = shift;
+	    	addr += (1<<(BIGSUR_IOMAP_HI_SHIFT));
+	}
+}
+EXPORT_SYMBOL(bigsur_port_map);
+
+void bigsur_port_unmap(u32 baseport, u32 nports)
+{
+    u32 port, endport = baseport + nports;
+	
+    DPRINTK("bigsur_port_unmap(base=0x%0x, n=0x%0x)\n", baseport, nports);
+
+	for (port = baseport ;
+	     port < endport && port < BIGSUR_IOMAP_LO_THRESH ;
+	     port += (1<<BIGSUR_IOMAP_LO_SHIFT)) {
+    	    bigsur_iomap_lo[port>>BIGSUR_IOMAP_LO_SHIFT] = 0;
+	}
+
+	for (port = MAX(baseport, BIGSUR_IOMAP_LO_THRESH) ;
+	     port < endport && port < BIGSUR_IOMAP_HI_THRESH ;
+	     port += (1<<BIGSUR_IOMAP_HI_SHIFT)) {
+    	    bigsur_iomap_hi[port>>BIGSUR_IOMAP_HI_SHIFT] = 0;
+	}
+}
+EXPORT_SYMBOL(bigsur_port_unmap);
+
+unsigned long bigsur_isa_port2addr(unsigned long port)
+{
+    unsigned long addr = 0;
+	unsigned char shift;
+
+	/* Physical address not in P0, do nothing */
+	if (PXSEG(port)) addr = port;
+	/* physical address in P0, map to P2 */
+	else if (port >= 0x30000)
+	    addr = P2SEGADDR(port);
+	/* Big Sur I/O + HD64465 registers 0x10000-0x30000 */
+	else if (port >= BIGSUR_IOMAP_HI_THRESH)
+	    addr = BIGSUR_INTERNAL_BASE + (port - BIGSUR_IOMAP_HI_THRESH);
+	/* Handle remapping of high IO/PCI IO ports */
+	else if (port >= BIGSUR_IOMAP_LO_THRESH) {
+	    addr = bigsur_iomap_hi[port >> BIGSUR_IOMAP_HI_SHIFT];
+	    shift = bigsur_iomap_hi_shift[port >> BIGSUR_IOMAP_HI_SHIFT];
+	    if (addr != 0)
+		    addr += (port & BIGSUR_IOMAP_HI_MASK) << shift;
+	}
+	/* Handle remapping of low IO ports */
+	else {
+	    addr = bigsur_iomap_lo[port >> BIGSUR_IOMAP_LO_SHIFT];
+	    shift = bigsur_iomap_lo_shift[port >> BIGSUR_IOMAP_LO_SHIFT];
+	    if (addr != 0)
+	    	addr += (port & BIGSUR_IOMAP_LO_MASK) << shift;
+	}
+
+    DIPRINTK(2, "PORT2ADDR(0x%08lx) = 0x%08lx\n", port, addr);
+
+	return addr;
+}
+
+static inline void delay(void)
+{
+	ctrl_inw(0xa0000000);
+}
+
+unsigned char bigsur_inb(unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+	unsigned long b = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
+
+	DIPRINTK(0, "inb(%08lx) = %02x\n", addr, (unsigned)b);
+	return b;
+}
+
+unsigned char bigsur_inb_p(unsigned long port)
+{
+    unsigned long v;
+	unsigned long addr = PORT2ADDR(port);
+
+	v = (addr == 0 ? 0 : *(volatile unsigned char*)addr);
+	delay();
+	DIPRINTK(0, "inb_p(%08lx) = %02x\n", addr, (unsigned)v);
+	return v;
+}
+
+unsigned short bigsur_inw(unsigned long port)
+{
+    unsigned long addr = PORT2ADDR(port);
+	unsigned long b = (addr == 0 ? 0 : *(volatile unsigned short*)addr);
+	DIPRINTK(0, "inw(%08lx) = %04lx\n", addr, b);
+	return b;
+}
+
+unsigned int bigsur_inl(unsigned long port)
+{
+    unsigned long addr = PORT2ADDR(port);
+	unsigned int b = (addr == 0 ? 0 : *(volatile unsigned long*)addr);
+	DIPRINTK(0, "inl(%08lx) = %08x\n", addr, b);
+	return b;
+}
+
+void bigsur_insb(unsigned long port, void *buffer, unsigned long count)
+{
+	unsigned char *buf=buffer;
+	while(count--) *buf++=inb(port);
+}
+
+void bigsur_insw(unsigned long port, void *buffer, unsigned long count)
+{
+	unsigned short *buf=buffer;
+	while(count--) *buf++=inw(port);
+}
+
+void bigsur_insl(unsigned long port, void *buffer, unsigned long count)
+{
+	unsigned long *buf=buffer;
+	while(count--) *buf++=inl(port);
+}
+
+void bigsur_outb(unsigned char b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+
+	DIPRINTK(0, "outb(%02x, %08lx)\n", (unsigned)b, addr);
+	if (addr != 0)
+	    *(volatile unsigned char*)addr = b;
+}
+
+void bigsur_outb_p(unsigned char b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+
+	DIPRINTK(0, "outb_p(%02x, %08lx)\n", (unsigned)b, addr);
+    if (addr != 0)
+	    *(volatile unsigned char*)addr = b;
+	delay();
+}
+
+void bigsur_outw(unsigned short b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+	DIPRINTK(0, "outw(%04x, %08lx)\n", (unsigned)b, addr);
+	if (addr != 0)
+	    *(volatile unsigned short*)addr = b;
+}
+
+void bigsur_outl(unsigned int b, unsigned long port)
+{
+	unsigned long addr = PORT2ADDR(port);
+	DIPRINTK(0, "outl(%08x, %08lx)\n", b, addr);
+	if (addr != 0)
+            *(volatile unsigned long*)addr = b;
+}
+
+void bigsur_outsb(unsigned long port, const void *buffer, unsigned long count)
+{
+	const unsigned char *buf=buffer;
+	while(count--) outb(*buf++, port);
+}
+
+void bigsur_outsw(unsigned long port, const void *buffer, unsigned long count)
+{
+	const unsigned short *buf=buffer;
+	while(count--) outw(*buf++, port);
+}
+
+void bigsur_outsl(unsigned long port, const void *buffer, unsigned long count)
+{
+	const unsigned long *buf=buffer;
+	while(count--) outl(*buf++, port);
+}
+
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_dc.c linux/arch/sh/kernel/io_dc.c
--- v2.4.5/linux/arch/sh/kernel/io_dc.c	Sun May 20 12:11:38 2001
+++ linux/arch/sh/kernel/io_dc.c	Wed Jun 27 13:55:29 2001
@@ -1,5 +1,5 @@
 /*
- *	$Id: io_dc.c,v 1.1 2001/04/01 15:02:00 yaegashi Exp $
+ *	$Id: io_dc.c,v 1.2 2001/05/24 00:13:47 gniibe Exp $
  *	I/O routines for SEGA Dreamcast
  */
 
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_hd64465.c linux/arch/sh/kernel/io_hd64465.c
--- v2.4.5/linux/arch/sh/kernel/io_hd64465.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/io_hd64465.c	Wed Jun 27 13:55:29 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: io_hd64465.c,v 1.6 2001/02/15 09:13:51 dave_mckay Exp $
+ * $Id: io_hd64465.c,v 1.7 2001/05/09 07:39:36 gniibe Exp $
  * by Greg Banks <gbanks@pocketpenguins.com>
  * (c) 2000 PocketPenguins Inc
  *
@@ -52,6 +52,8 @@
 #define MAX(a,b)    ((a)>(b)?(a):(b))
 #endif
 
+#define PORT2ADDR(x) (sh_mv.mv_isa_port2addr(x))
+
 void hd64465_port_map(unsigned short baseport, unsigned int nports,
 		      unsigned long addr, unsigned char shift)
 {
@@ -101,7 +103,7 @@
 }
 EXPORT_SYMBOL(hd64465_port_unmap);
 
-static /*__inline__*/ unsigned long PORT2ADDR(unsigned long port)
+unsigned long hd64465_isa_port2addr(unsigned long port)
 {
     	unsigned long addr = 0;
 	unsigned char shift;
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/io_sh2000.c linux/arch/sh/kernel/io_sh2000.c
--- v2.4.5/linux/arch/sh/kernel/io_sh2000.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/io_sh2000.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,19 @@
+/*
+ * I/O routine for SH-2000
+ */
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/machvec.h>
+
+#define IDE_OFFSET    0xb6200000
+#define NIC_OFFSET    0xb6000000
+#define EXTBUS_OFFSET 0xba000000
+
+unsigned long sh2000_isa_port2addr(unsigned long offset)
+{
+	if((offset & ~7) == 0x1f0 || offset == 0x3f6)
+		return IDE_OFFSET + offset;
+	else if((offset & ~0x1f) == 0x300)
+		return NIC_OFFSET + offset;
+	return EXTBUS_OFFSET + offset;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
--- v2.4.5/linux/arch/sh/kernel/irq.c	Fri Feb  9 11:29:44 2001
+++ linux/arch/sh/kernel/irq.c	Wed Jun 27 13:55:29 2001
@@ -38,12 +38,6 @@
 #include <linux/irq.h>
 
 /*
- * Micro-access to controllers is serialized over the whole
- * system. We never hold this lock when we call the actual
- * IRQ handler.
- */
-spinlock_t irq_controller_lock = SPIN_LOCK_UNLOCKED;
-/*
  * Controller mappings for all interrupt sources:
  */
 irq_desc_t irq_desc[NR_IRQS] __cacheline_aligned =
@@ -160,14 +154,15 @@
  */
 void disable_irq_nosync(unsigned int irq)
 {
+	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	spin_lock_irqsave(&irq_controller_lock, flags);
-	if (!irq_desc[irq].depth++) {
-		irq_desc[irq].status |= IRQ_DISABLED;
-		irq_desc[irq].handler->disable(irq);
+	spin_lock_irqsave(&desc->lock, flags);
+	if (!desc->depth++) {
+		desc->status |= IRQ_DISABLED;
+		desc->handler->disable(irq);
 	}
-	spin_unlock_irqrestore(&irq_controller_lock, flags);
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 /*
@@ -187,28 +182,29 @@
 
 void enable_irq(unsigned int irq)
 {
+	irq_desc_t *desc = irq_desc + irq;
 	unsigned long flags;
 
-	spin_lock_irqsave(&irq_controller_lock, flags);
-	switch (irq_desc[irq].depth) {
+	spin_lock_irqsave(&desc->lock, flags);
+	switch (desc->depth) {
 	case 1: {
-		unsigned int status = irq_desc[irq].status & ~IRQ_DISABLED;
-		irq_desc[irq].status = status;
+		unsigned int status = desc->status & ~IRQ_DISABLED;
+		desc->status = status;
 		if ((status & (IRQ_PENDING | IRQ_REPLAY)) == IRQ_PENDING) {
-			irq_desc[irq].status = status | IRQ_REPLAY;
-			hw_resend_irq(irq_desc[irq].handler,irq);
+			desc->status = status | IRQ_REPLAY;
+			hw_resend_irq(desc->handler,irq);
 		}
-		irq_desc[irq].handler->enable(irq);
+		desc->handler->enable(irq);
 		/* fall-through */
 	}
 	default:
-		irq_desc[irq].depth--;
+		desc->depth--;
 		break;
 	case 0:
 		printk("enable_irq() unbalanced from %p\n",
 		       __builtin_return_address(0));
 	}
-	spin_unlock_irqrestore(&irq_controller_lock, flags);
+	spin_unlock_irqrestore(&desc->lock, flags);
 }
 
 /*
@@ -245,7 +241,7 @@
 
 	kstat.irqs[cpu][irq]++;
 	desc = irq_desc + irq;
-	spin_lock(&irq_controller_lock);
+	spin_lock(&desc->lock);
 	desc->handler->ack(irq);
 	/*
 	   REPLAY is when Linux resends an IRQ that was dropped earlier
@@ -265,7 +261,6 @@
 		status |= IRQ_INPROGRESS; /* we are handling it */
 	}
 	desc->status = status;
-	spin_unlock(&irq_controller_lock);
 
 	/*
 	 * If there is no IRQ handler or it was disabled, exit early.
@@ -274,7 +269,7 @@
 	   will take care of it.
 	 */
 	if (!action)
-		return 1;
+		goto out;
 
 	/*
 	 * Edge triggered interrupts need to remember
@@ -287,23 +282,24 @@
 	 * SMP environment.
 	 */
 	for (;;) {
+		spin_unlock(&desc->lock);
 		handle_IRQ_event(irq, &regs, action);
-		spin_lock(&irq_controller_lock);
+		spin_lock(&desc->lock);
 
 		if (!(desc->status & IRQ_PENDING))
 			break;
 		desc->status &= ~IRQ_PENDING;
-		spin_unlock(&irq_controller_lock);
 	}
 	desc->status &= ~IRQ_INPROGRESS;
-	if (!(desc->status & IRQ_DISABLED))
-		desc->handler->end(irq);
-	spin_unlock(&irq_controller_lock);
+out:
+	/*
+	 * The ->end() handler has to deal with interrupts which got
+	 * disabled while the handler was running.
+	 */
+	desc->handler->end(irq);
+	spin_unlock(&desc->lock);
 
-#if 0
-	__sti();
-#endif
-	if (softirq_active(cpu)&softirq_mask(cpu))
+	if (softirq_pending(cpu))
 		do_softirq();
 	return 1;
 }
@@ -342,14 +338,16 @@
 
 void free_irq(unsigned int irq, void *dev_id)
 {
+	irq_desc_t *desc;
 	struct irqaction **p;
 	unsigned long flags;
 
 	if (irq >= ACTUAL_NR_IRQS)
 		return;
 
-	spin_lock_irqsave(&irq_controller_lock,flags);
-	p = &irq_desc[irq].action;
+	desc = irq_desc + irq;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
 	for (;;) {
 		struct irqaction * action = *p;
 		if (action) {
@@ -360,20 +358,22 @@
 
 			/* Found it - now remove it from the list of entries */
 			*pp = action->next;
-			if (!irq_desc[irq].action) {
-				irq_desc[irq].status |= IRQ_DISABLED;
-				irq_desc[irq].handler->shutdown(irq);
+			if (!desc->action) {
+				desc->status |= IRQ_DISABLED;
+				desc->handler->shutdown(irq);
 			}
-			spin_unlock_irqrestore(&irq_controller_lock,flags);
+			spin_unlock_irqrestore(&desc->lock,flags);
 			kfree(action);
 			return;
 		}
 		printk("Trying to free free IRQ%d\n",irq);
-		spin_unlock_irqrestore(&irq_controller_lock,flags);
+		spin_unlock_irqrestore(&desc->lock,flags);
 		return;
 	}
 }
 
+static DECLARE_MUTEX(probe_sem);
+
 /*
  * IRQ autodetection code..
  *
@@ -385,21 +385,44 @@
 unsigned long probe_irq_on(void)
 {
 	unsigned int i;
-	unsigned long delay;
+	irq_desc_t *desc;
 	unsigned long val;
+	unsigned long delay;
+
+	down(&probe_sem);
+	/* 
+	 * something may have generated an irq long ago and we want to
+	 * flush such a longstanding irq before considering it as spurious. 
+	 */
+	for (i = NR_IRQS-1; i > 0; i--) {
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!desc->action)
+		  desc->handler->startup(i);
+		spin_unlock_irq(&desc->lock);
+	}
+
+	/* Wait for longstanding interrupts to trigger. */
+	for (delay = jiffies + HZ/50; time_after(delay, jiffies); )
+		/* about 20ms delay */ synchronize_irq();
 
 	/*
-	 * first, enable any unassigned irqs
+	 * enable any unassigned irqs
+	 * (we must startup again here because if a longstanding irq
+	 * happened in the previous stage, it may have masked itself)
 	 */
-	spin_lock_irq(&irq_controller_lock);
 	for (i = NR_IRQS-1; i > 0; i--) {
-		if (!irq_desc[i].action) {
-			irq_desc[i].status |= IRQ_AUTODETECT | IRQ_WAITING;
-			if (irq_desc[i].handler->startup(i))
-				irq_desc[i].status |= IRQ_PENDING;
+		desc = irq_desc + i;
+
+		spin_lock_irq(&desc->lock);
+		if (!desc->action) {
+			desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
+			if (desc->handler->startup(i))
+				desc->status |= IRQ_PENDING;
 		}
+		spin_unlock_irq(&desc->lock);
 	}
-	spin_unlock_irq(&irq_controller_lock);
 
 	/*
 	 * Wait for spurious interrupts to trigger
@@ -411,23 +434,25 @@
 	 * Now filter out any obviously spurious interrupts
 	 */
 	val = 0;
-	spin_lock_irq(&irq_controller_lock);
 	for (i=0; i<NR_IRQS; i++) {
-		unsigned int status = irq_desc[i].status;
+		desc = irq_desc + i;
+		unsigned int status;
 
-		if (!(status & IRQ_AUTODETECT))
-			continue;
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
 
-		/* It triggered already - consider it spurious. */
-		if (!(status & IRQ_WAITING)) {
-			irq_desc[i].status = status & ~IRQ_AUTODETECT;
-			irq_desc[i].handler->shutdown(i);
+		if (status & IRQ_AUTODETECT) {
+			/* It triggered already - consider it spurious. */
+			if (!(status & IRQ_WAITING)) {
+				desc->status = status & ~IRQ_AUTODETECT;
+				desc->handler->shutdown(i);
+			} else
+				if (i < 32)
+					val |= 1 << i;
 		}
-
-		if (i < 32)
-			val |= 1 << i;
+		spin_unlock_irq(&desc->lock);
 	}
-	spin_unlock_irq(&irq_controller_lock);
+	spin_unlock_irq(&desc->lock);
 
 	return val;
 }
@@ -438,22 +463,25 @@
 
 	nr_irqs = 0;
 	irq_found = 0;
-	spin_lock_irq(&irq_controller_lock);
 	for (i=0; i<NR_IRQS; i++) {
-		unsigned int status = irq_desc[i].status;
+		irq_desc_t *desc = irq_desc + i;
+		unsigned int status;
 
-		if (!(status & IRQ_AUTODETECT))
-			continue;
+		spin_lock_irq(&desc->lock);
+		status = desc->status;
 
-		if (!(status & IRQ_WAITING)) {
-			if (!nr_irqs)
-				irq_found = i;
-			nr_irqs++;
+		if (status & IRQ_AUTODETECT) {
+			if (!(status & IRQ_WAITING)) {
+				if (!nr_irqs)
+					irq_found = i;
+				nr_irqs++;
+			}
+			desc->status = status & ~IRQ_AUTODETECT;
+			desc->handler->shutdown(i);
 		}
-		irq_desc[i].status = status & ~IRQ_AUTODETECT;
-		irq_desc[i].handler->shutdown(i);
+		spin_unlock_irq(&desc->lock);
 	}
-	spin_unlock_irq(&irq_controller_lock);
+	up(&probe_sem);
 
 	if (nr_irqs > 1)
 		irq_found = -irq_found;
@@ -465,6 +493,7 @@
 	int shared = 0;
 	struct irqaction *old, **p;
 	unsigned long flags;
+	irq_desc_t *desc = irq_desc + irq;
 
 	/*
 	 * Some drivers like serial.c use request_irq() heavily,
@@ -486,12 +515,12 @@
 	/*
 	 * The following block of code has to be executed atomically
 	 */
-	spin_lock_irqsave(&irq_controller_lock,flags);
-	p = &irq_desc[irq].action;
+	spin_lock_irqsave(&desc->lock,flags);
+	p = &desc->action;
 	if ((old = *p) != NULL) {
 		/* Can't share interrupts unless both agree to */
 		if (!(old->flags & new->flags & SA_SHIRQ)) {
-			spin_unlock_irqrestore(&irq_controller_lock,flags);
+			spin_unlock_irqrestore(&desc->lock,flags);
 			return -EBUSY;
 		}
 
@@ -506,11 +535,11 @@
 	*p = new;
 
 	if (!shared) {
-		irq_desc[irq].depth = 0;
-		irq_desc[irq].status &= ~IRQ_DISABLED;
-		irq_desc[irq].handler->startup(irq);
+		desc->depth = 0;
+		desc->status &= ~IRQ_DISABLED;
+		desc->handler->startup(irq);
 	}
-	spin_unlock_irqrestore(&irq_controller_lock,flags);
+	spin_unlock_irqrestore(&desc->lock,flags);
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/irq_intc2.c linux/arch/sh/kernel/irq_intc2.c
--- v2.4.5/linux/arch/sh/kernel/irq_intc2.c	Sun May 20 12:11:38 2001
+++ linux/arch/sh/kernel/irq_intc2.c	Wed Jun 27 13:55:29 2001
@@ -45,7 +45,7 @@
 }
 
 static struct hw_interrupt_type intc2_irq_type = {
-	"INTC2-based-IRQ",
+	"INTC2-IRQ",
 	startup_intc2_irq,
 	shutdown_intc2_irq,
 	enable_intc2_irq,
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/irq_ipr.c linux/arch/sh/kernel/irq_ipr.c
--- v2.4.5/linux/arch/sh/kernel/irq_ipr.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/irq_ipr.c	Wed Jun 27 13:55:29 2001
@@ -46,7 +46,7 @@
 }
 
 static struct hw_interrupt_type ipr_irq_type = {
-	"IPR-based-IRQ",
+	"IPR-IRQ",
 	startup_ipr_irq,
 	shutdown_ipr_irq,
 	enable_ipr_irq,
@@ -189,7 +189,9 @@
 
 void __init init_IRQ(void)
 {
+#if defined(CONFIG_CPU_SUBTYPE_SH7707) || defined(CONFIG_CPU_SUBTYPE_SH7709)
 	int i;
+#endif
 
 	make_ipr_irq(TIMER_IRQ, TIMER_IPR_ADDR, TIMER_IPR_POS, TIMER_PRIORITY);
 	make_ipr_irq(RTC_IRQ, RTC_IPR_ADDR, RTC_IPR_POS, RTC_PRIORITY);
@@ -226,27 +228,6 @@
 	 * Initialize the Interrupt Controller (INTC)
 	 * registers to their power on values
 	 */ 
-#if 0
-	/*
-	 * XXX: I think that this is the job of boot loader. -- gniibe
-	 *
-	 * When Takeshi released new boot loader following setting
-	 * will be removed shortly.
-	 */
-	ctrl_outb(0, INTC_IRR0);
-	ctrl_outb(0, INTC_IRR1);
-	ctrl_outb(0, INTC_IRR2);
-
-	ctrl_outw(0, INTC_ICR0);
-	ctrl_outw(0, INTC_ICR1);/* Really? 0x4000?*/
-	ctrl_outw(0, INTC_ICR2);
-	ctrl_outw(0, INTC_INTER);
-	ctrl_outw(0, INTC_IPRA);
-	ctrl_outw(0, INTC_IPRB);
-	ctrl_outw(0, INTC_IPRC);
-	ctrl_outw(0, INTC_IPRD);
-	ctrl_outw(0, INTC_IPRE);
-#endif
 
 	/*
 	 * Enable external irq (INTC IRQ mode).
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/led_bigsur.c linux/arch/sh/kernel/led_bigsur.c
--- v2.4.5/linux/arch/sh/kernel/led_bigsur.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/led_bigsur.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/sh/kernel/led_bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from led_se.c and led.c, which bore the message:
+ * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains Big Sur specific LED code.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include <asm/bigsur.h>
+
+static void mach_led(int position, int value)
+{
+	int word;
+	
+	word = bigsur_inl(BIGSUR_CSLR);
+	if (value) {
+		bigsur_outl(word & ~BIGSUR_LED, BIGSUR_CSLR);
+	} else {
+		bigsur_outl(word | BIGSUR_LED, BIGSUR_CSLR);
+	}
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* Cycle the LED on/off */
+void heartbeat_bigsur(void)
+{
+	static unsigned cnt = 0, period = 0, dist = 0;
+
+	if (cnt == 0 || cnt == dist)
+		mach_led( -1, 1);
+	else if (cnt == 7 || cnt == dist+7)
+		mach_led( -1, 0);
+
+	if (++cnt > period) {
+		cnt = 0;
+		/* The hyperbolic function below modifies the heartbeat period
+		 * length in dependency of the current (5min) load. It goes
+		 * through the points f(0)=126, f(1)=86, f(5)=51,
+		 * f(inf)->30. */
+		period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+		dist = period / 4;
+	}
+}
+#endif /* CONFIG_HEARTBEAT */
+
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/mach_bigsur.c linux/arch/sh/kernel/mach_bigsur.c
--- v2.4.5/linux/arch/sh/kernel/mach_bigsur.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/mach_bigsur.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/sh/kernel/mach_bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * Derived from mach_se.h, which bore the message:
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the Hitachi Big Sur Evaluation Board
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+#include <asm/io.h>
+#include <asm/io_bigsur.h>
+#include <asm/irq.h>
+
+/*
+ * The Machine Vector
+ */
+extern void heartbeat_bigsur(void);
+extern void setup_bigsur(void);
+extern void init_bigsur_IRQ(void);
+
+struct sh_machine_vector mv_bigsur __initmv = {
+	mv_name:		"Big Sur",
+	mv_nr_irqs:		NR_IRQS,     // Defined in <asm/irq.h>
+	mv_inb:			bigsur_inb,
+	mv_inw:			bigsur_inw,
+	mv_inl:			bigsur_inl,
+	mv_outb:		bigsur_outb,
+	mv_outw:		bigsur_outw,
+	mv_outl:		bigsur_outl,
+
+	mv_inb_p:		bigsur_inb_p,
+	mv_inw_p:		bigsur_inw,
+	mv_inl_p:		bigsur_inl,
+	mv_outb_p:		bigsur_outb_p,
+	mv_outw_p:		bigsur_outw,
+	mv_outl_p:		bigsur_outl,
+
+	mv_insb:		bigsur_insb,
+	mv_insw:		bigsur_insw,
+	mv_insl:		bigsur_insl,
+	mv_outsb:		bigsur_outsb,
+	mv_outsw:		bigsur_outsw,
+	mv_outsl:		bigsur_outsl,
+
+	mv_readb:		generic_readb,
+	mv_readw:		generic_readw,
+	mv_readl:		generic_readl,
+	mv_writeb:		generic_writeb,
+	mv_writew:		generic_writew,
+	mv_writel:		generic_writel,
+
+	mv_ioremap:		generic_ioremap,
+	mv_iounmap:		generic_iounmap,
+
+	mv_isa_port2addr:	bigsur_isa_port2addr,
+	mv_irq_demux:       bigsur_irq_demux,
+
+	mv_init_arch:		setup_bigsur,
+	mv_init_irq:		init_bigsur_IRQ,
+#ifdef CONFIG_HEARTBEAT
+	mv_heartbeat:		heartbeat_bigsur,
+#endif
+	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
+	mv_rtc_settimeofday:	sh_rtc_settimeofday,
+
+};
+ALIAS_MV(bigsur)
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/mach_dc.c linux/arch/sh/kernel/mach_dc.c
--- v2.4.5/linux/arch/sh/kernel/mach_dc.c	Sun May 20 12:11:38 2001
+++ linux/arch/sh/kernel/mach_dc.c	Wed Jun 27 13:55:29 2001
@@ -1,5 +1,5 @@
 /*
- *	$Id: mach_dc.c,v 1.1 2001/04/01 15:02:00 yaegashi Exp $
+ *	$Id: mach_dc.c,v 1.4 2001/05/24 05:09:16 mrbrown Exp $
  *	SEGA Dreamcast machine vector
  */
 
@@ -23,7 +23,7 @@
 struct sh_machine_vector mv_dreamcast __initmv = {
 	mv_name:		"dreamcast",
 
-	mv_nr_irqs:		48,
+	mv_nr_irqs:		NR_IRQS,
 
 	mv_inb:			generic_inb,
 	mv_inw:			generic_inw,
@@ -57,11 +57,9 @@
 	mv_iounmap:		generic_iounmap,
 
 	mv_init_arch:		setup_dreamcast,
-#ifdef CONFIG_PCI
-	mv_init_pci:		dreamcast_pcibios_init,
-#endif
 	mv_isa_port2addr:	dreamcast_isa_port2addr,
+	mv_irq_demux:		systemasic_irq_demux,
 
-	mv_hw_dreamcast:		1,
+	mv_hw_dreamcast:	1,
 };
 ALIAS_MV(dreamcast)
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-7751se.c linux/arch/sh/kernel/pci-7751se.c
--- v2.4.5/linux/arch/sh/kernel/pci-7751se.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/pci-7751se.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/sh/kernel/pci-7751se.c
+ *
+ * Author:  Ian DaSilva (idasilva@mvista.com)
+ *
+ * Highly leveraged from pci-bigsur.c, written by Dustin McIntire.
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Hitachi SH7751 Solution Engine board (MS7751SE01)
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/pci-sh7751.h>
+
+#define PCIMCR_MRSET_OFF	0xBFFFFFFF
+#define PCIMCR_RFSH_OFF		0xFFFFFFFB
+
+/*
+ * Only long word accesses of the PCIC's internal local registers and the
+ * configuration registers from the CPU is supported.
+ */
+#define PCIC_WRITE(x,v) writel((v), PCI_REG(x))
+#define PCIC_READ(x) readl(PCI_REG(x))
+
+/*
+ * Description:  This function sets up and initializes the pcic, sets
+ * up the BARS, maps the DRAM into the address space etc, etc.
+ */
+int __init pcibios_init_platform(void)
+{
+   unsigned long data;
+   unsigned long bcr1, wcr1, wcr2, wcr3, mcr;
+   unsigned short bcr2;
+
+   //
+   // Initialize the slave bus controller on the pcic.  The values used
+   // here should not be hardcoded, but they should be taken from the bsc
+   // on the processor, to make this function as generic as possible.
+   // (i.e. Another sbc may usr different SDRAM timing settings -- in order
+   // for the pcic to work, its settings need to be exactly the same.)
+   //
+   bcr1 = (*(volatile unsigned long*)(SH7751_BCR1));
+   bcr2 = (*(volatile unsigned short*)(SH7751_BCR2));
+   wcr1 = (*(volatile unsigned long*)(SH7751_WCR1));
+   wcr2 = (*(volatile unsigned long*)(SH7751_WCR2));
+   wcr3 = (*(volatile unsigned long*)(SH7751_WCR3));
+   mcr = (*(volatile unsigned long*)(SH7751_MCR));
+
+   bcr1 = bcr1 | 0x00080000;  /* Enable Bit 19, BREQEN */
+   (*(volatile unsigned long*)(SH7751_BCR1)) = bcr1;   
+
+   bcr1 = bcr1 | 0x40080000;  /* Enable Bit 19 BREQEN, set PCIC to slave */
+   PCIC_WRITE(SH7751_PCIBCR1, bcr1);	 /* PCIC BCR1 */
+   PCIC_WRITE(SH7751_PCIBCR2, bcr2);     /* PCIC BCR2 */
+   PCIC_WRITE(SH7751_PCIWCR1, wcr1);     /* PCIC WCR1 */
+   PCIC_WRITE(SH7751_PCIWCR2, wcr2);     /* PCIC WCR2 */
+   PCIC_WRITE(SH7751_PCIWCR3, wcr3);     /* PCIC WCR3 */
+   mcr = (mcr & PCIMCR_MRSET_OFF) & PCIMCR_RFSH_OFF;
+   PCIC_WRITE(SH7751_PCIMCR, mcr);      /* PCIC MCR */
+
+   PCIC_WRITE(SH7751_PCIINTM, 0x0000c3ff);
+   PCIC_WRITE(SH7751_PCIAINTM, 0x0000980f);
+   PCIC_WRITE(SH7751_PCICONF1, 0xF39000C7);  /* FB9000C7 */
+   PCIC_WRITE(SH7751_PCICONF2, 0x00000000);  /* PCI Class code & Revision ID */
+   PCIC_WRITE(SH7751_PCICONF4, 0xab000001);  /* PCI I/O */
+   PCIC_WRITE(SH7751_PCICONF5, 0x0c000000);  /* PCI MEM0 old val: 0xb0000000 */
+   PCIC_WRITE(SH7751_PCICONF6, 0xd0000000);  /* PCI MEM1 */
+   PCIC_WRITE(SH7751_PCICONF11, 0x35051054); /* PCI Sub system ID & Sub system vendor ID */
+   PCIC_WRITE(SH7751_PCILSR0, 0x03f00000);   /* PCI MEM0 */
+   PCIC_WRITE(SH7751_PCILSR1, 0x00000000);   /* PCI MEM1 */
+   PCIC_WRITE(SH7751_PCILAR0, 0x0c000000);   /* MEM0 */
+   PCIC_WRITE(SH7751_PCILAR1, 0x00000000);   /* MEM1 */
+
+   PCIC_WRITE(SH7751_PCICR, 0xa5000001);
+
+   printk("SH7751 PCI: Finished initialization of the PCI controller\n");
+
+   return 1;
+}
+
+int __init pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+        switch (slot) {
+        case 0: return 13;
+        case 1: return 13; 	/* AMD Ethernet controller */
+        case 2: return -1;
+        case 3: return -1;
+        case 4: return -1;
+        default:
+                printk("PCI: Bad IRQ mapping request for slot %d\n", slot);
+                return -1;
+        }
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-bigsur.c linux/arch/sh/kernel/pci-bigsur.c
--- v2.4.5/linux/arch/sh/kernel/pci-bigsur.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/pci-bigsur.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,163 @@
+/*
+ * linux/arch/sh/kernel/pci-bigsur.c
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * PCI initialization for the Hitachi Big Sur Evaluation Board
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/pci-sh7751.h>
+#include <asm/bigsur.h>
+
+#define PCI_REG(reg)        (SH7751_PCIREG_BASE+reg)
+
+/*
+ * Initialize the Big Sur PCI interface 
+ * Setup hardware to be Central Funtion
+ * Copy the BSR regs to the PCI interface
+ * Setup PCI windows into local RAM
+ */
+int __init pcibios_init_platform(void) {
+	u32 reg;
+	u32 word;
+
+	PCIDBG(1,"PCI: bigsur_pci_init called\n");
+	/* Set the BCR's to enable PCI access */
+	reg = inl(SH7751_BCR1);
+	reg |= 0x80000;
+	outl(reg, SH7751_BCR1);
+	
+	/* Setup the host hardware */
+	if(inl(PCI_REG(SH7751_PCICONF0)) !=
+	   (u32)((SH7751_DEVICE_ID <<16) | (SH7751_VENDOR_ID))) {
+	   printk("PCI: Unkown PCI host bridge.\n");
+	   return 0;
+	}  
+	printk("PCI: SH7751 PCI host bridge found.\n");
+	
+	/* Turn the clocks back on (not done in reset)*/
+	outl(0, PCI_REG(SH7751_PCICLKR));
+	/* Clear Powerdown IRQ's (not done in reset) */
+	word = SH7751_PCIPINT_D3 | SH7751_PCIPINT_D0;
+	outl(word, PCI_REG(SH7751_PCICLKR));
+
+	/* toggle PCI reset pin */
+	word = SH7751_PCICR_PREFIX | SH7751_PCICR_PRST;
+	outl(word,PCI_REG(SH7751_PCICR));    
+	/* Wait for a long time... not 1 sec. but long enough */
+	mdelay(100);
+	word = SH7751_PCICR_PREFIX;
+	outl(word,PCI_REG(SH7751_PCICR)); 
+	
+    /* set the command/status bits to:
+     * Wait Cycle Control + Parity Enable + Bus Master +
+     * Mem space enable
+     */
+    word = SH7751_PCICONF1_WCC | SH7751_PCICONF1_PER | 
+           SH7751_PCICONF1_BUM | SH7751_PCICONF1_MES;
+	outl(word, PCI_REG(SH7751_PCICONF1));
+
+	/* define this host as the host bridge */
+	word = SH7751_PCI_HOST_BRIDGE << 24;
+	outl(word, PCI_REG(SH7751_PCICONF2));
+
+	/* Set IO and Mem windows to local address 
+	 * Make PCI and local address the same for easy 1 to 1 mapping 
+	 * Window0 = BIGSUR_LSR0_SIZE @ non-cached CS3 base = SDRAM
+	 * Window1 = BIGSUR_LSR1_SIZE @ cached CS3 base = SDRAM 
+	 */
+	word = BIGSUR_LSR0_SIZE - 1;
+	outl(word, PCI_REG(SH7751_PCILSR0));
+	word = BIGSUR_LSR1_SIZE - 1;
+	outl(word, PCI_REG(SH7751_PCILSR1));
+	/* Set the values on window 0 PCI config registers */
+	word = P2SEGADDR(SH7751_CS3_BASE_ADDR);
+	outl(word, PCI_REG(SH7751_PCILAR0));
+	outl(word, PCI_REG(SH7751_PCICONF5));
+	/* Set the values on window 1 PCI config registers */
+	word =  PHYSADDR(SH7751_CS3_BASE_ADDR);
+	outl(word, PCI_REG(SH7751_PCILAR1));
+	outl(word, PCI_REG(SH7751_PCICONF6));
+
+	/* Set the local 16MB PCI memory space window to 
+	 * the lowest PCI mapped address
+	 */
+	word = PCIBIOS_MIN_MEM & SH7751_PCIMBR_MASK;
+	PCIDBG(2,"PCI: Setting upper bits of Memory window to 0x%x\n", word);
+	outl(word , PCI_REG(SH7751_PCIMBR));
+
+	/* Map IO space into PCI IO window
+	 * The IO window is 64K-PCIBIOS_MIN_IO in size
+	 * IO addresses will be translated to the 
+	 * PCI IO window base address
+	 */
+	PCIDBG(3,"PCI: Mapping IO address 0x%x - 0x%x to base 0x%x\n", PCIBIOS_MIN_IO,
+	    (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO);
+	bigsur_port_map(PCIBIOS_MIN_IO, (64*1024), SH7751_PCI_IO_BASE+PCIBIOS_MIN_IO,0);
+	    
+	/* Make sure the MSB's of IO window are set to access PCI space correctly */
+	word = PCIBIOS_MIN_IO & SH7751_PCIIOBR_MASK;
+	PCIDBG(2,"PCI: Setting upper bits of IO window to 0x%x\n", word);
+	outl(word, PCI_REG(SH7751_PCIIOBR));
+	
+	/* Set PCI WCRx, BCRx's, copy from BSC locations */
+	word = inl(SH7751_BCR1);
+	/* check BCR for SDRAM in area 3 */
+	if(((word >> 3) & 1) == 0) {
+		printk("PCI: Area 3 is not configured for SDRAM. BCR1=0x%x\n", word);
+		return 0;
+	}
+	outl(word, PCI_REG(SH7751_PCIBCR1));
+	word = (u16)inw(SH7751_BCR2);
+	/* check BCR2 for 32bit SDRAM interface*/
+	if(((word >> 6) & 0x3) != 0x3) {
+		printk("PCI: Area 3 is not 32 bit SDRAM. BCR2=0x%x\n", word);
+		return 0;
+	}
+	outl(word, PCI_REG(SH7751_PCIBCR2));
+	/* configure the wait control registers */
+	word = inl(SH7751_WCR1);
+	outl(word, PCI_REG(SH7751_PCIWCR1));
+	word = inl(SH7751_WCR2);
+	outl(word, PCI_REG(SH7751_PCIWCR2));
+	word = inl(SH7751_WCR3);
+	outl(word, PCI_REG(SH7751_PCIWCR3));
+	word = inl(SH7751_MCR);
+	outl(word, PCI_REG(SH7751_PCIMCR));
+
+	/* NOTE: I'm ignoring the PCI error IRQs for now..
+	 * TODO: add support for the internal error interrupts and
+	 * DMA interrupts...
+	 */
+	 
+	/* SH7751 init done, set central function init complete */
+	word = SH7751_PCICR_PREFIX | SH7751_PCICR_CFIN;
+	outl(word,PCI_REG(SH7751_PCICR)); 
+	PCIDBG(2,"PCI: bigsur_pci_init finished\n");
+
+	return 1;
+}
+
+int pcibios_map_platform_irq(u8 slot, u8 pin)
+{
+    /* The Big Sur can be used in a CPCI chassis, but the SH7751 PCI interface is on the
+     * wrong end of the board so that it can also support a V320 CPI interface chip...
+     * Therefor the IRQ mapping is somewhat use dependent... I'l assume a linear map for
+     * now, i.e. INTA=slot0,pin0... INTD=slot3,pin0...
+     */ 
+    int irq = (slot + pin-1)%4 + BIGSUR_SH7751_PCI_IRQ_BASE;
+    PCIDBG(2,"PCI: Mapping Big Sur IRQ for slot %d, pin %c to irq %d\n", slot, pin-1+'A', irq);
+    return irq;
+     
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-dc.c linux/arch/sh/kernel/pci-dc.c
--- v2.4.5/linux/arch/sh/kernel/pci-dc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/pci-dc.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,276 @@
+/*
+ $	$Id: pci-dc.c,v 1.2 2001/05/24 05:09:16 mrbrown Exp $
+ *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/dc_sysasic.h>
+
+#define	GAPSPCI_REGS		0x01001400
+#define GAPSPCI_DMA_BASE	0x01840000
+#define GAPSPCI_DMA_SIZE	32768
+#define GAPSPCI_BBA_CONFIG	0x01001600
+
+#define	GAPSPCI_IRQ		HW_EVENT_EXTERNAL
+
+static int gapspci_dma_used;
+
+static struct pci_bus *pci_root_bus;
+
+struct pci_fixup pcibios_fixups[] = {
+	{0, 0, 0, NULL}
+};
+
+#define BBA_SELECTED(dev) (dev->bus->number==0 && dev->devfn==0)
+
+static int gapspci_read_config_byte(struct pci_dev *dev, int where,
+                                    u8 * val)
+{
+	if (BBA_SELECTED(dev))
+		*val = inb(GAPSPCI_BBA_CONFIG+where);
+	else
+                *val = 0xff;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int gapspci_read_config_word(struct pci_dev *dev, int where,
+                                    u16 * val)
+{
+        if (BBA_SELECTED(dev))
+		*val = inw(GAPSPCI_BBA_CONFIG+where);
+	else
+                *val = 0xffff;
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int gapspci_read_config_dword(struct pci_dev *dev, int where,
+                                     u32 * val)
+{
+        if (BBA_SELECTED(dev))
+		*val = inl(GAPSPCI_BBA_CONFIG+where);
+	else
+                *val = 0xffffffff;
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int gapspci_write_config_byte(struct pci_dev *dev, int where,
+                                     u8 val)
+{
+        if (BBA_SELECTED(dev))
+		outb(val, GAPSPCI_BBA_CONFIG+where);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int gapspci_write_config_word(struct pci_dev *dev, int where,
+                                     u16 val)
+{
+        if (BBA_SELECTED(dev))
+		outw(val, GAPSPCI_BBA_CONFIG+where);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static int gapspci_write_config_dword(struct pci_dev *dev, int where,
+                                      u32 val)
+{
+        if (BBA_SELECTED(dev))
+		outl(val, GAPSPCI_BBA_CONFIG+where);
+
+        return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_config_ops = {
+        gapspci_read_config_byte,
+        gapspci_read_config_word,
+        gapspci_read_config_dword,
+        gapspci_write_config_byte,
+        gapspci_write_config_word,
+        gapspci_write_config_dword
+};
+
+
+void pcibios_align_resource(void *data, struct resource *res,
+			    unsigned long size)
+{
+}
+
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+}
+
+
+void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			     struct resource *res, int resource)
+{
+}
+
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	/* No special bus mastering setup handling */
+}
+
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			printk(KERN_ERR
+			       "PCI: Device %s not available because"
+			       " of resource collisions\n",
+			       dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (cmd != old_cmd) {
+		printk("PCI: enabling device %s (%04x -> %04x)\n",
+		       dev->slot_name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+
+}
+
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t * dma_handle)
+{
+	unsigned long buf;
+
+	if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE)
+		return NULL;
+
+	buf = GAPSPCI_DMA_BASE+gapspci_dma_used;
+
+	gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size);
+	
+	printk("pci_alloc_consistent: %ld bytes at 0x%p\n", size, buf);
+
+	*dma_handle = (dma_addr_t)buf;
+
+	return (void *)P2SEGADDR(buf);
+}
+
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	/* XXX */
+}
+
+
+void __init pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+{
+}                                                                                
+
+void __init pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct list_head *ln;
+	struct pci_dev *dev;
+
+	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
+		dev = pci_dev_b(ln);
+		if (!BBA_SELECTED(dev)) continue;
+
+		printk("PCI: MMIO fixup to %s\n", dev->name);
+		dev->resource[1].start=0x01001700;
+		dev->resource[1].end=0x010017ff;
+	}
+}
+
+
+static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+{
+	return PCI_SLOT(dev->devfn);
+}
+
+
+static int __init map_dc_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	return GAPSPCI_IRQ;
+}
+
+
+void __init pcibios_init(void)
+{
+	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
+	/* pci_assign_unassigned_resources(); */
+	pci_fixup_irqs(no_swizzle, map_dc_irq);
+}
+
+
+/* Haven't done anything here as yet */
+char * __init pcibios_setup(char *str)
+{
+	return str;
+}
+
+
+int __init gapspci_init(void)
+{
+	int i;
+	char idbuf[16];
+
+	for(i=0; i<16; i++)
+		idbuf[i]=inb(GAPSPCI_REGS+i);
+
+	if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
+		return -1;
+
+	outl(0x5a14a501, GAPSPCI_REGS+0x18);
+
+	for(i=0; i<1000000; i++);
+
+	if(inl(GAPSPCI_REGS+0x18)!=1)
+		return -1;
+
+	outl(0x01000000, GAPSPCI_REGS+0x20);
+	outl(0x01000000, GAPSPCI_REGS+0x24);
+
+	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
+	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
+
+	outl(1, GAPSPCI_REGS+0x14);
+	outl(1, GAPSPCI_REGS+0x34);
+
+	gapspci_dma_used=0;
+
+	/* Setting Broadband Adapter */
+	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
+	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
+	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
+	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
+	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
+	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
+	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-dma.c linux/arch/sh/kernel/pci-dma.c
--- v2.4.5/linux/arch/sh/kernel/pci-dma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/pci-dma.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,42 @@
+/* 
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Dynamic DMA mapping support.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t * dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+	        /* Is it neccessary to do the memset? */
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	/* We must flush the cache before we pass it on to the device */
+	flush_cache_all();
+	return  P2SEGADDR(ret);
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+        unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
+
+	free_pages(p1addr, get_order(size));
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-sh.c linux/arch/sh/kernel/pci-sh.c
--- v2.4.5/linux/arch/sh/kernel/pci-sh.c	Wed Aug  9 13:59:04 2000
+++ linux/arch/sh/kernel/pci-sh.c	Wed Dec 31 16:00:00 1969
@@ -1,25 +0,0 @@
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <asm/machvec.h>
-
-void __init pcibios_init(void)
-{
-	if (sh_mv.mv_init_pci != NULL) {
-		sh_mv.mv_init_pci();
-	}
-}
-
-/* Haven't done anything here as yet */
-char * __init pcibios_setup(char *str)
-{
-	return str;
-}
-
-/* We don't have anything here to fixup */
-struct pci_fixup pcibios_fixups[] = {
-	{0, 0, 0, NULL}
-};
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci-sh7751.c linux/arch/sh/kernel/pci-sh7751.c
--- v2.4.5/linux/arch/sh/kernel/pci-sh7751.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/pci-sh7751.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,674 @@
+/*
+ *	Low-Level PCI Support for the SH7751
+ *
+ *  Dustin McIntire (dustin@sensoria.com)
+ *	Derived from arch/i386/kernel/pci-*.c which bore the message:
+ *	(c) 1999--2000 Martin Mares <mj@suse.cz>
+ *	
+ *  May be copied or modified under the terms of the GNU General Public
+ *  License.  See linux/COPYING for more information.
+ *
+*/
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+
+#include <asm/segment.h>
+#include <asm/machvec.h>
+#include <asm/io.h>
+#include <asm/pci-sh7751.h>
+
+struct pci_ops *pci_check_direct(void);
+void pcibios_resource_survey(void);
+static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin);
+static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin);
+
+unsigned int pci_probe = PCI_PROBE_BIOS | PCI_PROBE_CONF1;
+int pcibios_last_bus = -1;
+struct pci_bus *pci_root_bus;
+struct pci_ops *pci_root_ops;
+
+/*
+ * Direct access to PCI hardware...
+ */
+
+#ifdef CONFIG_PCI_DIRECT
+
+
+#define CONFIG_CMD(dev, where) (0x80000000 | (dev->bus->number << 16) | (dev->devfn << 8) | (where & ~3))
+
+#define PCI_REG(reg) (SH7751_PCIREG_BASE+reg)
+
+/*
+ * Functions for accessing PCI configuration space with type 1 accesses
+ */
+static int pci_conf1_read_config_byte(struct pci_dev *dev, int where, u8 *value)
+{
+	u32 word;
+	unsigned long flags;
+
+    /* PCIPDR may only be accessed as 32 bit words, 
+     * so we must do byte alignment by hand 
+     */
+	__save_and_cli(flags);
+	outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR));
+	word = inl(PCI_REG(SH7751_PCIPDR));
+	__restore_flags(flags);
+	switch (where & 0x3) {
+	    case 3:
+		    *value = (u8)(word >> 24);
+			break;
+		case 2:
+		    *value = (u8)(word >> 16);
+			break;
+		case 1:
+		    *value = (u8)(word >> 8);
+			break;
+		default:
+		    *value = (u8)word;
+			break;
+    }
+	PCIDBG(4,"pci_conf1_read_config_byte@0x%08x=0x%x\n",
+	     CONFIG_CMD(dev,where),*value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config_word(struct pci_dev *dev, int where, u16 *value)
+{
+	u32 word;
+	unsigned long flags;
+
+    /* PCIPDR may only be accessed as 32 bit words, 
+     * so we must do word alignment by hand 
+     */
+	__save_and_cli(flags);
+	outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR));
+	word = inl(PCI_REG(SH7751_PCIPDR));
+	__restore_flags(flags);
+	switch (where & 0x3) {
+	    case 3:
+		    // This should never happen...
+			printk(KERN_ERR "PCI BIOS: read_config_word: Illegal u16 alignment");
+	        return PCIBIOS_BAD_REGISTER_NUMBER;
+		case 2:
+		    *value = (u16)(word >> 16);
+			break;
+		case 1:
+		    *value = (u16)(word >> 8);
+			break;
+		default:
+		    *value = (u16)word;
+			break;
+    }
+	PCIDBG(4,"pci_conf1_read_config_word@0x%08x=0x%x\n",
+	     CONFIG_CMD(dev,where),*value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_read_config_dword(struct pci_dev *dev, int where, u32 *value)
+{
+	unsigned long flags;
+	
+	__save_and_cli(flags);
+	outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR));
+	*value = inl(PCI_REG(SH7751_PCIPDR));
+	__restore_flags(flags);
+	PCIDBG(4,"pci_conf1_read_config_dword@0x%08x=0x%x\n",
+	     CONFIG_CMD(dev,where),*value);
+	return PCIBIOS_SUCCESSFUL;    
+}
+
+static int pci_conf1_write_config_byte(struct pci_dev *dev, int where, u8 value)
+{
+	u32 word;
+	u32 shift = (where & 3) * 8;
+	u32 mask = ((1 << 8) - 1) << shift;  // create the byte mask
+	unsigned long flags;
+
+    /* Since SH7751 only does 32bit access we'll have to do a
+     * read,mask,write operation
+     */ 
+	__save_and_cli(flags);
+	outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR));
+	word = inl(PCI_REG(SH7751_PCIPDR)) ;
+	word &= ~mask;
+	word |= value << shift;
+ 
+	outl(word, PCI_REG(SH7751_PCIPDR));
+	__restore_flags(flags);
+	PCIDBG(4,"pci_conf1_write_config_byte@0x%08x=0x%x\n",
+	     CONFIG_CMD(dev,where),word);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config_word(struct pci_dev *dev, int where, u16 value)
+{
+	u32 word;
+	u32 shift = (where & 3) * 8;
+	u32 mask = ((1 << 16) - 1) << shift;  // create the word mask
+	unsigned long flags;
+
+    /* Since SH7751 only does 32bit access we'll have to do a
+     * read,mask,write operation.  We'll allow an odd byte offset,
+	 * though it should be illegal.
+     */ 
+	if (shift == 24)
+	    return PCIBIOS_BAD_REGISTER_NUMBER;
+	__save_and_cli(flags);
+	outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR));
+	word = inl(PCI_REG(SH7751_PCIPDR)) ;
+	word &= ~mask;
+	word |= value << shift;
+ 
+	outl(value, PCI_REG(SH7751_PCIPDR));
+	__restore_flags(flags);
+	PCIDBG(4,"pci_conf1_write_config_word@0x%08x=0x%x\n",
+	     CONFIG_CMD(dev,where),word);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pci_conf1_write_config_dword(struct pci_dev *dev, int where, u32 value)
+{
+	unsigned long flags;
+
+	__save_and_cli(flags);
+	outl(CONFIG_CMD(dev,where), PCI_REG(SH7751_PCIPAR));
+	outl(value, PCI_REG(SH7751_PCIPDR));
+	__restore_flags(flags);
+	PCIDBG(4,"pci_conf1_write_config_dword@0x%08x=0x%x\n",
+	     CONFIG_CMD(dev,where),value);
+	return PCIBIOS_SUCCESSFUL;
+}
+
+#undef CONFIG_CMD
+
+static struct pci_ops pci_direct_conf1 = {
+	pci_conf1_read_config_byte,
+	pci_conf1_read_config_word,
+	pci_conf1_read_config_dword,
+	pci_conf1_write_config_byte,
+	pci_conf1_write_config_word,
+	pci_conf1_write_config_dword
+};
+
+struct pci_ops * __init pci_check_direct(void)
+{
+	unsigned int tmp, id;
+
+	/* check for SH7751 hardware */
+	id = (SH7751_DEVICE_ID << 16) | SH7751_VENDOR_ID;
+	if(inl(SH7751_PCIREG_BASE+SH7751_PCICONF0) != id) {
+		PCIDBG(2,"PCI: This is not an SH7751\n");
+		return NULL;
+	}
+	/*
+	 * Check if configuration works.
+	 */
+	if (pci_probe & PCI_PROBE_CONF1) {
+		tmp = inl (PCI_REG(SH7751_PCIPAR));
+		outl (0x80000000, PCI_REG(SH7751_PCIPAR));
+		if (inl (PCI_REG(SH7751_PCIPAR)) == 0x80000000) {
+			outl (tmp, PCI_REG(SH7751_PCIPAR));
+			printk(KERN_INFO "PCI: Using configuration type 1\n");
+			request_region(PCI_REG(SH7751_PCIPAR), 8, "PCI conf1");
+			return &pci_direct_conf1;
+		}
+		outl (tmp, PCI_REG(SH7751_PCIPAR));
+	}
+
+	PCIDBG(2,"PCI: pci_check_direct failed\n");
+	return NULL;
+}
+
+#endif
+
+/*
+ * BIOS32 and PCI BIOS handling.
+ * 
+ * The BIOS version of the pci functions is not yet implemented but it is left
+ * in for completeness.  Currently an error will be genereated at compile time. 
+ */
+ 
+#ifdef CONFIG_PCI_BIOS
+
+#error PCI BIOS is not yet supported on SH7751
+
+#endif /* CONFIG_PCI_BIOS */
+
+/***************************************************************************************/
+
+/*
+ *  Handle bus scanning and fixups ....
+ */
+
+
+/*
+ * Discover remaining PCI buses in case there are peer host bridges.
+ * We use the number of last PCI bus provided by the PCI BIOS.
+ */
+static void __init pcibios_fixup_peer_bridges(void)
+{
+	int n;
+	struct pci_bus bus;
+	struct pci_dev dev;
+	u16 l;
+
+	if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff)
+		return;
+	PCIDBG(2,"PCI: Peer bridge fixup\n");
+	for (n=0; n <= pcibios_last_bus; n++) {
+		if (pci_bus_exists(&pci_root_buses, n))
+			continue;
+		bus.number = n;
+		bus.ops = pci_root_ops;
+		dev.bus = &bus;
+		for(dev.devfn=0; dev.devfn<256; dev.devfn += 8)
+			if (!pci_read_config_word(&dev, PCI_VENDOR_ID, &l) &&
+			    l != 0x0000 && l != 0xffff) {
+				PCIDBG(3,"Found device at %02x:%02x [%04x]\n", n, dev.devfn, l);
+				printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n);
+				pci_scan_bus(n, pci_root_ops, NULL);
+				break;
+			}
+	}
+}
+
+
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	PCIDBG(3,"PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ 0 }
+};
+
+void __init pcibios_fixup_pbus_ranges(struct pci_bus *b,
+		struct pbus_set_ranges_data *range)
+{
+	/* No fixups needed */
+}
+
+/*
+ *  Called after each bus is probed, but before its children
+ *  are examined.
+ */
+
+void __init pcibios_fixup_bus(struct pci_bus *b)
+{
+	pci_read_bridge_bases(b);
+}
+
+/*
+ * Initialization. Try all known PCI access methods. Note that we support
+ * using both PCI BIOS and direct access: in such cases, we use I/O ports
+ * to access config space.
+ * 
+ * Note that the platform specific initialization (BSC registers, and memory
+ * space mapping) will be called via the machine vectors (sh_mv.mv_pci_init()) if it
+ * exitst and via the platform defined function pcibios_init_platform().  
+ * See pci_bigsur.c for implementation;
+ * 
+ * The BIOS version of the pci functions is not yet implemented but it is left
+ * in for completeness.  Currently an error will be genereated at compile time. 
+ */
+
+void __init pcibios_init(void)
+{
+	struct pci_ops *bios = NULL;
+	struct pci_ops *dir = NULL;
+
+	PCIDBG(1,"PCI: Starting intialization.\n");
+#ifdef CONFIG_PCI_BIOS
+	if ((pci_probe & PCI_PROBE_BIOS) && ((bios = pci_find_bios()))) {
+		pci_probe |= PCI_BIOS_SORT;
+		pci_bios_present = 1;
+	}
+#endif
+#ifdef CONFIG_PCI_DIRECT
+	if (pci_probe & PCI_PROBE_CONF1 )
+		dir = pci_check_direct();
+#endif
+	if (dir) {
+		pci_root_ops = dir;
+	    if(!pcibios_init_platform())
+			PCIDBG(1,"PCI: Initialization failed\n");
+	    if (sh_mv.mv_init_pci != NULL)
+            sh_mv.mv_init_pci();
+	}
+	else if (bios)
+		pci_root_ops = bios;
+	else {
+		PCIDBG(1,"PCI: No PCI bus detected\n");
+		return;
+	}
+
+	PCIDBG(1,"PCI: Probing PCI hardware\n");
+	pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
+	//pci_assign_unassigned_resources();
+	pci_fixup_irqs(pcibios_swizzle, pcibios_lookup_irq);
+	pcibios_fixup_peer_bridges();
+	pcibios_resource_survey();
+
+#ifdef CONFIG_PCI_BIOS
+	if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT))
+		pcibios_sort();
+#endif
+}
+
+char * __init pcibios_setup(char *str)
+{
+	if (!strcmp(str, "off")) {
+		pci_probe = 0;
+		return NULL;
+	}
+#ifdef CONFIG_PCI_BIOS
+	else if (!strcmp(str, "bios")) {
+		pci_probe = PCI_PROBE_BIOS;
+		return NULL;
+	} else if (!strcmp(str, "nobios")) {
+		pci_probe &= ~PCI_PROBE_BIOS;
+		return NULL;
+	} else if (!strcmp(str, "nosort")) {
+		pci_probe |= PCI_NO_SORT;
+		return NULL;
+	} else if (!strcmp(str, "biosirq")) {
+		pci_probe |= PCI_BIOS_IRQ_SCAN;
+		return NULL;
+	}
+#endif
+#ifdef CONFIG_PCI_DIRECT
+	else if (!strcmp(str, "conf1")) {
+		pci_probe = PCI_PROBE_CONF1 | PCI_NO_CHECKS;
+		return NULL;
+	}
+#endif
+	else if (!strcmp(str, "rom")) {
+		pci_probe |= PCI_ASSIGN_ROMS;
+		return NULL;
+	} else if (!strncmp(str, "lastbus=", 8)) {
+		pcibios_last_bus = simple_strtol(str+8, NULL, 0);
+		return NULL;
+	}
+	return str;
+}
+
+void
+pcibios_update_resource(struct pci_dev *dev, struct resource *root,
+			struct resource *res, int resource)
+{
+	u32 new, check;
+	int reg;
+
+	new = res->start | (res->flags & PCI_REGION_FLAG_MASK);
+	if (resource < 6) {
+		reg = PCI_BASE_ADDRESS_0 + 4*resource;
+	} else if (resource == PCI_ROM_RESOURCE) {
+		res->flags |= PCI_ROM_ADDRESS_ENABLE;
+		new |= PCI_ROM_ADDRESS_ENABLE;
+		reg = dev->rom_base_reg;
+	} else {
+		/* Somebody might have asked allocation of a non-standard resource */
+		return;
+	}
+	
+	pci_write_config_dword(dev, reg, new);
+	pci_read_config_dword(dev, reg, &check);
+	if ((new ^ check) & ((new & PCI_BASE_ADDRESS_SPACE_IO) ? PCI_BASE_ADDRESS_IO_MASK : PCI_BASE_ADDRESS_MEM_MASK)) {
+		printk(KERN_ERR "PCI: Error while updating region "
+		       "%s/%d (%08x != %08x)\n", dev->slot_name, resource,
+		       new, check);
+	}
+}
+
+/*
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ */
+void
+pcibios_align_resource(void *data, struct resource *res, unsigned long size)
+{
+	if (res->flags & IORESOURCE_IO) {
+		unsigned long start = res->start;
+
+		if (start & 0x300) {
+			start = (start + 0x3ff) & ~0x3ff;
+			res->start = start;
+		}
+	}
+}
+
+
+/*
+ *    Allocate the bridge and device resources
+ */
+
+static void __init pcibios_allocate_bus_resources(struct list_head *bus_list)
+{
+	struct list_head *ln;
+	struct pci_bus *bus;
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r, *pr;
+	
+	PCIDBG(2,"PCI: pcibios_allocate_bus_reasources called\n" );
+	/* Depth-First Search on bus tree */
+	for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+		bus = pci_bus_b(ln);
+		if ((dev = bus->self)) {
+			for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
+				r = &dev->resource[idx];
+				if (!r->start)
+					continue;
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0)
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
+			}
+		}
+		pcibios_allocate_bus_resources(&bus->children);
+	}
+}
+
+static void __init pcibios_allocate_resources(int pass)
+{
+	struct pci_dev *dev;
+	int idx, disabled;
+	u16 command;
+	struct resource *r, *pr;
+
+	PCIDBG(2,"PCI: pcibios_allocate_resources pass %d called\n", pass);
+	pci_for_each_dev(dev) {
+		pci_read_config_word(dev, PCI_COMMAND, &command);
+		for(idx = 0; idx < 6; idx++) {
+			r = &dev->resource[idx];
+			if (r->parent)		/* Already allocated */
+				continue;
+			if (!r->start)		/* Address not assigned at all */
+				continue;
+			if (r->flags & IORESOURCE_IO)
+				disabled = !(command & PCI_COMMAND_IO);
+			else
+				disabled = !(command & PCI_COMMAND_MEMORY);
+			if (pass == disabled) {
+				PCIDBG(3,"PCI: Resource %08lx-%08lx (f=%lx, d=%d, p=%d)\n",
+				    r->start, r->end, r->flags, disabled, pass);
+				pr = pci_find_parent_resource(dev, r);
+				if (!pr || request_resource(pr, r) < 0) {
+					printk(KERN_ERR "PCI: Cannot allocate resource region %d of device %s\n", idx, dev->slot_name);
+					/* We'll assign a new address later */
+					r->end -= r->start;
+					r->start = 0;
+				}
+			}
+		}
+		if (!pass) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			if (r->flags & PCI_ROM_ADDRESS_ENABLE) {
+				/* Turn the ROM off, leave the resource region, but keep it unregistered. */
+				u32 reg;
+				PCIDBG(3,"PCI: Switching off ROM of %s\n", dev->slot_name);
+				r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
+				pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+				pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+			}
+		}
+	}
+}
+
+static void __init pcibios_assign_resources(void)
+{
+	struct pci_dev *dev;
+	int idx;
+	struct resource *r;
+
+	PCIDBG(2,"PCI: pcibios_assign_resources called\n");
+	pci_for_each_dev(dev) {
+		int class = dev->class >> 8;
+
+		/* Don't touch classless devices and host bridges */
+		if (!class || class == PCI_CLASS_BRIDGE_HOST)
+			continue;
+
+		for(idx=0; idx<6; idx++) {
+			r = &dev->resource[idx];
+
+			/*
+			 *  Don't touch IDE controllers and I/O ports of video cards!
+			 */
+			if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
+			    (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
+				continue;
+
+			/*
+			 *  We shall assign a new address to this resource, either because
+			 *  the BIOS forgot to do so or because we have decided the old
+			 *  address was unusable for some reason.
+			 */
+			if (!r->start && r->end)
+				pci_assign_resource(dev, idx);
+		}
+
+		if (pci_probe & PCI_ASSIGN_ROMS) {
+			r = &dev->resource[PCI_ROM_RESOURCE];
+			r->end -= r->start;
+			r->start = 0;
+			if (r->end)
+				pci_assign_resource(dev, PCI_ROM_RESOURCE);
+		}
+	}
+}
+
+void __init pcibios_resource_survey(void)
+{
+	PCIDBG(1,"PCI: Allocating resources\n");
+	pcibios_allocate_bus_resources(&pci_root_buses);
+	pcibios_allocate_resources(0);
+	pcibios_allocate_resources(1);
+	pcibios_assign_resources();
+}
+
+int pcibios_enable_device(struct pci_dev *dev)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for(idx=0; idx<6; idx++) {
+		r = &dev->resource[idx];
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because of resource collisions\n", dev->slot_name);
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+	if (dev->resource[PCI_ROM_RESOURCE].start)
+		cmd |= PCI_COMMAND_MEMORY;
+	if (cmd != old_cmd) {
+		printk(KERN_INFO "PCI: Enabling device %s (%04x -> %04x)\n", dev->name, old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+/*
+ *  If we set up a device for bus mastering, we need to check and set
+ *  the latency timer as it may not be properly set.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	u8 lat;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	if (lat < 16)
+		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+	else if (lat > pcibios_max_latency)
+		lat = pcibios_max_latency;
+	else
+		return;
+	printk(KERN_INFO "PCI: Setting latency timer of device %s to %d\n", dev->name, lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+/***************************************************************************************/
+/* 
+ * 	IRQ functions 
+ */
+static u8 __init pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	/* no swizzling */
+	return PCI_SLOT(dev->devfn);
+}
+
+static int pcibios_lookup_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq = -1;
+
+	/* now lookup the actual IRQ on a platform specific basis (pci-'platform'.c) */
+	irq = pcibios_map_platform_irq(slot,pin);
+	if( irq < 0 ) {
+	    PCIDBG(3,"PCI: Error mapping IRQ on device %s\n", dev->name);
+		return irq;
+	}
+	
+	PCIDBG(2,"Setting IRQ for slot %s to %d\n", dev->slot_name, irq);
+
+	return irq;
+}
+
+void __init pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	PCIDBG(3,"PCI: Update IRQ for %s on irq %d\n", dev->name, irq);
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/pci_st40.c linux/arch/sh/kernel/pci_st40.c
--- v2.4.5/linux/arch/sh/kernel/pci_st40.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/pci_st40.c	Wed Jun 27 13:55:29 2001
@@ -141,6 +141,31 @@
 	return tmp;
 }
 
+static void __init pci_fixup_ide_bases(struct pci_dev *d)
+{
+	int i;
+
+	/*
+	 * PCI IDE controllers use non-standard I/O port decoding, respect it.
+	 */
+	if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return;
+	printk("PCI: IDE base address fixup for %s\n", d->slot_name);
+	for(i=0; i<4; i++) {
+		struct resource *r = &d->resource[i];
+		if ((r->start & ~0x80) == 0x374) {
+			r->start |= 2;
+			r->end = r->start;
+		}
+	}
+}
+
+
+/* Add future fixups here... */
+struct pci_fixup pcibios_fixups[] = {
+	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,	PCI_ANY_ID,	pci_fixup_ide_bases },
+	{ 0 }
+};
 
 int __init st40pci_init(unsigned memStart, unsigned memSize)
 {
@@ -234,6 +259,11 @@
 	return 1;
 }
 
+char * __init pcibios_setup(char *str)
+{
+	return str;
+}
+
 
 #define SET_CONFIG_BITS(bus,devfn,where)\
   (((bus) << 16) | ((devfn) << 8) | ((where) & ~3) | (bus!=0))
@@ -390,10 +420,14 @@
 	ranges->mem_end -= bus->resource[1]->start;
 }
 
-void __init st40_pcibios_init(void)
+void __init pcibios_init(void)
 {
 	extern unsigned long memory_start, memory_end;
 
+	if (sh_mv.mv_init_pci != NULL) {
+		sh_mv.mv_init_pci();
+	}
+
 	/* The pci subsytem needs to know where memory is and how much 
 	 * of it there is. I've simply made these globals. A better mechanism
 	 * is probably needed.
@@ -491,4 +525,24 @@
 {
 	printk("PCI: Assigning IRQ %02d to %s\n", irq, dev->name);
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ *  If we set up a device for bus mastering, we need to check the latency
+ *  timer as certain crappy BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
+void pcibios_set_master(struct pci_dev *dev)
+{
+	u8 lat;
+	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+	if (lat < 16)
+		lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+	else if (lat > pcibios_max_latency)
+		lat = pcibios_max_latency;
+	else
+		return;
+	printk("PCI: Setting latency timer of device %s to %d\n", dev->slot_name, lat);
+	pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/rtc.c linux/arch/sh/kernel/rtc.c
--- v2.4.5/linux/arch/sh/kernel/rtc.c	Thu May 24 15:14:08 2001
+++ linux/arch/sh/kernel/rtc.c	Wed Jun 27 13:55:29 2001
@@ -13,62 +13,6 @@
 #include <asm/io.h>
 #include <asm/rtc.h>
 
-/* RCR1 Bits */
-#define RCR1_CF		0x80	/* Carry Flag             */
-#define RCR1_CIE	0x10	/* Carry Interrupt Enable */
-#define RCR1_AIE	0x08	/* Alarm Interrupt Enable */
-#define RCR1_AF		0x01	/* Alarm Flag             */
-
-/* RCR2 Bits */
-#define RCR2_PEF	0x80	/* PEriodic interrupt Flag */
-#define RCR2_PESMASK	0x70	/* Periodic interrupt Set  */
-#define RCR2_RTCEN	0x08	/* ENable RTC              */
-#define RCR2_ADJ	0x04	/* ADJustment (30-second)  */
-#define RCR2_RESET	0x02	/* Reset bit               */
-#define RCR2_START	0x01	/* Start bit               */
-
-#if defined(__sh3__)
-/* SH-3 RTC */
-#define R64CNT  	0xfffffec0
-#define RSECCNT 	0xfffffec2
-#define RMINCNT 	0xfffffec4
-#define RHRCNT  	0xfffffec6
-#define RWKCNT  	0xfffffec8
-#define RDAYCNT 	0xfffffeca
-#define RMONCNT 	0xfffffecc
-#define RYRCNT  	0xfffffece
-#define RSECAR  	0xfffffed0
-#define RMINAR  	0xfffffed2
-#define RHRAR   	0xfffffed4
-#define RWKAR   	0xfffffed6
-#define RDAYAR  	0xfffffed8
-#define RMONAR  	0xfffffeda
-#define RCR1    	0xfffffedc
-#define RCR2    	0xfffffede
-
-#define RTC_BIT_INVERTED	0	/* No bug on SH7708, SH7709A */
-#elif defined(__SH4__)
-/* SH-4 RTC */
-#define R64CNT  	0xffc80000
-#define RSECCNT 	0xffc80004
-#define RMINCNT 	0xffc80008
-#define RHRCNT  	0xffc8000c
-#define RWKCNT  	0xffc80010
-#define RDAYCNT 	0xffc80014
-#define RMONCNT 	0xffc80018
-#define RYRCNT  	0xffc8001c  /* 16bit */
-#define RSECAR  	0xffc80020
-#define RMINAR  	0xffc80024
-#define RHRAR   	0xffc80028
-#define RWKAR   	0xffc8002c
-#define RDAYAR  	0xffc80030
-#define RMONAR  	0xffc80034
-#define RCR1    	0xffc80038
-#define RCR2    	0xffc8003c
-
-#define RTC_BIT_INVERTED	0x40	/* bug on SH7750, SH7750S */
-#endif
-
 #ifndef BCD_TO_BIN
 #define BCD_TO_BIN(val) ((val)=((val)&15) + ((val)>>4)*10)
 #endif
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c
--- v2.4.5/linux/arch/sh/kernel/setup.c	Fri Apr 27 14:10:32 2001
+++ linux/arch/sh/kernel/setup.c	Wed Jun 27 13:55:29 2001
@@ -521,6 +521,9 @@
 	
 	PRINT_CLOCK("CPU", boot_cpu_data.cpu_clock);
 	PRINT_CLOCK("Bus", boot_cpu_data.bus_clock);
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+	PRINT_CLOCK("Memory", boot_cpu_data.memory_clock);
+#endif
 	PRINT_CLOCK("Peripheral module", boot_cpu_data.module_clock);
 
 	return p - buffer;
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_bigsur.c linux/arch/sh/kernel/setup_bigsur.c
--- v2.4.5/linux/arch/sh/kernel/setup_bigsur.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/setup_bigsur.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,381 @@
+/*
+ *
+ * By Dustin McIntire (dustin@sensoria.com) (c)2001
+ * 
+ * Setup and IRQ handling code for the HD64465 companion chip.
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc
+ *
+ * Derived from setup_hd64465.c which bore the message:
+ * Greg Banks <gbanks@pocketpenguins.com>
+ * Copyright (c) 2000 PocketPenguins Inc and
+ * Copyright (C) 2000 YAEGASHI Takeshi
+ * and setup_cqreek.c which bore message:
+ * Copyright (C) 2000  Niibe Yutaka
+ * 
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Setup and IRQ functions for a Hitachi Big Sur Evaluation Board.
+ * 
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+
+#include <asm/io_bigsur.h>
+#include <asm/hd64465.h>
+#include <asm/bigsur.h>
+
+//#define BIGSUR_DEBUG 3
+#undef BIGSUR_DEBUG
+
+#ifdef BIGSUR_DEBUG
+#define DPRINTK(args...)	printk(args)
+#define DIPRINTK(n, args...)	if (BIGSUR_DEBUG>(n)) printk(args)
+#else
+#define DPRINTK(args...)
+#define DIPRINTK(n, args...)
+#endif /* BIGSUR_DEBUG */
+
+#ifdef CONFIG_HD64465
+extern int hd64465_irq_demux(int irq);
+#endif /* CONFIG_HD64465 */
+
+
+/*===========================================================*/
+//		Big Sur CPLD IRQ Routines	
+/*===========================================================*/
+
+/* Level 1 IRQ routines */
+static void disable_bigsur_l1irq(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned char mask;
+	unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
+	unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
+
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {	
+   		DPRINTK("Disable L1 IRQ %d\n", irq);
+   		DIPRINTK(2,"disable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", 
+   			mask_port, bit);
+		save_and_cli(flags);
+
+		/* Disable IRQ - set mask bit */
+		mask = inb(mask_port) | bit;
+		outb(mask, mask_port);
+		restore_flags(flags);
+		return;
+	}
+   	DPRINTK("disable_bigsur_l1irq: Invalid IRQ %d\n", irq);	
+}
+
+static void enable_bigsur_l1irq(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned char mask;
+	unsigned int mask_port = ((irq - BIGSUR_IRQ_LOW)/8) ? BIGSUR_IRLMR1 : BIGSUR_IRLMR0;
+	unsigned char bit =  (1 << ((irq - MGATE_IRQ_LOW)%8) );
+
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {	
+	   	DPRINTK("Enable L1 IRQ %d\n", irq);
+   		DIPRINTK(2,"enable_bigsur_l1irq: IMR=0x%08x mask=0x%x\n", 
+   			mask_port, bit);
+		save_and_cli(flags);
+		/* Enable L1 IRQ - clear mask bit */
+		mask = inb(mask_port) & ~bit;
+		outb(mask, mask_port);
+		restore_flags(flags);
+		return;
+	}
+   	DPRINTK("enable_bigsur_l1irq: Invalid IRQ %d\n", irq);	
+}
+
+
+/* Level 2 irq masks and registers for L2 decoding */
+/* Level2 bitmasks for each level 1 IRQ */
+const u32 bigsur_l2irq_mask[] = 
+    {0x40,0x80,0x08,0x01,0x01,0x3C,0x3E,0xFF,0x40,0x80,0x06,0x03};
+/* Level2 to ISR[n] map for each level 1 IRQ */
+const u32 bigsur_l2irq_reg[]  = 
+    {   2,   2,   3,   3,   1,   2,   1,   0,   1,   1,   3,   2};
+/* Level2 to Level 1 IRQ map */
+const u32 bigsur_l2_l1_map[]  = 
+    {7,7,7,7,7,7,7,7, 4,6,6,6,6,6,8,9, 11,11,5,5,5,5,0,1, 3,10,10,2,-1,-1,-1,-1};
+/* IRQ inactive level (high or low) */
+const u32 bigsur_l2_inactv_state[]  =   {0x00, 0xBE, 0xFC, 0xF7};
+ 
+/* CPLD external status and mask registers base and offsets */
+static const u32 isr_base = BIGSUR_IRQ0;
+static const u32 isr_offset = BIGSUR_IRQ0 - BIGSUR_IRQ1;
+static const u32 imr_base = BIGSUR_IMR0;
+static const u32 imr_offset = BIGSUR_IMR0 - BIGSUR_IMR1;
+
+#define REG_NUM(irq)  ((irq-BIGSUR_2NDLVL_IRQ_LOW)/8 )
+
+/* Level 2 IRQ routines */
+static void disable_bigsur_l2irq(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned char mask;
+	unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
+	unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
+
+    if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+   		DPRINTK("Disable L2 IRQ %d\n", irq);
+   		DIPRINTK(2,"disable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", 
+   			mask_port, bit);
+		save_and_cli(flags);
+
+		/* Disable L2 IRQ - set mask bit */
+		mask = inb(mask_port) | bit;
+		outb(mask, mask_port);
+		restore_flags(flags);
+		return;
+	}
+ 	DPRINTK("disable_bigsur_l2irq: Invalid IRQ %d\n", irq);	
+}
+
+static void enable_bigsur_l2irq(unsigned int irq)
+{
+	unsigned long flags;
+	unsigned char mask;
+	unsigned char bit = 1 << ((irq-BIGSUR_2NDLVL_IRQ_LOW)%8);
+	unsigned int mask_port = imr_base - REG_NUM(irq)*imr_offset;
+
+    if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {
+   		DPRINTK("Enable L2 IRQ %d\n", irq);
+   		DIPRINTK(2,"enable_bigsur_l2irq: IMR=0x%08x mask=0x%x\n", 
+   			mask_port, bit);
+		save_and_cli(flags);
+
+		/* Enable L2 IRQ - clear mask bit */
+		mask = inb(mask_port) & ~bit;
+		outb(mask, mask_port);
+		restore_flags(flags);
+		return;
+	}
+   	DPRINTK("enable_bigsur_l2irq: Invalid IRQ %d\n", irq);
+}
+
+static void mask_and_ack_bigsur(unsigned int irq)
+{
+   	DPRINTK("mask_and_ack_bigsur IRQ %d\n", irq);
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)	
+		disable_bigsur_l1irq(irq);
+	else
+		disable_bigsur_l2irq(irq);
+}
+
+static void end_bigsur_irq(unsigned int irq)
+{
+   	DPRINTK("end_bigsur_irq IRQ %d\n", irq);
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)	
+		enable_bigsur_l1irq(irq);
+	else
+		enable_bigsur_l2irq(irq);
+}
+
+static unsigned int startup_bigsur_irq(unsigned int irq)
+{ 
+	u8 mask;
+	u32 reg;
+
+   	DPRINTK("startup_bigsur_irq IRQ %d\n", irq);
+
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+		/* Enable the L1 IRQ */	
+		enable_bigsur_l1irq(irq);
+		/* Enable all L2 IRQs in this L1 IRQ */
+		mask = ~(bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW]);
+		reg = imr_base - bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW] * imr_offset;
+		mask &= inb(reg);
+		outb(mask,reg); 
+   		DIPRINTK(2,"startup_bigsur_irq: IMR=0x%08x mask=0x%x\n",reg,inb(reg));
+	}
+	else {
+		/* Enable the L2 IRQ - clear mask bit */
+		enable_bigsur_l2irq(irq);
+		/* Enable the L1 bit masking this L2 IRQ */
+		enable_bigsur_l1irq(bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW]);
+   		DIPRINTK(2,"startup_bigsur_irq: L1=%d L2=%d\n",
+   			bigsur_l2_l1_map[irq-BIGSUR_2NDLVL_IRQ_LOW],irq);
+	}
+	return 0;
+}
+
+static void shutdown_bigsur_irq(unsigned int irq)
+{
+   	DPRINTK("shutdown_bigsur_irq IRQ %d\n", irq);
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH)	
+		disable_bigsur_l1irq(irq);
+	else
+		disable_bigsur_l2irq(irq);
+}
+
+/* Define the IRQ structures for the L1 and L2 IRQ types */
+static struct hw_interrupt_type bigsur_l1irq_type = {
+	"BigSur-CPLD-Level1-IRQ",
+	startup_bigsur_irq,
+	shutdown_bigsur_irq,
+	enable_bigsur_l1irq,
+	disable_bigsur_l1irq,
+	mask_and_ack_bigsur,
+	end_bigsur_irq
+};
+
+static struct hw_interrupt_type bigsur_l2irq_type = {
+	"BigSur-CPLD-Level2-IRQ",
+	startup_bigsur_irq,
+	shutdown_bigsur_irq,
+	enable_bigsur_l2irq,
+	disable_bigsur_l2irq,
+	mask_and_ack_bigsur,
+	end_bigsur_irq
+};
+
+
+static void make_bigsur_l1isr(unsigned int irq) {
+
+	/* sanity check first */
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {	
+		/* save the handler in the main description table */
+		irq_desc[irq].handler = &bigsur_l1irq_type;
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = 0;
+		irq_desc[irq].depth = 1;
+
+		disable_bigsur_l1irq(irq);
+		return;
+	}
+   	DPRINTK("make_bigsur_l1isr: bad irq, %d\n", irq);
+	return;
+} 
+
+static void make_bigsur_l2isr(unsigned int irq) {
+
+	/* sanity check first */
+	if(irq >= BIGSUR_2NDLVL_IRQ_LOW && irq < BIGSUR_2NDLVL_IRQ_HIGH) {	
+		/* save the handler in the main description table */
+		irq_desc[irq].handler = &bigsur_l2irq_type;
+		irq_desc[irq].status = IRQ_DISABLED;
+		irq_desc[irq].action = 0;
+		irq_desc[irq].depth = 1;
+
+		disable_bigsur_l2irq(irq);
+		return;
+	}
+   	DPRINTK("make_bigsur_l2isr: bad irq, %d\n", irq);
+	return;
+} 
+
+/* The IRQ's will be decoded as follows: 
+ * If a level 2 handler exists and there is an unmasked active
+ * IRQ, the 2nd level handler will be called.
+ * If a level 2 handler does not exist for the active IRQ
+ * the 1st level handler will be called.
+ */ 
+
+int bigsur_irq_demux(int irq)
+{
+	int dmux_irq = irq;
+	u8 mask, actv_irqs;
+	u32 reg_num;
+
+   	DIPRINTK(3,"bigsur_irq_demux, irq=%d\n", irq);
+   	/* decode the 1st level IRQ */
+	if(irq >= BIGSUR_IRQ_LOW && irq < BIGSUR_IRQ_HIGH) {
+		/* Get corresponding L2 ISR bitmask and ISR number */
+		mask = bigsur_l2irq_mask[irq-BIGSUR_IRQ_LOW];
+		reg_num = bigsur_l2irq_reg[irq-BIGSUR_IRQ_LOW];
+		/* find the active IRQ's (XOR with inactive level)*/
+		actv_irqs = inb(isr_base-reg_num*isr_offset) ^ 
+					bigsur_l2_inactv_state[reg_num];
+		/* decode active IRQ's */
+		actv_irqs = actv_irqs & mask & ~(inb(imr_base-reg_num*imr_offset));
+		/* if NEZ then we have an active L2 IRQ */
+		if(actv_irqs) dmux_irq = ffz(~actv_irqs) + reg_num*8+BIGSUR_2NDLVL_IRQ_LOW;	
+   		/* if no 2nd level IRQ action, but has 1st level, use 1st level handler */
+		if(!irq_desc[dmux_irq].action && irq_desc[irq].action) 
+			dmux_irq = irq;
+   		DIPRINTK(1,"bigsur_irq_demux: irq=%d dmux_irq=%d mask=0x%04x reg=%d\n", 
+   			irq, dmux_irq, mask, reg_num);
+	}
+#ifdef CONFIG_HD64465
+	dmux_irq = hd64465_irq_demux(dmux_irq);
+#endif /* CONFIG_HD64465 */
+   	DIPRINTK(3,"bigsur_irq_demux, demux_irq=%d\n", dmux_irq);
+		
+	return dmux_irq;
+}
+
+/*===========================================================*/
+//		Big Sur Init Routines	
+/*===========================================================*/
+void __init init_bigsur_IRQ(void)
+{
+	int i;
+
+	if (!MACH_BIGSUR) return;
+
+	/* Create ISR's for Big Sur CPLD IRQ's */
+	/*==============================================================*/
+	for(i=BIGSUR_IRQ_LOW;i<BIGSUR_IRQ_HIGH;i++) 
+	 	make_bigsur_l1isr(i);
+
+	printk(KERN_INFO "Big Sur CPLD L1 interrupts %d to %d.\n",
+		BIGSUR_IRQ_LOW,BIGSUR_IRQ_HIGH);
+
+	for(i=BIGSUR_2NDLVL_IRQ_LOW;i<BIGSUR_2NDLVL_IRQ_HIGH;i++) 
+ 		make_bigsur_l2isr(i);
+
+	printk(KERN_INFO "Big Sur CPLD L2 interrupts %d to %d.\n",
+		BIGSUR_2NDLVL_IRQ_LOW,BIGSUR_2NDLVL_IRQ_HIGH);
+
+}
+
+int __init setup_bigsur(void)
+{
+	static int done = 0; /* run this only once */
+
+	if (!MACH_BIGSUR || done) return 0;
+	done = 1;
+
+	/* Mask all 2nd level IRQ's */
+	outb(-1,BIGSUR_IMR0);
+	outb(-1,BIGSUR_IMR1);
+	outb(-1,BIGSUR_IMR2);
+	outb(-1,BIGSUR_IMR3);
+
+	/* Mask 1st level interrupts */
+	outb(-1,BIGSUR_IRLMR0);
+	outb(-1,BIGSUR_IRLMR1);
+
+#if defined (CONFIG_HD64465) && defined (CONFIG_SERIAL) 
+	/* remap IO ports for first ISA serial port to HD64465 UART */
+	bigsur_port_map(0x3f8, 8, CONFIG_HD64465_IOBASE + 0x8000, 1);
+#endif /* CONFIG_HD64465 && CONFIG_SERIAL */
+	/* TODO: setup IDE registers */
+	bigsur_port_map(BIGSUR_IDECTL_IOPORT, 2, BIGSUR_ICTL, 8);
+	/* Setup the Ethernet port to BIGSUR_ETHER_IOPORT */
+	bigsur_port_map(BIGSUR_ETHER_IOPORT, 16, BIGSUR_ETHR+BIGSUR_ETHER_IOPORT, 0);
+	/* set page to 1 */
+	outw(1, BIGSUR_ETHR+0xe);
+	/* set the IO port to BIGSUR_ETHER_IOPORT */
+	outw(BIGSUR_ETHER_IOPORT<<3, BIGSUR_ETHR+0x2);
+
+    return 0;
+}
+
+module_init(setup_bigsur);
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_dc.c linux/arch/sh/kernel/setup_dc.c
--- v2.4.5/linux/arch/sh/kernel/setup_dc.c	Sun May 20 12:11:38 2001
+++ linux/arch/sh/kernel/setup_dc.c	Wed Jun 27 13:55:29 2001
@@ -1,5 +1,15 @@
-/*
- *	$Id: setup_dc.c,v 1.1 2001/04/01 15:02:00 yaegashi Exp $
+/* arch/sh/kernel/setup_dc.c
+ *
+ * Hardware support for the Sega Dreamcast.
+ *
+ * Copyright (c) 2001 M. R. Brown <mrbrown@linuxdc.org>
+ *
+ * This file is part of the LinuxDC project (www.linuxdc.org)
+ *
+ * Released under the terms of the GNU GPL v2.0.
+ * 
+ * This file originally bore the message:
+ *	$Id: setup_dc.c,v 1.5 2001/05/24 05:09:16 mrbrown Exp $
  *	SEGA Dreamcast support
  */
 
@@ -9,105 +19,167 @@
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/irq.h>
-#include <linux/pci.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/dc_sysasic.h>
 
-#define	GAPSPCI_REGS		0x01001400
-#define GAPSPCI_DMA_BASE	0x01840000
-#define GAPSPCI_DMA_SIZE	32768
-#define GAPSPCI_BBA_CONFIG	0x01001600
+int __init gapspci_init(void);
 
-#define	GAPSPCI_IRQ		11
-#define	GAPSPCI_INTC		0x005f6924
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 
-static int gapspci_dma_used;
+/* Dreamcast System ASIC Hardware Events -
+ 
+   The Dreamcast's System ASIC (located on the PowerVR2 chip) is responsible
+   for receiving hardware events from system peripherals and triggering an
+   SH7750 IRQ.  Hardware events can trigger IRQs 13, 11, or 9 depending on
+   which bits are set in the Event Mask Registers (EMRs).  When a hardware
+   event is triggered, it's corresponding bit in the Event Status Registers
+   (ESRs) is set, and that bit should be rewritten to the ESR to acknowledge
+   that event.
 
-static struct pci_bus *pci_root_bus;
+   There are three 32-bit ESRs located at 0xa05f8900 - 0xa05f6908.  Event
+   types can be found in include/asm-sh/dc_sysasic.h.  There are three groups
+   of EMRs that parallel the ESRs.  Each EMR group corresponds to an IRQ, so
+   0xa05f6910 - 0xa05f6918 triggers IRQ 13, 0xa05f6920 - 0xa05f6928 triggers
+   IRQ 11, and 0xa05f6930 - 0xa05f6938 triggers IRQ 9.
 
-static void disable_gapspci_irq(unsigned int irq)
-{
-	unsigned long flags;
-	unsigned long intc;
+   In the kernel, these events are mapped to virtual IRQs so that drivers can
+   respond to them as they would a normal interrupt.  In order to keep this
+   mapping simple, the events are mapped as:
 
-	save_and_cli(flags);
-	intc = inl(GAPSPCI_INTC);
-	intc &= ~(1<<3);
-	outl(intc, GAPSPCI_INTC);
-	restore_flags(flags);
-}
+   6900/6910 - Events  0-31, IRQ 13
+   6904/6924 - Events 32-63, IRQ 11
+   6908/6938 - Events 64-95, IRQ  9
 
+*/
 
-static void enable_gapspci_irq(unsigned int irq)
-{
-	unsigned long flags;
-	unsigned long intc;
+#define ESR_BASE 0x005f6900    /* Base event status register */
+#define EMR_BASE 0x005f6910    /* Base event mask register */
 
-	save_and_cli(flags);
-	intc = inl(GAPSPCI_INTC);
-	intc |= (1<<3);
-	outl(intc, GAPSPCI_INTC);
-	restore_flags(flags);
-}
+/* Helps us determine the EMR group that this event belongs to: 0 = 0x6910,
+   1 = 0x6920, 2 = 0x6930; also determine the event offset */
+#define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32)
+
+/* Return the hardware event's bit positon within the EMR/ESR */
+#define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31)
 
+/* For each of these *_irq routines, the IRQ passed in is the virtual IRQ
+   (logically mapped to the corresponding bit for the hardware event). */
 
-static void mask_and_ack_gapspci_irq(unsigned int irq)
+/* Disable the hardware event by masking its bit in its EMR */
+static inline void disable_systemasic_irq(unsigned int irq)
 {
-	unsigned long flags;
-	unsigned long intc;
+	__u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
+	__u32 mask;
+	mask = inl(emr);
+	mask &= ~(1 << EVENT_BIT(irq));
+	outl(mask, emr);
+}
 
-	save_and_cli(flags);
-	intc = inl(GAPSPCI_INTC);
-	intc &= ~(1<<3);
-	outl(intc, GAPSPCI_INTC);
-	restore_flags(flags);
+/* Enable the hardware event by setting its bit in its EMR */
+static inline void enable_systemasic_irq(unsigned int irq)
+{
+	__u32 emr = EMR_BASE + (LEVEL(irq) << 4) + (LEVEL(irq) << 2);
+	__u32 mask;
+	mask = inl(emr);
+	mask |= (1 << EVENT_BIT(irq));
+	outl(mask, emr);
 }
 
+/* Acknowledge a hardware event by writing its bit back to its ESR */
+static void ack_systemasic_irq(unsigned int irq)
+{
+	__u32 esr = ESR_BASE + (LEVEL(irq) << 2);
+	disable_systemasic_irq(irq);
+	outl((1 << EVENT_BIT(irq)), esr);
+}
 
-static void end_gapspci_irq(unsigned int irq)
+/* After a IRQ has been ack'd and responded to, it needs to be renabled */
+static void end_systemasic_irq(unsigned int irq)
 {
-	enable_gapspci_irq(irq);
+	enable_systemasic_irq(irq);
 }
 
+static unsigned int startup_systemasic_irq(unsigned int irq)
+{
+	enable_systemasic_irq(irq);
 
-static unsigned int startup_gapspci_irq(unsigned int irq)
-{ 
-	enable_gapspci_irq(irq);
 	return 0;
 }
 
-
-static void shutdown_gapspci_irq(unsigned int irq)
+static void shutdown_systemasic_irq(unsigned int irq)
 {
-	disable_gapspci_irq(irq);
+	disable_systemasic_irq(irq);
 }
 
-
-static struct hw_interrupt_type gapspci_irq_type = {
-	"GAPSPCI-IRQ",
-	startup_gapspci_irq,
-	shutdown_gapspci_irq,
-	enable_gapspci_irq,
-	disable_gapspci_irq,
-	mask_and_ack_gapspci_irq,
-	end_gapspci_irq
+static struct hw_interrupt_type systemasic_int = {
+	typename:       "System ASIC",
+	startup:        startup_systemasic_irq,
+	shutdown:       shutdown_systemasic_irq,
+	enable:         enable_systemasic_irq,
+	disable:        disable_systemasic_irq,
+	ack:            ack_systemasic_irq,
+	end:            end_systemasic_irq,
 };
 
-
-static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin)
+/*
+ * Map the hardware event indicated by the processor IRQ to a virtual IRQ.
+ */
+int systemasic_irq_demux(int irq)
 {
-	return PCI_SLOT(dev->devfn);
-}
+	__u32 emr, esr, status, level;
+	__u32 j, bit;
 
-static int __init map_od_irq(struct pci_dev *dev, u8 slot, u8 pin)
-{
-	return GAPSPCI_IRQ;
+	switch (irq) {
+		case 13:
+			level = 0;
+			break;
+		case 11:
+			level = 1;
+			break;
+		case  9:
+			level = 2;
+			break;
+		default:
+			return irq;
+	}
+	emr = EMR_BASE + (level << 4) + (level << 2);
+	esr = ESR_BASE + (level << 2);
+
+	/* Mask the ESR to filter any spurious, unwanted interrtupts */
+	status = inl(esr);
+	status &= inl(emr);
+
+	/* Now scan and find the first set bit as the event to map */
+	for (bit = 1, j = 0; j < 32; bit <<= 1, j++) {
+		if (status & bit) {
+			irq = HW_EVENT_IRQ_BASE + j + (level << 5);
+			return irq;
+		}
+	}
+
+	/* Not reached */
+	return irq;
 }
 
 int __init setup_dreamcast(void)
 {
+	int i;
+
+	/* Mask all hardware events */
+	/* XXX */
+
+	/* Acknowledge any previous events */
+	/* XXX */
+
+	/* Assign all virtual IRQs to the System ASIC int. handler */
+	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
+		irq_desc[i].handler = &systemasic_int;
+
+#ifdef CONFIG_PCI
 	gapspci_init();
+#endif
 
 	printk(KERN_INFO "SEGA Dreamcast support.\n");
 #if 0
@@ -128,232 +200,5 @@
  *	PCR: 0x0000
  */
 #endif
-	return 0;
-}
-
-
-/*
- *	Dreamcast PCI: Supports SEGA Broadband Adaptor only.
- */
-
-#define BBA_SELECTED(dev) (dev->bus->number==0 && dev->devfn==0)
-
-static int gapspci_read_config_byte(struct pci_dev *dev, int where,
-                                    u8 * val)
-{
-	if (BBA_SELECTED(dev))
-		*val = inb(GAPSPCI_BBA_CONFIG+where);
-	else
-                *val = 0xff;
-
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int gapspci_read_config_word(struct pci_dev *dev, int where,
-                                    u16 * val)
-{
-        if (BBA_SELECTED(dev))
-		*val = inw(GAPSPCI_BBA_CONFIG+where);
-	else
-                *val = 0xffff;
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-static int gapspci_read_config_dword(struct pci_dev *dev, int where,
-                                     u32 * val)
-{
-        if (BBA_SELECTED(dev))
-		*val = inl(GAPSPCI_BBA_CONFIG+where);
-	else
-                *val = 0xffffffff;
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-static int gapspci_write_config_byte(struct pci_dev *dev, int where,
-                                     u8 val)
-{
-        if (BBA_SELECTED(dev))
-		outb(val, GAPSPCI_BBA_CONFIG+where);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int gapspci_write_config_word(struct pci_dev *dev, int where,
-                                     u16 val)
-{
-        if (BBA_SELECTED(dev))
-		outw(val, GAPSPCI_BBA_CONFIG+where);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-static int gapspci_write_config_dword(struct pci_dev *dev, int where,
-                                      u32 val)
-{
-        if (BBA_SELECTED(dev))
-		outl(val, GAPSPCI_BBA_CONFIG+where);
-
-        return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops pci_config_ops = {
-        gapspci_read_config_byte,
-        gapspci_read_config_word,
-        gapspci_read_config_dword,
-        gapspci_write_config_byte,
-        gapspci_write_config_word,
-        gapspci_write_config_dword
-};
-
-
-void pcibios_align_resource(void *data, struct resource *res,
-			    unsigned long size)
-{
-}
-
-
-void __init pcibios_update_irq(struct pci_dev *dev, int irq)
-{
-}
-
-
-void __init pcibios_update_resource(struct pci_dev *dev, struct resource *root,
-			     struct resource *res, int resource)
-{
-}
-
-
-int pcibios_enable_device(struct pci_dev *dev)
-{
-
-	u16 cmd, old_cmd;
-	int idx;
-	struct resource *r;
-
-	pci_read_config_word(dev, PCI_COMMAND, &cmd);
-	old_cmd = cmd;
-	for (idx = 0; idx < 6; idx++) {
-		r = dev->resource + idx;
-		if (!r->start && r->end) {
-			printk(KERN_ERR
-			       "PCI: Device %s not available because"
-			       " of resource collisions\n",
-			       dev->slot_name);
-			return -EINVAL;
-		}
-		if (r->flags & IORESOURCE_IO)
-			cmd |= PCI_COMMAND_IO;
-		if (r->flags & IORESOURCE_MEM)
-			cmd |= PCI_COMMAND_MEMORY;
-	}
-	if (cmd != old_cmd) {
-		printk("PCI: enabling device %s (%04x -> %04x)\n",
-		       dev->slot_name, old_cmd, cmd);
-		pci_write_config_word(dev, PCI_COMMAND, cmd);
-	}
-	return 0;
-
-}
-
-
-void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
-			   dma_addr_t * dma_handle)
-{
-	unsigned long buf;
-
-	if (gapspci_dma_used+size > GAPSPCI_DMA_SIZE)
-		return NULL;
-
-	buf = GAPSPCI_DMA_BASE+gapspci_dma_used;
-
-	gapspci_dma_used = PAGE_ALIGN(gapspci_dma_used+size);
-	
-	printk("pci_alloc_consistent: %d bytes at 0x%08x\n", size, buf);
-
-	*dma_handle = (dma_addr_t)buf;
-
-	return (void *)P2SEGADDR(buf);
-}
-
-
-void pci_free_consistent(struct pci_dev *hwdev, size_t size,
-			 void *vaddr, dma_addr_t dma_handle)
-{
-}
-
-
-void __init
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}                                                                                
-
-void __init pcibios_fixup_bus(struct pci_bus *bus)
-{
-	struct list_head *ln;
-	struct pci_dev *dev;
-
-	for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
-		dev = pci_dev_b(ln);
-		if (!BBA_SELECTED(dev)) continue;
-
-		printk("PCI: MMIO fixup to %s\n", dev->name);
-		dev->resource[1].start=0x01001700;
-		dev->resource[1].end=0x010017ff;
-	}
-}
-
-
-void __init dreamcast_pcibios_init(void)
-{
-	pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL);
-	/* pci_assign_unassigned_resources(); */
-	pci_fixup_irqs(no_swizzle, map_od_irq);
-}
-
-
-static __init int gapspci_init(void)
-{
-	int i;
-	char idbuf[16];
-
-	for(i=0; i<16; i++)
-		idbuf[i]=inb(GAPSPCI_REGS+i);
-
-	if(strncmp(idbuf, "GAPSPCI_BRIDGE_2", 16))
-		return -1;
-
-	outl(0x5a14a501, GAPSPCI_REGS+0x18);
-
-	for(i=0; i<1000000; i++);
-
-	if(inl(GAPSPCI_REGS+0x18)!=1)
-		return -1;
-
-	outl(0x01000000, GAPSPCI_REGS+0x20);
-	outl(0x01000000, GAPSPCI_REGS+0x24);
-
-	outl(GAPSPCI_DMA_BASE, GAPSPCI_REGS+0x28);
-	outl(GAPSPCI_DMA_BASE+GAPSPCI_DMA_SIZE, GAPSPCI_REGS+0x2c);
-
-	outl(1, GAPSPCI_REGS+0x14);
-	outl(1, GAPSPCI_REGS+0x34);
-
-	gapspci_dma_used=0;
-
-	/*  */
-	irq_desc[GAPSPCI_IRQ].handler = &gapspci_irq_type;
-
-	/* Setting Broadband Adapter */
-	outw(0xf900, GAPSPCI_BBA_CONFIG+0x06);
-	outl(0x00000000, GAPSPCI_BBA_CONFIG+0x30);
-	outb(0x00, GAPSPCI_BBA_CONFIG+0x3c);
-	outb(0xf0, GAPSPCI_BBA_CONFIG+0x0d);
-	outw(0x0006, GAPSPCI_BBA_CONFIG+0x04);
-	outl(0x00002001, GAPSPCI_BBA_CONFIG+0x10);
-	outl(0x01000000, GAPSPCI_BBA_CONFIG+0x14);
-
 	return 0;
 }
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_od.c linux/arch/sh/kernel/setup_od.c
--- v2.4.5/linux/arch/sh/kernel/setup_od.c	Mon Jun 19 17:59:37 2000
+++ linux/arch/sh/kernel/setup_od.c	Wed Dec 31 16:00:00 1969
@@ -1,35 +0,0 @@
-/* $Id: setup_od.c,v 1.1 2000/06/14 09:35:59 stuart_menefy Exp $
- *
- * arch/sh/kernel/setup_od.c
- *
- * Copyright (C) 2000  Stuart Menefy
- *
- * STMicroelectronics Overdrive Support.
- *
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-
-/*
- * Initialize the board
- */
-int __init setup_od(void)
-{
-	/* Enable RS232 receive buffers */
-	volatile int* p = (volatile int*)0xa3000000;
-
-#if defined(CONFIG_SH_ORION)
-	*p=1;
-#elif defined(CONFIG_SH_OVERDRIVE)
-	*p=0x1e;
-#else
-#error Illegal configuration
-#endif
-
-	printk(KERN_INFO "STMicroelectronics Overdrive Setup...done\n");
-	return 0;
-}
-
-module_init(setup_od);
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/setup_sh2000.c linux/arch/sh/kernel/setup_sh2000.c
--- v2.4.5/linux/arch/sh/kernel/setup_sh2000.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/kernel/setup_sh2000.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,95 @@
+/*
+ * linux/arch/sh/kernel/setup_sh2000.c
+ *
+ * Copyright (C) 2001  SUGIOKA Tochinobu
+ *
+ * SH-2000 Support.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/io_generic.h>
+#include <asm/machvec.h>
+#include <asm/machvec_init.h>
+#include <asm/rtc.h>
+
+#define CF_CIS_BASE	0xb4200000
+
+#define PORT_PECR	0xa4000108
+#define PORT_PHCR	0xa400010E
+#define	PORT_ICR1	0xa4000010
+#define	PORT_IRR0	0xa4000004
+
+/*
+ * Initialize the board
+ */
+int __init setup_sh2000(void)
+{
+	/* XXX: RTC setting comes here */
+
+	/* These should be done by BIOS/IPL ... */
+	/* Enable nCE2A, nCE2B output */
+	ctrl_outw(ctrl_inw(PORT_PECR) & ~0xf00, PORT_PECR);
+	/* Enable the Compact Flash card, and set the level interrupt */
+	ctrl_outw(0x0042, CF_CIS_BASE+0x0200);
+	/* Enable interrupt */
+	ctrl_outw(ctrl_inw(PORT_PHCR) & ~0x03f3, PORT_PHCR);
+	ctrl_outw(1, PORT_ICR1);
+	ctrl_outw(ctrl_inw(PORT_IRR0) & ~0xff3f, PORT_IRR0);
+	printk(KERN_INFO "SH-2000 Setup...done\n");
+	return 0;
+}
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_sh2000 __initmv = {
+	mv_name:		"sh2000",
+
+	mv_nr_irqs:		80,
+
+	mv_inb:			generic_inb,
+	mv_inw:			generic_inw,
+	mv_inl:			generic_inl,
+	mv_outb:		generic_outb,
+	mv_outw:		generic_outw,
+	mv_outl:		generic_outl,
+
+	mv_inb_p:		generic_inb_p,
+	mv_inw_p:		generic_inw_p,
+	mv_inl_p:		generic_inl_p,
+	mv_outb_p:		generic_outb_p,
+	mv_outw_p:		generic_outw_p,
+	mv_outl_p:		generic_outl_p,
+
+	mv_insb:		generic_insb,
+	mv_insw:		generic_insw,
+	mv_insl:		generic_insl,
+	mv_outsb:		generic_outsb,
+	mv_outsw:		generic_outsw,
+	mv_outsl:		generic_outsl,
+
+	mv_readb:		generic_readb,
+	mv_readw:		generic_readw,
+	mv_readl:		generic_readl,
+	mv_writeb:		generic_writeb,
+	mv_writew:		generic_writew,
+	mv_writel:		generic_writel,
+
+	mv_init_arch:		setup_sh2000,
+
+	mv_isa_port2addr:	sh2000_isa_port2addr,
+
+	mv_ioremap:		generic_ioremap,
+	mv_iounmap:		generic_iounmap,
+
+	mv_rtc_gettimeofday:	sh_rtc_gettimeofday,
+	mv_rtc_settimeofday:	sh_rtc_settimeofday,
+
+	mv_hw_sh2000:		1,
+};
+ALIAS_MV(sh2000)
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/sh_ksyms.c linux/arch/sh/kernel/sh_ksyms.c
--- v2.4.5/linux/arch/sh/kernel/sh_ksyms.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/sh_ksyms.c	Wed Jun 27 13:55:29 2001
@@ -18,6 +18,7 @@
 #include <asm/hardirq.h>
 #include <asm/delay.h>
 #include <asm/pgalloc.h>
+#include <asm/pci.h>
 #include <linux/irq.h>
 
 extern void dump_thread(struct pt_regs *, struct user *);
@@ -44,14 +45,25 @@
 EXPORT_SYMBOL(strpbrk);
 EXPORT_SYMBOL(strstr);
 EXPORT_SYMBOL(strlen);
+EXPORT_SYMBOL(strnlen);
 EXPORT_SYMBOL(strchr);
 EXPORT_SYMBOL(strcat);
 EXPORT_SYMBOL(strncat);
 
+/* PCI exports */
+#ifdef CONFIG_PCI
+EXPORT_SYMBOL(pci_alloc_consistent);
+EXPORT_SYMBOL(pci_free_consistent);
+EXPORT_SYMBOL(pcibios_penalize_isa_irq);
+#endif
+
 /* mem exports */
 EXPORT_SYMBOL(memchr);
 EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memcpy_toio);
 EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memset_io);
 EXPORT_SYMBOL(memmove);
 EXPORT_SYMBOL(memcmp);
 
@@ -63,20 +75,32 @@
 
 EXPORT_SYMBOL(get_vm_area);
 
+/* semaphore exports */
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__const_udelay);
+
 #define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL_NOVERS(name)
  
 /* These symbols are generated by the compiler itself */
 DECLARE_EXPORT(__udivsi3);
 DECLARE_EXPORT(__sdivsi3);
+DECLARE_EXPORT(__ashrdi3);
+DECLARE_EXPORT(__ashldi3);
+DECLARE_EXPORT(__lshrdi3);
+DECLARE_EXPORT(__movstr);
 
 #ifdef __SH4__
  
 DECLARE_EXPORT(__movstr_i4_even);
 DECLARE_EXPORT(__movstr_i4_odd);
-DECLARE_EXPORT(__ashrdi3);
-DECLARE_EXPORT(__ashldi3);
 
 /* needed by some modules */
+EXPORT_SYMBOL(flush_cache_all);
+EXPORT_SYMBOL(flush_cache_range);
 EXPORT_SYMBOL(flush_dcache_page);
 #endif
 EXPORT_SYMBOL(flush_tlb_page);
diff -u --recursive --new-file v2.4.5/linux/arch/sh/kernel/time.c linux/arch/sh/kernel/time.c
--- v2.4.5/linux/arch/sh/kernel/time.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/kernel/time.c	Wed Jun 27 13:55:29 2001
@@ -64,7 +64,11 @@
 #define CCN_PVR_CHIP_MASK  0xff
 #define CCN_PVR_CHIP_ST40STB1 0x4
 
-#endif
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+#define CLOCKGEN_MEMCLKCR 0xbb040038
+#define MEMCLKCR_RATIO_MASK 0x7
+#endif /* CONFIG_CPU_SUBTYPE_ST40STB1 */
+#endif /* __sh3__ or __SH4__ */
 
 extern rwlock_t xtime_lock;
 extern unsigned long wall_jiffies;
@@ -285,6 +289,9 @@
 void __init time_init(void)
 {
 	unsigned int cpu_clock, master_clock, bus_clock, module_clock;
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+	unsigned int memory_clock;
+#endif
 	unsigned int timer_freq;
 	unsigned short frqcr, ifc, pfc, bfc;
 	unsigned long interval;
@@ -335,23 +342,35 @@
 		{ 0x123, {{1,4}, {1,4}, {1,8}}},
 		{ 0x16C, {{1,4}, {1,8}, {1,8}}},
 	};
+
+	struct memclk_data {
+		unsigned char multiplier;
+		unsigned char divisor;
+	};
+	static struct memclk_data st40_memclk_table[8] = {
+		{1,1},	// 000
+		{1,2},	// 001
+		{1,3},	// 010
+		{2,3},	// 011
+		{1,4},	// 100
+		{1,6},	// 101
+		{1,8},	// 110
+		{1,8}	// 111
+	};
 #endif
 #endif
 
-#if defined(CONFIG_SH_DREAMCAST)
-	xtime.tv_sec = 0;
-	xtime.tv_usec = 0;
-#else
-	rtc_gettimeofday(&xtime);
-#endif
+	if (MACH_DREAMCAST)
+		xtime.tv_sec = xtime.tv_usec = 0;
+	else
+		rtc_gettimeofday(&xtime);
 
 	setup_irq(TIMER_IRQ, &irq0);
 
-#if defined(CONFIG_SH_DREAMCAST)
-	timer_freq = 50*1000*1000/4;
-#else
-	timer_freq = get_timer_frequency();
-#endif
+	if (MACH_DREAMCAST)
+		timer_freq = 50*1000*1000/4;
+	else
+		timer_freq = get_timer_frequency();
 
 	module_clock = timer_freq * 4;
 
@@ -386,6 +405,8 @@
 			/* Unfortunatly the STB1 FRQCR values are different from the 7750 ones */
 			struct frqcr_data *d;
 			int a;
+			unsigned long memclkcr;
+			struct memclk_data *e;
 
 			for (a=0; a<ARRAY_SIZE(st40_frqcr_table); a++) {
 				d = &st40_frqcr_table[a];
@@ -397,13 +418,18 @@
 				printk("ERROR: Unrecognised FRQCR value, using default multipliers\n");
 			}
 
-			printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Periph: %d/%d\n",
+			memclkcr = ctrl_inl(CLOCKGEN_MEMCLKCR);
+			e = &st40_memclk_table[memclkcr & MEMCLKCR_RATIO_MASK];
+
+			printk("Clock multipliers: CPU: %d/%d Bus: %d/%d Mem: %d/%d Periph: %d/%d\n",
 			       d->factor[0].multiplier, d->factor[0].divisor,
 			       d->factor[1].multiplier, d->factor[1].divisor,
+			       e->multiplier,           e->divisor,
 			       d->factor[2].multiplier, d->factor[2].divisor);
 			
 			master_clock = module_clock * d->factor[2].divisor    / d->factor[2].multiplier;
 			bus_clock    = master_clock * d->factor[1].multiplier / d->factor[1].divisor;
+			memory_clock = master_clock * e->multiplier           / e->divisor;
 			cpu_clock    = master_clock * d->factor[0].multiplier / d->factor[0].divisor;
 			goto skip_calc;
 		} else
@@ -418,11 +444,17 @@
 	master_clock = module_clock * pfc;
 	bus_clock = master_clock / bfc;
 	cpu_clock = master_clock / ifc;
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
  skip_calc:
+#endif
 	printk("CPU clock: %d.%02dMHz\n",
 	       (cpu_clock / 1000000), (cpu_clock % 1000000)/10000);
 	printk("Bus clock: %d.%02dMHz\n",
 	       (bus_clock/1000000), (bus_clock % 1000000)/10000);
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+	printk("Memory clock: %d.%02dMHz\n",
+	       (memory_clock/1000000), (memory_clock % 1000000)/10000);
+#endif
 	printk("Module clock: %d.%02dMHz\n",
 	       (module_clock/1000000), (module_clock % 1000000)/10000);
 	interval = (module_clock/4 + HZ/2) / HZ;
@@ -432,6 +464,9 @@
 	current_cpu_data.cpu_clock    = cpu_clock;
 	current_cpu_data.master_clock = master_clock;
 	current_cpu_data.bus_clock    = bus_clock;
+#ifdef CONFIG_CPU_SUBTYPE_ST40STB1
+	current_cpu_data.memory_clock = memory_clock;
+#endif
 	current_cpu_data.module_clock = module_clock;
 
 	/* Start TMU0 */
diff -u --recursive --new-file v2.4.5/linux/arch/sh/mm/cache.c linux/arch/sh/mm/cache.c
--- v2.4.5/linux/arch/sh/mm/cache.c	Sun May 20 12:11:38 2001
+++ linux/arch/sh/mm/cache.c	Wed Jun 27 13:55:29 2001
@@ -151,7 +151,8 @@
 #elif defined(__SH4__)
 #ifdef CONFIG_CPU_SUBTYPE_ST40STB1
 	cpu_data->type = CPU_ST40STB1;
-#elif defined(CONFIG_CPU_SUBTYPE_SH7750)
+#elif defined(CONFIG_CPU_SUBTYPE_SH7750) || \
+      defined(CONFIG_CPU_SUBTYPE_SH7751)
 	cpu_data->type = CPU_SH7750;
 #else
 #error Unknown SH4 CPU type
diff -u --recursive --new-file v2.4.5/linux/arch/sh/mm/fault.c linux/arch/sh/mm/fault.c
--- v2.4.5/linux/arch/sh/mm/fault.c	Mon Mar 19 12:35:10 2001
+++ linux/arch/sh/mm/fault.c	Wed Jun 27 13:55:29 2001
@@ -281,11 +281,12 @@
 {
 	unsigned long flags;
 	unsigned long pteval;
-	unsigned long pteaddr;
+	unsigned long vpn;
+#if defined(__SH4__)
 	unsigned long ptea;
+#endif
 
 	save_and_cli(flags);
-
 #if defined(__SH4__)
 	if (pte_shared(pte)) {
 		struct page *pg;
@@ -305,13 +306,13 @@
 	}
 
 	/* Set PTEH register */
-	pteaddr = (address & MMU_VPN_MASK) | get_asid();
-	ctrl_outl(pteaddr, MMU_PTEH);
+	vpn = (address & MMU_VPN_MASK) | get_asid();
+	ctrl_outl(vpn, MMU_PTEH);
 
-	/* Set PTEA register */
-	/* TODO: make this look less hacky */
 	pteval = pte_val(pte);
 #if defined(__SH4__)
+	/* Set PTEA register */
+	/* TODO: make this look less hacky */
 	ptea = ((pteval >> 28) & 0xe) | (pteval & 0x1);
 	ctrl_outl(ptea, MMU_PTEA);
 #endif
@@ -341,9 +342,9 @@
 	data = (page & 0xfffe0000) | asid; /* VALID bit is off */
 	ctrl_outl(data, addr);
 #elif defined(__SH4__)
-	jump_to_P2();
 	addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT;
 	data = page | asid; /* VALID bit is off */
+	jump_to_P2();
 	ctrl_outl(data, addr);
 	back_to_P1();
 #endif
@@ -352,27 +353,34 @@
 #if defined(__SH4__)
 static void __flush_tlb_phys(unsigned long phys)
 {
-	int i;
-	unsigned long addr, data;
+	unsigned long addr, data, pte;
 
-	jump_to_P2();
-	for (i = 0; i < MMU_UTLB_ENTRIES; i++) {
-		addr = MMU_UTLB_DATA_ARRAY | (i<<MMU_U_ENTRY_SHIFT);
+	pte = phys | MMU_UTLB_VALID;
+	for (addr = MMU_UTLB_DATA_ARRAY;
+	     addr < MMU_UTLB_DATA_ARRAY+(MMU_UTLB_ENTRIES<<MMU_U_ENTRY_SHIFT);
+	     addr += (1<<MMU_U_ENTRY_SHIFT)) {
 		data = ctrl_inl(addr);
-		if ((data & MMU_UTLB_VALID) && (data&PAGE_MASK) == phys) {
+		if ((data & (MMU_UTLB_VALID|PAGE_MASK)) == pte) {
 			data &= ~MMU_UTLB_VALID;
+			jump_to_P2();
 			ctrl_outl(data, addr);
+			back_to_P1();
+			break;
 		}
 	}
-	for (i = 0; i < MMU_ITLB_ENTRIES; i++) {
-		addr = MMU_ITLB_DATA_ARRAY | (i<<MMU_I_ENTRY_SHIFT);
+	pte = phys | MMU_ITLB_VALID;
+	for (addr = MMU_ITLB_DATA_ARRAY;
+	     addr < MMU_ITLB_DATA_ARRAY+(MMU_ITLB_ENTRIES<<MMU_I_ENTRY_SHIFT);
+	     addr += (1<<MMU_I_ENTRY_SHIFT)) {
 		data = ctrl_inl(addr);
-		if ((data & MMU_ITLB_VALID) && (data&PAGE_MASK) == phys) {
+		if ((data & (MMU_ITLB_VALID|PAGE_MASK)) == pte) {
 			data &= ~MMU_ITLB_VALID;
+			jump_to_P2();
 			ctrl_outl(data, addr);
+			back_to_P1();
+			break;
 		}
 	}
-	back_to_P1();
 }
 #endif
 
diff -u --recursive --new-file v2.4.5/linux/arch/sh/mm/init.c linux/arch/sh/mm/init.c
--- v2.4.5/linux/arch/sh/mm/init.c	Wed Apr 11 21:24:52 2001
+++ linux/arch/sh/mm/init.c	Wed Jun 27 13:55:29 2001
@@ -100,7 +100,7 @@
 extern char _text, _etext, _edata, __bss_start, _end;
 extern char __init_begin, __init_end;
 
-pgd_t swapper_pg_dir[1024];
+pgd_t swapper_pg_dir[PTRS_PER_PGD];
 
 /* It'd be good if these lines were in the standard header file. */
 #define START_PFN	(NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT)
@@ -120,7 +120,7 @@
 	/* We don't need kernel mapping as hardware support that. */
 	pg_dir = swapper_pg_dir;
 
-	for (i=0; i < USER_PTRS_PER_PGD*2; i++)
+	for (i=0; i < PTRS_PER_PGD; i++)
 		pgd_val(pg_dir[i]) = 0;
 
 	/* Enable MMU */
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/Makefile linux/arch/sh/stboards/Makefile
--- v2.4.5/linux/arch/sh/stboards/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/Makefile	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,15 @@
+#
+# Makefile for STMicroelectronics board specific parts of the kernel
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+
+all: stboards.o
+O_TARGET := stboards.o
+obj-y := irq.o setup.o mach.o led.o
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/harp.h linux/arch/sh/stboards/harp.h
--- v2.4.5/linux/arch/sh/stboards/harp.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/harp.h	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,43 @@
+/* 
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Defintions applicable to the STMicroelectronics ST40STB1 HARP and
+ * compatible boards.
+ */
+
+#if defined(CONFIG_SH_STB1_HARP)
+
+#define EPLD_BASE     0xa0800000
+
+#define EPLD_LED      (EPLD_BASE+0x000c0000)
+#define EPLD_INTSTAT0 (EPLD_BASE+0x00200000)
+#define EPLD_INTSTAT1 (EPLD_BASE+0x00240000)
+#define EPLD_INTMASK0 (EPLD_BASE+0x00280000)
+#define EPLD_INTMASK1 (EPLD_BASE+0x002c0000)
+#define EPLD_PAGEADDR (EPLD_BASE+0x00300000)
+#define EPLD_REVID1   (EPLD_BASE+0x00380000)
+#define EPLD_REVID2   (EPLD_BASE+0x003c0000)
+
+#define EPLD_LED_ON  1
+#define EPLD_LED_OFF 0
+
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+
+#define EPLD_BASE     0xa7000000
+
+#define EPLD_REVID    (EPLD_BASE+0x00000000)
+#define EPLD_LED      (EPLD_BASE+0x00040000)
+#define EPLD_INTMASK0 (EPLD_BASE+0x001c0000)
+#define EPLD_INTMASK1 (EPLD_BASE+0x00200000)
+#define EPLD_INTSTAT0 (EPLD_BASE+0x00240000)
+#define EPLD_INTSTAT1 (EPLD_BASE+0x00280000)
+
+#define EPLD_LED_ON  0
+#define EPLD_LED_OFF 1
+
+#else
+#error Unknown board
+#endif
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/irq.c linux/arch/sh/stboards/irq.c
--- v2.4.5/linux/arch/sh/stboards/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/irq.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,149 @@
+/* 
+ * Copyright (C) 2000 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Looks after interrupts on the HARP board.
+ *
+ * Bases on the IPR irq system
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include "harp.h"
+
+
+#define NUM_EXTERNAL_IRQS 16
+
+// Early versions of the STB1 Overdrive required this nasty frig
+//#define INVERT_INTMASK_WRITES
+
+static void enable_harp_irq(unsigned int irq);
+static void disable_harp_irq(unsigned int irq);
+
+/* shutdown is same as "disable" */
+#define shutdown_harp_irq disable_harp_irq
+
+static void mask_and_ack_harp(unsigned int);
+static void end_harp_irq(unsigned int irq);
+
+static unsigned int startup_harp_irq(unsigned int irq)
+{
+	enable_harp_irq(irq);
+	return 0;		/* never anything pending */
+}
+
+static struct hw_interrupt_type harp_irq_type = {
+	"Harp-IRQ",
+	startup_harp_irq,
+	shutdown_harp_irq,
+	enable_harp_irq,
+	disable_harp_irq,
+	mask_and_ack_harp,
+	end_harp_irq
+};
+
+static void disable_harp_irq(unsigned int irq)
+{
+	unsigned val, flags;
+	unsigned maskReg;
+	unsigned mask;
+	int pri;
+
+	if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+		return;
+
+	pri = 15 - irq;
+
+	if (pri < 8) {
+		maskReg = EPLD_INTMASK0;
+	} else {
+		maskReg = EPLD_INTMASK1;
+		pri -= 8;
+	}
+
+	save_and_cli(flags);
+	mask = ctrl_inl(maskReg);
+	mask &= (~(1 << pri));
+#if defined(INVERT_INTMASK_WRITES)
+	mask ^= 0xff;
+#endif
+	ctrl_outl(mask, maskReg);
+	restore_flags(flags);
+}
+
+static void enable_harp_irq(unsigned int irq)
+{
+	unsigned flags;
+	unsigned maskReg;
+	unsigned mask;
+	int pri;
+
+	if (irq < 0 || irq >= NUM_EXTERNAL_IRQS)
+		return;
+
+	pri = 15 - irq;
+
+	if (pri < 8) {
+		maskReg = EPLD_INTMASK0;
+	} else {
+		maskReg = EPLD_INTMASK1;
+		pri -= 8;
+	}
+
+	save_and_cli(flags);
+	mask = ctrl_inl(maskReg);
+
+
+	mask |= (1 << pri);
+
+#if defined(INVERT_INTMASK_WRITES)
+	mask ^= 0xff;
+#endif
+	ctrl_outl(mask, maskReg);
+
+	restore_flags(flags);
+}
+
+/* This functions sets the desired irq handler to be an overdrive type */
+static void __init make_harp_irq(unsigned int irq)
+{
+	disable_irq_nosync(irq);
+	irq_desc[irq].handler = &harp_irq_type;
+	disable_harp_irq(irq);
+}
+
+static void mask_and_ack_harp(unsigned int irq)
+{
+	disable_harp_irq(irq);
+}
+
+static void end_harp_irq(unsigned int irq)
+{
+	enable_harp_irq(irq);
+}
+
+void __init init_harp_irq(void)
+{
+	int i;
+
+#if !defined(INVERT_INTMASK_WRITES)
+	// On the harp these are set to enable an interrupt
+	ctrl_outl(0x00, EPLD_INTMASK0);
+	ctrl_outl(0x00, EPLD_INTMASK1);
+#else
+	// On the Overdrive the data is inverted before being stored in the reg
+	ctrl_outl(0xff, EPLD_INTMASK0);
+	ctrl_outl(0xff, EPLD_INTMASK1);
+#endif
+
+	for (i = 0; i < NUM_EXTERNAL_IRQS; i++) {
+		make_harp_irq(i);
+	}
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/led.c linux/arch/sh/stboards/led.c
--- v2.4.5/linux/arch/sh/stboards/led.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/led.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/sh/stboards/led.c
+ *
+ * Copyright (C) 2000 Stuart Menefy <stuart.menefy@st.com>
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * This file contains ST40STB1 HARP and compatible code.
+ */
+
+#include <linux/config.h>
+#include <asm/io.h>
+#include "harp.h"
+
+/* Harp: Flash LD10 (front pannel) connected to EPLD (IC8) */
+/* Overdrive: Flash LD1 (front panel) connected to EPLD (IC4) */
+/* Works for HARP and overdrive */
+static void mach_led(int position, int value)
+{
+	if (value) {
+		ctrl_outl(EPLD_LED_ON, EPLD_LED);
+	} else {
+		ctrl_outl(EPLD_LED_OFF, EPLD_LED);
+	}
+}
+
+#ifdef CONFIG_HEARTBEAT
+
+#include <linux/sched.h>
+
+/* acts like an actual heart beat -- ie thump-thump-pause... */
+void heartbeat_harp(void)
+{
+	static unsigned cnt = 0, period = 0, dist = 0;
+
+	if (cnt == 0 || cnt == dist)
+		mach_led( -1, 1);
+	else if (cnt == 7 || cnt == dist+7)
+		mach_led( -1, 0);
+
+	if (++cnt > period) {
+		cnt = 0;
+		/* The hyperbolic function below modifies the heartbeat period
+		 * length in dependency of the current (5min) load. It goes
+		 * through the points f(0)=126, f(1)=86, f(5)=51,
+		 * f(inf)->30. */
+		period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+		dist = period / 4;
+	}
+}
+#endif
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/mach.c linux/arch/sh/stboards/mach.c
--- v2.4.5/linux/arch/sh/stboards/mach.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/mach.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/sh/stboards/mach.c
+ *
+ * Copyright (C) 2000 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * Machine vector for the STMicroelectronics STB1 HARP and compatible boards
+ */
+
+#include <linux/init.h>
+
+#include <asm/machvec.h>
+#include <asm/rtc.h>
+#include <asm/machvec_init.h>
+#include <asm/io_hd64465.h>
+#include <asm/hd64465.h>
+
+void setup_harp(void);
+void init_harp_irq(void);
+void heartbeat_harp(void);
+
+/*
+ * The Machine Vector
+ */
+
+struct sh_machine_vector mv_harp __initmv = {
+	mv_name:		"STB1 Harp",
+
+	mv_nr_irqs:		89 + HD64465_IRQ_NUM,
+
+	mv_inb:			hd64465_inb,
+	mv_inw:			hd64465_inw,
+	mv_inl:			hd64465_inl,
+	mv_outb:		hd64465_outb,
+	mv_outw:		hd64465_outw,
+	mv_outl:		hd64465_outl,
+
+	mv_inb_p:		hd64465_inb_p,
+	mv_inw_p:		hd64465_inw,
+	mv_inl_p:		hd64465_inl,
+	mv_outb_p:		hd64465_outb_p,
+	mv_outw_p:		hd64465_outw,
+	mv_outl_p:		hd64465_outl,
+
+	mv_insb:		hd64465_insb,
+	mv_insw:		hd64465_insw,
+	mv_insl:		hd64465_insl,
+	mv_outsb:		hd64465_outsb,
+	mv_outsw:		hd64465_outsw,
+	mv_outsl:		hd64465_outsl,
+
+	mv_readb:		generic_readb,
+	mv_readw:		generic_readw,
+	mv_readl:		generic_readl,
+	mv_writeb:		generic_writeb,
+	mv_writew:		generic_writew,
+	mv_writel:		generic_writel,
+
+        mv_ioremap:             generic_ioremap,
+        mv_iounmap:             generic_iounmap,
+ 
+        mv_isa_port2addr:       hd64465_isa_port2addr,
+
+	mv_init_arch:		setup_harp,
+#ifdef CONFIG_PCI
+	mv_init_irq:		init_harp_irq,
+#endif
+#ifdef CONFIG_HEARTBEAT
+	mv_heartbeat:		heartbeat_harp,
+#endif
+        mv_rtc_gettimeofday:    sh_rtc_gettimeofday,
+        mv_rtc_settimeofday:    sh_rtc_settimeofday,
+};
+
+ALIAS_MV(harp)
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/pcidma.c linux/arch/sh/stboards/pcidma.c
--- v2.4.5/linux/arch/sh/stboards/pcidma.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/pcidma.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,42 @@
+/* 
+ * Copyright (C) 2001 David J. Mckay (david.mckay@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.                            
+ *
+ * Dynamic DMA mapping support.
+ */
+
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+
+
+void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size,
+			   dma_addr_t * dma_handle)
+{
+	void *ret;
+	int gfp = GFP_ATOMIC;
+
+	ret = (void *) __get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+	        /* Is it neccessary to do the memset? */
+		memset(ret, 0, size);
+		*dma_handle = virt_to_bus(ret);
+	}
+	/* We must flush the cache before we pass it on to the device */
+	flush_cache_all();
+	return  P2SEGADDR(ret);
+}
+
+void pci_free_consistent(struct pci_dev *hwdev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+        unsigned long p1addr=P1SEGADDR((unsigned long)vaddr);
+
+	free_pages(p1addr, get_order(size));
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/stboards/setup.c linux/arch/sh/stboards/setup.c
--- v2.4.5/linux/arch/sh/stboards/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/sh/stboards/setup.c	Wed Jun 27 13:55:29 2001
@@ -0,0 +1,50 @@
+/*
+ * arch/sh/stboard/setup.c
+ *
+ * Copyright (C) 2001 Stuart Menefy (stuart.menefy@st.com)
+ *
+ * May be copied or modified under the terms of the GNU General Public
+ * License.  See linux/COPYING for more information.
+ *
+ * STMicroelectronics ST40STB1 HARP and compatible support.
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <asm/io.h>
+#include "harp.h"
+/*
+ * Initialize the board
+ */
+int __init setup_harp(void)
+{
+#ifdef CONFIG_SH_STB1_HARP
+	unsigned long ic8_version, ic36_version;
+
+	ic8_version = ctrl_inl(EPLD_REVID2);
+	ic36_version = ctrl_inl(EPLD_REVID1);
+
+        printk("STMicroelectronics STB1 HARP initialisaton\n");
+        printk("EPLD versions: IC8: %d.%02d, IC36: %d.%02d\n",
+               (ic8_version >> 4) & 0xf, ic8_version & 0xf,
+               (ic36_version >> 4) & 0xf, ic36_version & 0xf);
+#elif defined(CONFIG_SH_STB1_OVERDRIVE)
+	unsigned long version;
+
+	version = ctrl_inl(EPLD_REVID);
+
+        printk("STMicroelectronics STB1 Overdrive initialisaton\n");
+        printk("EPLD version: %d.%02d\n",
+	       (version >> 4) & 0xf, version & 0xf);
+#else
+#error Undefined machine
+#endif
+ 
+        /* Currently all STB1 chips have problems with the sleep instruction,
+         * so disable it here.
+         */
+	disable_hlt();
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.5/linux/arch/sh/vmlinux.lds.S linux/arch/sh/vmlinux.lds.S
--- v2.4.5/linux/arch/sh/vmlinux.lds.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/sh/vmlinux.lds.S	Mon Jul  2 14:40:58 2001
@@ -24,7 +24,7 @@
 	*(.gnu.warning)
 	} = 0x0009
   .text.lock : { *(.text.lock) }	/* out-of-line lock text */
-  .rodata : { *(.rodata) }
+  .rodata : { *(.rodata) *(.rodata.*) }
   .kstrtab : { *(.kstrtab) }
 
   . = ALIGN(16);		/* Exception table */
diff -u --recursive --new-file v2.4.5/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.4.5/linux/arch/sparc/config.in	Mon May 21 18:12:09 2001
+++ linux/arch/sparc/config.in	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.110 2001/05/20 05:14:46 davem Exp $
+# $Id: config.in,v 1.111 2001/06/01 08:12:10 davem Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -250,6 +250,10 @@
 endmenu
 
 source fs/Config.in
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   source net/bluetooth/Config.in
+fi
 
 mainmenu_option next_comment
 comment 'Watchdog'
diff -u --recursive --new-file v2.4.5/linux/arch/sparc/kernel/rtrap.S linux/arch/sparc/kernel/rtrap.S
--- v2.4.5/linux/arch/sparc/kernel/rtrap.S	Sun Aug  6 11:43:17 2000
+++ linux/arch/sparc/kernel/rtrap.S	Tue Jun 12 11:08:46 2001
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.55 2000/08/05 10:48:40 davem Exp $
+/* $Id: rtrap.S,v 1.56 2001/06/05 09:56:06 davem Exp $
  * rtrap.S: Return from Sparc trap low-level code.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -52,9 +52,8 @@
 	sll	%l3, 5, %l3
 	sethi	%hi(C_LABEL(irq_stat)), %l4		! &softirq_active
 	add	%l4, %l3, %l4
-	ld	[%l4 + %lo(C_LABEL(irq_stat))], %g5	! softirq_active
-	ld	[%l4 + %lo(C_LABEL(irq_stat) + 4)], %g4	! softirq_mask
-	andcc	%g4, %g5, %g0
+	ld	[%l4 + %lo(C_LABEL(irq_stat))], %g5	! softirq_pending
+	cmp	%g5, 0
 	be	C_LABEL(ret_trap_lockless_ipi)
 	 nop
 	call	C_LABEL(do_softirq)
diff -u --recursive --new-file v2.4.5/linux/arch/sparc/vmlinux.lds linux/arch/sparc/vmlinux.lds
--- v2.4.5/linux/arch/sparc/vmlinux.lds	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc/vmlinux.lds	Mon Jul  2 14:40:58 2001
@@ -12,7 +12,7 @@
   } =0
   _etext = .;
   PROVIDE (etext = .);
-  .rodata    : { *(.rodata)  }
+  .rodata    : { *(.rodata) *(.rodata.*) }
   .rodata1   : { *(.rodata1) }
   .data    :
   {
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.4.5/linux/arch/sparc64/config.in	Sun May 20 11:32:07 2001
+++ linux/arch/sparc64/config.in	Thu Jun 21 14:27:40 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.143 2001/05/20 05:14:46 davem Exp $
+# $Id: config.in,v 1.146 2001/06/16 04:15:26 davem Exp $
 # For a description of the syntax of this configuration file,
 # see the Configure script.
 #
@@ -36,6 +36,7 @@
 define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
 define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
 define_bool CONFIG_ISA n
+define_bool CONFIG_ISAPNP n
 define_bool CONFIG_EISA n
 define_bool CONFIG_MCA n
 define_bool CONFIG_PCMCIA n
@@ -235,71 +236,7 @@
 
    bool 'Network device support' CONFIG_NETDEVICES
    if [ "$CONFIG_NETDEVICES" = "y" ]; then
-      tristate '  Dummy net driver support' CONFIG_DUMMY
-      tristate '  Bonding driver support' CONFIG_BONDING
-      tristate '  Universal TUN/TAP device driver support' CONFIG_TUN
-      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-        if [ "$CONFIG_NETLINK" = "y" ]; then
-          tristate '  Ethertap network tap (OBSOLETE)' CONFIG_ETHERTAP
-        fi
-      fi
-      tristate '  PPP (point-to-point) 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
-         dep_tristate '  PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
-         dep_tristate '  PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
-         if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-            dep_tristate '  PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP
-         fi
-      fi
-      tristate '  SLIP (serial line) support' CONFIG_SLIP
-      if [ "$CONFIG_SLIP" != "n" ]; then
-	 bool '    CSLIP compressed headers' CONFIG_SLIP_COMPRESSED
-	 bool '    Keepalive and linefill' CONFIG_SLIP_SMART
-	 bool '    Six bit SLIP encapsulation' CONFIG_SLIP_MODE_SLIP6
-      fi
-
-      mainmenu_option next_comment
-      comment 'Ethernet (10 or 100Mbit)'
-
-      tristate 'Sun LANCE support' CONFIG_SUNLANCE
-      tristate 'Sun Happy Meal 10/100baseT support' CONFIG_HAPPYMEAL
-      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-	 tristate 'Sun BigMAC 10/100baseT support (EXPERIMENTAL)' CONFIG_SUNBMAC
-      fi
-      tristate '  Sun QuadEthernet support' CONFIG_SUNQE
-      if [ "$CONFIG_PCI" = "y" ]; then
-	 tristate 'Generic DECchip & DIGITAL EtherWORKS PCI/EISA' CONFIG_DE4X5
-	 tristate 'DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP
-	 tristate '3c590/3c900 series (592/595/597) "Vortex/Boomerang" support' CONFIG_VORTEX
-	 tristate 'RealTek RTL-8139 support' CONFIG_8139TOO
-	 tristate 'PCI NE2000 support' CONFIG_NE2K_PCI
-	 tristate 'VIA Rhine support' CONFIG_VIA_RHINE
-	 tristate 'EtherExpressPro/100 support' CONFIG_EEPRO100
-	 tristate 'Adaptec Starfire support' CONFIG_ADAPTEC_STARFIRE
-      fi
-      endmenu
-
-      mainmenu_option next_comment
-      comment 'Ethernet (1000 Mbit)'
-
-      if [ "$CONFIG_PCI" = "y" ]; then
-	  tristate 'Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support' CONFIG_ACENIC
-	  if [ "$CONFIG_ACENIC" != "n" ]; then
-	    bool '  Omit support for old Tigon I based AceNICs' CONFIG_ACENIC_OMIT_TIGON_I
-	  fi
-	  tristate 'SysKonnect SK-98xx support' CONFIG_SK98LIN
-	  tristate 'Sun GEM support' CONFIG_SUNGEM
-      fi
-      tristate 'MyriCOM Gigabit Ethernet support' CONFIG_MYRI_SBUS
-      endmenu
-
-      bool 'FDDI driver support' CONFIG_FDDI
-      if [ "$CONFIG_FDDI" = "y" ]; then
-          tristate '  SysKonnect FDDI PCI support' CONFIG_SKFP
-      fi
-
+      source drivers/net/Config.in
       if [ "$CONFIG_ATM" = "y" ]; then
 	source drivers/atm/Config.in
       fi
@@ -330,6 +267,11 @@
 comment 'XFree86 DRI support'
 bool 'Direct Rendering Manager (XFree86 DRI support)' CONFIG_DRM
 dep_tristate '  Creator/Creator3D' CONFIG_DRM_FFB $CONFIG_DRM
+dep_tristate '  3dfx Banshee/Voodoo3+' CONFIG_DRM_TDFX $CONFIG_DRM
+dep_tristate '  ATI Rage 128' CONFIG_DRM_R128 $CONFIG_DRM
+if [ "$CONFIG_DRM_R128" != "n" ]; then
+   define_bool CONFIG_AGP y
+fi
 endmenu
 
 source drivers/input/Config.in
@@ -346,6 +288,10 @@
 endmenu
 
 source drivers/usb/Config.in
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+   source net/bluetooth/Config.in
+fi
 
 mainmenu_option next_comment
 comment 'Watchdog'
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.4.5/linux/arch/sparc64/defconfig	Thu May 24 15:00:58 2001
+++ linux/arch/sparc64/defconfig	Fri Jun 29 19:38:26 2001
@@ -26,6 +26,7 @@
 # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
 CONFIG_RWSEM_XCHGADD_ALGORITHM=y
 # CONFIG_ISA is not set
+# CONFIG_ISAPNP is not set
 # CONFIG_EISA is not set
 # CONFIG_MCA is not set
 # CONFIG_PCMCIA is not set
@@ -359,46 +360,119 @@
 # Network device support
 #
 CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+
+#
+# Appletalk devices
+#
+# CONFIG_APPLETALK is not set
 CONFIG_DUMMY=m
 CONFIG_BONDING=m
+CONFIG_EQUALIZER=m
 CONFIG_TUN=m
-CONFIG_PPP=m
-# CONFIG_PPP_ASYNC is not set
-# CONFIG_PPP_SYNC_TTY is not set
-# CONFIG_PPP_DEFLATE is not set
-# CONFIG_PPP_BSDCOMP is not set
-CONFIG_PPPOE=m
-CONFIG_SLIP=m
-CONFIG_SLIP_COMPRESSED=y
-CONFIG_SLIP_SMART=y
-# CONFIG_SLIP_MODE_SLIP6 is not set
 
 #
 # Ethernet (10 or 100Mbit)
 #
+CONFIG_NET_ETHERNET=y
 CONFIG_SUNLANCE=y
 CONFIG_HAPPYMEAL=y
 CONFIG_SUNBMAC=m
 CONFIG_SUNQE=m
-CONFIG_DE4X5=m
-CONFIG_TULIP=m
+CONFIG_SUNLANCE=y
+CONFIG_SUNGEM=y
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_EL1 is not set
+# CONFIG_EL2 is not set
+# CONFIG_ELPLUS is not set
+# CONFIG_EL16 is not set
+# CONFIG_ELMC is not set
+# CONFIG_ELMC_II is not set
 CONFIG_VORTEX=m
-CONFIG_8139TOO=m
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_HP100 is not set
+# CONFIG_NET_ISA is not set
+CONFIG_NET_PCI=y
+CONFIG_PCNET32=m
+CONFIG_ADAPTEC_STARFIRE=m
+# CONFIG_APRICOT is not set
+# CONFIG_CS89x0 is not set
+CONFIG_TULIP=m
+# CONFIG_TULIP_MWI is not set
+# CONFIG_TULIP_MMIO is not set
+CONFIG_DE4X5=m
+CONFIG_DGRS=m
+# CONFIG_DM9102 is not set
+CONFIG_EEPRO100=m
+# CONFIG_LNE390 is not set
+CONFIG_FEALNX=m
+CONFIG_NATSEMI=m
 CONFIG_NE2K_PCI=m
+# CONFIG_NE3210 is not set
+# CONFIG_ES3210 is not set
+CONFIG_8139TOO=m
+# CONFIG_8139TOO_PIO is not set
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_SIS900 is not set
+CONFIG_EPIC100=m
+# CONFIG_SUNDANCE is not set
+# CONFIG_TLAN is not set
 CONFIG_VIA_RHINE=m
-CONFIG_EEPRO100=m
-CONFIG_ADAPTEC_STARFIRE=m
+CONFIG_WINBOND_840=m
+# CONFIG_NET_POCKET is not set
 
 #
 # Ethernet (1000 Mbit)
 #
 CONFIG_ACENIC=m
 # CONFIG_ACENIC_OMIT_TIGON_I is not set
-CONFIG_SK98LIN=m
-CONFIG_SUNGEM=y
 CONFIG_MYRI_SBUS=m
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_SK98LIN=m
 CONFIG_FDDI=y
+# CONFIG_DEFXX is not set
 CONFIG_SKFP=m
+CONFIG_HIPPI=y
+# CONFIG_ROADRUNNER is not set
+CONFIG_PLIP=m
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+# CONFIG_PPP_ASYNC is not set
+# CONFIG_PPP_SYNC_TTY is not set
+# CONFIG_PPP_DEFLATE is not set
+# CONFIG_PPP_BSDCOMP is not set
+CONFIG_PPPOE=m
+CONFIG_SLIP=m
+CONFIG_SLIP_COMPRESSED=y
+CONFIG_SLIP_SMART=y
+# CONFIG_SLIP_MODE_SLIP6 is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
 
 #
 # Unix 98 PTY support
@@ -417,6 +491,9 @@
 #
 CONFIG_DRM=y
 CONFIG_DRM_FFB=m
+CONFIG_DRM_TDFX=m
+CONFIG_DRM_R128=m
+CONFIG_AGP=y
 
 #
 # Input core support
@@ -619,6 +696,7 @@
 CONFIG_USB_IBMCAM=m
 CONFIG_USB_OV511=m
 CONFIG_USB_PWC=m
+CONFIG_USB_SE401=m
 CONFIG_USB_DSBR=m
 CONFIG_USB_DABUSB=m
 
@@ -627,6 +705,7 @@
 #
 CONFIG_USB_PLUSB=m
 CONFIG_USB_PEGASUS=m
+CONFIG_USB_CATC=m
 CONFIG_USB_NET1080=m
 
 #
@@ -655,12 +734,27 @@
 # CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
 # CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
 CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_CYBERJACK=m
 CONFIG_USB_SERIAL_OMNINET=m
 
 #
 # USB misc drivers
 #
 CONFIG_USB_RIO500=m
+
+#
+# Bluetooth support
+#
+CONFIG_BLUEZ=m
+CONFIG_BLUEZ_L2CAP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BLUEZ_HCIUSB=m
+CONFIG_BLUEZ_HCIUART=m
+CONFIG_BLUEZ_HCIEMU=m
 
 #
 # Watchdog
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/devices.c linux/arch/sparc64/kernel/devices.c
--- v2.4.5/linux/arch/sparc64/kernel/devices.c	Sun May 20 12:11:38 2001
+++ linux/arch/sparc64/kernel/devices.c	Tue Jun 12 11:08:46 2001
@@ -9,6 +9,7 @@
 #include <linux/threads.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
+#include <linux/string.h>
 
 #include <asm/page.h>
 #include <asm/oplib.h>
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.4.5/linux/arch/sparc64/kernel/ebus.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/ebus.c	Tue Jun 12 11:08:46 2001
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.61 2001/04/24 05:13:25 davem Exp $
+/* $Id: ebus.c,v 1.63 2001/06/08 02:27:16 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -25,7 +25,6 @@
 #ifdef CONFIG_SUN_AUXIO
 extern void auxio_probe(void);
 #endif
-extern void rs_init(void);
 
 static inline void *ebus_alloc(size_t size)
 {
@@ -269,8 +268,6 @@
 	printk("]");
 }
 
-extern void clock_probe(void);
-extern void power_init(void);
 
 void __init ebus_init(void)
 {
@@ -395,10 +392,7 @@
 		++num_ebus;
 	}
 
-	rs_init();
 #ifdef CONFIG_SUN_AUXIO
 	auxio_probe();
 #endif
-	clock_probe();
-	power_init();
 }
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.4.5/linux/arch/sparc64/kernel/ioctl32.c	Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.115 2001/05/12 06:41:58 davem Exp $
+/* $Id: ioctl32.c,v 1.117 2001/06/02 21:39:55 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -90,6 +90,9 @@
 #include <linux/sonet.h>
 #include <linux/atm_suni.h>
 
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci.h>
+
 /* Use this to get at 32-bit user passed pointers. 
    See sys_sparc32.c for description about these. */
 #define A(__x) ((unsigned long)(__x))
@@ -3469,6 +3472,10 @@
 COMPATIBLE_IOCTL(CDROM_LOCKDOOR)
 COMPATIBLE_IOCTL(CDROM_DEBUG)
 COMPATIBLE_IOCTL(CDROM_GET_CAPABILITY)
+/* DVD ioctls */
+COMPATIBLE_IOCTL(DVD_READ_STRUCT)
+COMPATIBLE_IOCTL(DVD_WRITE_STRUCT)
+COMPATIBLE_IOCTL(DVD_AUTH)
 /* Big L */
 COMPATIBLE_IOCTL(LOOP_SET_FD)
 COMPATIBLE_IOCTL(LOOP_CLR_FD)
@@ -3719,6 +3726,17 @@
 COMPATIBLE_IOCTL(WIOCSTART)
 COMPATIBLE_IOCTL(WIOCSTOP)
 COMPATIBLE_IOCTL(WIOCGSTAT)
+/* Bluetooth ioctls */
+COMPATIBLE_IOCTL(HCIDEVUP)
+COMPATIBLE_IOCTL(HCIDEVDOWN)
+COMPATIBLE_IOCTL(HCIDEVRESET)
+COMPATIBLE_IOCTL(HCIRESETSTAT)
+COMPATIBLE_IOCTL(HCIGETINFO)
+COMPATIBLE_IOCTL(HCIGETDEVLIST)
+COMPATIBLE_IOCTL(HCISETRAW)
+COMPATIBLE_IOCTL(HCISETSCAN)
+COMPATIBLE_IOCTL(HCISETAUTH)
+COMPATIBLE_IOCTL(HCIINQUIRY)
 /* Misc. */
 COMPATIBLE_IOCTL(0x41545900)		/* ATYIO_CLKR */
 COMPATIBLE_IOCTL(0x41545901)		/* ATYIO_CLKW */
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.4.5/linux/arch/sparc64/kernel/irq.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/irq.c	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.100 2001/04/24 01:09:12 davem Exp $
+/* $Id: irq.c,v 1.101 2001/06/04 06:50:18 ecd Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -783,6 +783,8 @@
 		unsigned char flags = bp->flags;
 
 		nbp = __bucket(bp->irq_chain);
+		bp->irq_chain = 0;
+
 		if ((flags & IBF_ACTIVE) != 0) {
 #ifdef CONFIG_PCI
 			if ((flags & IBF_DMA_SYNC) != 0) {
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci.c linux/arch/sparc64/kernel/pci.c
--- v2.4.5/linux/arch/sparc64/kernel/pci.c	Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/pci.c	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.29 2001/05/15 08:54:30 davem Exp $
+/* $Id: pci.c,v 1.35 2001/06/13 06:34:30 davem Exp $
  * pci.c: UltraSparc PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
@@ -177,6 +177,10 @@
 	}
 }
 
+extern void rs_init(void);
+extern void clock_probe(void);
+extern void power_init(void);
+
 void __init pcibios_init(void)
 {
 	pci_controller_probe();
@@ -190,6 +194,9 @@
 
 	isa_init();
 	ebus_init();
+	rs_init();
+	clock_probe();
+	power_init();
 }
 
 struct pci_fixup pcibios_fixups[] = {
@@ -198,6 +205,66 @@
 
 void pcibios_fixup_bus(struct pci_bus *pbus)
 {
+	struct pci_pbm_info *pbm = pbus->sysdata;
+
+	/* Generic PCI bus probing sets these to point at
+	 * &io{port,mem}_resouce which is wrong for us.
+	 */
+	pbus->resource[0] = &pbm->io_space;
+	pbus->resource[1] = &pbm->mem_space;
+}
+
+/* NOTE: This can get called before we've fixed up pdev->sysdata. */
+int pci_claim_resource(struct pci_dev *pdev, int resource)
+{
+	struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number];
+	struct resource *res = &pdev->resource[resource];
+	struct resource *root;
+
+	if (!pbm)
+		return -EINVAL;
+
+	if (res->flags & IORESOURCE_IO)
+		root = &pbm->io_space;
+	else
+		root = &pbm->mem_space;
+
+	pbm->parent->resource_adjust(pdev, res, root);
+
+	return request_resource(root, res);
+}
+
+int pci_assign_resource(struct pci_dev *pdev, int resource)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm = pcp->pbm;
+	struct resource *res = &pdev->resource[resource];
+	struct resource *root;
+	unsigned long min, max, size, align;
+	int err;
+
+	if (res->flags & IORESOURCE_IO) {
+		root = &pbm->io_space;
+		min = root->start + 0x400UL;
+		max = root->end;
+	} else {
+		root = &pbm->mem_space;
+		min = root->start;
+		max = min + 0x80000000UL;
+	}
+
+	size = res->end - res->start;
+	align = size + 1;
+
+	err = allocate_resource(root, res, size + 1, min, max, align, NULL, NULL);
+	if (err < 0) {
+		printk("PCI: Failed to allocate resource %d for %s\n",
+		       resource, pdev->name);
+	} else {
+		pbm->parent->base_address_update(pdev, resource);
+	}
+
+	return err;
 }
 
 void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,
@@ -238,6 +305,53 @@
 
 /* Platform support for /proc/bus/pci/X/Y mmap()s. */
 
+/* If the user uses a host-bridge as the PCI device, he may use
+ * this to perform a raw mmap() of the I/O or MEM space behind
+ * that controller.
+ *
+ * This can be useful for execution of x86 PCI bios initialization code
+ * on a PCI card, like the xfree86 int10 stuff does.
+ */
+static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struct *vma,
+				      enum pci_mmap_state mmap_state)
+{
+	struct pcidev_cookie *pcp = pdev->sysdata;
+	struct pci_pbm_info *pbm;
+	unsigned long space_size, user_offset, user_size;
+
+	if (!pcp)
+		return -ENXIO;
+	pbm = pcp->pbm;
+	if (!pbm)
+		return -ENXIO;
+
+	if (mmap_state == pci_mmap_io) {
+		space_size = (pbm->io_space.end -
+			      pbm->io_space.start) + 1;
+	} else {
+		space_size = (pbm->mem_space.end -
+			      pbm->mem_space.start) + 1;
+	}
+
+	/* Make sure the request is in range. */
+	user_offset = vma->vm_pgoff << PAGE_SHIFT;
+	user_size = vma->vm_end - vma->vm_start;
+
+	if (user_offset >= space_size ||
+	    (user_offset + user_size) > space_size)
+		return -EINVAL;
+
+	if (mmap_state == pci_mmap_io) {
+		vma->vm_pgoff = (pbm->io_space.start +
+				 user_offset) >> PAGE_SHIFT;
+	} else {
+		vma->vm_pgoff = (pbm->mem_space.start +
+				 user_offset) >> PAGE_SHIFT;
+	}
+
+	return 0;
+}
+
 /* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding
  * to the 32-bit pci bus offset for DEV requested by the user.
  *
@@ -248,14 +362,17 @@
  *
  * Returns negative error code on failure, zero on success.
  */
-static __inline__ int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
-					     enum pci_mmap_state mmap_state)
+static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
+				  enum pci_mmap_state mmap_state)
 {
 	unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT;
 	unsigned long user32 = user_offset & 0xffffffffUL;
 	unsigned long largest_base, this_base, addr32;
 	int i;
 
+	if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+		return __pci_mmap_make_offset_bus(dev, vma, mmap_state);
+
 	/* Figure out which base address this is for. */
 	largest_base = 0UL;
 	for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
@@ -303,7 +420,7 @@
 /* Set vm_flags of VMA, as appropriate for this architecture, for a pci device
  * mapping.
  */
-static __inline__ void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
+static void __pci_mmap_set_flags(struct pci_dev *dev, struct vm_area_struct *vma,
 					    enum pci_mmap_state mmap_state)
 {
 	vma->vm_flags |= (VM_SHM | VM_LOCKED);
@@ -312,7 +429,7 @@
 /* Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
  * device mapping.
  */
-static __inline__ void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
+static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
 					     enum pci_mmap_state mmap_state)
 {
 	/* Our io_remap_page_range takes care of this, do nothing. */
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- v2.4.5/linux/arch/sparc64/kernel/pci_common.c	Sat May 19 18:13:15 2001
+++ linux/arch/sparc64/kernel/pci_common.c	Fri Jun 29 19:38:26 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.18 2001/05/18 23:06:35 davem Exp $
+/* $Id: pci_common.c,v 1.26 2001/06/28 01:32:18 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -93,12 +93,38 @@
 }
 
 /* Older versions of OBP on PCI systems encode 64-bit MEM
- * space assignments incorrectly, this fixes them up.
+ * space assignments incorrectly, this fixes them up.  We also
+ * take the opportunity here to hide other kinds of bogus
+ * assignments.
  */
-static void __init fixup_obp_assignments(struct pcidev_cookie *pcp)
+static void __init fixup_obp_assignments(struct pci_dev *pdev,
+					 struct pcidev_cookie *pcp)
 {
 	int i;
 
+	if (pdev->vendor == PCI_VENDOR_ID_AL &&
+	    (pdev->device == PCI_DEVICE_ID_AL_M7101 ||
+	     pdev->device == PCI_DEVICE_ID_AL_M1533)) {
+		int i;
+
+		/* Zap all of the normal resources, they are
+		 * meaningless and generate bogus resource collision
+		 * messages.  This is OpenBoot's ill-fated attempt to
+		 * represent the implicit resources that these devices
+		 * have.
+		 */
+		pcp->num_prom_assignments = 0;
+		for (i = 0; i < 6; i++) {
+			pdev->resource[i].start =
+				pdev->resource[i].end =
+				pdev->resource[i].flags = 0;
+		}
+		pdev->resource[PCI_ROM_RESOURCE].start =
+			pdev->resource[PCI_ROM_RESOURCE].end =
+			pdev->resource[PCI_ROM_RESOURCE].flags = 0;
+		return;
+	}
+
 	for (i = 0; i < pcp->num_prom_assignments; i++) {
 		struct linux_prom_pci_registers *ap;
 		int space;
@@ -194,7 +220,7 @@
 				(err / sizeof(pcp->prom_assignments[0]));
 	}
 
-	fixup_obp_assignments(pcp);
+	fixup_obp_assignments(pdev, pcp);
 
 	pdev->sysdata = pcp;
 }
@@ -231,11 +257,13 @@
 	}
 }
 
-static void __init bad_assignment(struct linux_prom_pci_registers *ap,
+static void __init bad_assignment(struct pci_dev *pdev,
+				  struct linux_prom_pci_registers *ap,
 				  struct resource *res,
 				  int do_prom_halt)
 {
-	prom_printf("PCI: Bogus PROM assignment.\n");
+	prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n",
+		    pdev->bus->number, pdev->devfn);
 	if (ap)
 		prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n",
 			    ap->phys_hi, ap->phys_mid, ap->phys_lo,
@@ -293,7 +321,7 @@
 	case  PCI_ROM_ADDRESS:
 		/* It had better be MEM space. */
 		if (space != 2)
-			bad_assignment(ap, NULL, 0);
+			bad_assignment(pdev, ap, NULL, 0);
 
 		res = &pdev->resource[PCI_ROM_RESOURCE];
 		break;
@@ -308,7 +336,7 @@
 		break;
 
 	default:
-		bad_assignment(ap, NULL, 0);
+		bad_assignment(pdev, ap, NULL, 0);
 		res = NULL;
 		break;
 	};
@@ -316,6 +344,19 @@
 	return res;
 }
 
+static int __init pdev_resource_collisions_expected(struct pci_dev *pdev)
+{
+	if (pdev->vendor != PCI_VENDOR_ID_SUN)
+		return 0;
+
+	if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS ||
+	    pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 ||
+	    pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
+		return 1;
+
+	return 0;
+}
+
 static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
 					   struct pci_dev *pdev)
 {
@@ -332,14 +373,15 @@
 		ap = &pcp->prom_assignments[i];
 		root = get_root_resource(ap, pbm);
 		res = get_device_resource(ap, pdev);
-		if (root == NULL || res == NULL)
+		if (root == NULL || res == NULL ||
+		    res->flags == 0)
 			continue;
 
 		/* Ok we know which resource this PROM assignment is
 		 * for, sanity check it.
 		 */
 		if ((res->start & 0xffffffffUL) != ap->phys_lo)
-			bad_assignment(ap, res, 1);
+			bad_assignment(pdev, ap, res, 1);
 
 		/* If it is a 64-bit MEM space assignment, verify that
 		 * the resource is too and that the upper 32-bits match.
@@ -348,9 +390,9 @@
 			if (((res->flags & IORESOURCE_MEM) == 0) ||
 			    ((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
 			     != PCI_BASE_ADDRESS_MEM_TYPE_64))
-				bad_assignment(ap, res, 1);
+				bad_assignment(pdev, ap, res, 1);
 			if ((res->start >> 32) != ap->phys_mid)
-				bad_assignment(ap, res, 1);
+				bad_assignment(pdev, ap, res, 1);
 
 			/* PBM cannot generate cpu initiated PIOs
 			 * to the full 64-bit space.  Therefore the
@@ -374,12 +416,17 @@
 		if (request_resource(root, res) < 0) {
 			/* OK, there is some conflict.  But this is fine
 			 * since we'll reassign it in the fixup pass.
-			 * Nevertheless notify the user that OBP made
-			 * an error.
+			 *
+			 * We notify the user that OBP made an error if it
+			 * is a case we don't expect.
 			 */
-			printk(KERN_ERR "PCI: Address space collision on region %ld "
-			       "of device %s\n",
-			       (res - &pdev->resource[0]), pdev->name);
+			if (!pdev_resource_collisions_expected(pdev)) {
+				printk(KERN_ERR "PCI: Address space collision on region %ld "
+				       "[%016lx:%016lx] of device %s\n",
+				       (res - &pdev->resource[0]),
+				       res->start, res->end,
+				       pdev->name);
+			}
 		}
 	}
 }
@@ -397,6 +444,23 @@
 		pci_record_assignments(pbm, pci_bus_b(walk));
 }
 
+/* Return non-zero if PDEV has implicit I/O resources even
+ * though it may not have an I/O base address register
+ * active.
+ */
+static int __init has_implicit_io(struct pci_dev *pdev)
+{
+	int class = pdev->class >> 8;
+
+	if (class == PCI_CLASS_NOT_DEFINED ||
+	    class == PCI_CLASS_NOT_DEFINED_VGA ||
+	    class == PCI_CLASS_STORAGE_IDE ||
+	    (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+		return 1;
+
+	return 0;
+}
+
 static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
 					  struct pci_dev *pdev)
 {
@@ -460,7 +524,7 @@
 	 */
 	if (io_seen || mem_seen) {
 		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
-		if (io_seen)
+		if (io_seen || has_implicit_io(pdev))
 			cmd |= PCI_COMMAND_IO;
 		if (mem_seen)
 			cmd |= PCI_COMMAND_MEMORY;
@@ -649,17 +713,22 @@
 			line = ((pci_irq_line - 1) & 3);
 		}
 
-		/* Now figure out the slot. */
+		/* Now figure out the slot.
+		 *
+		 * Basically, device number zero on the top-level bus is
+		 * always the PCI host controller.  Slot 0 is then device 1.
+		 * PBM A supports two external slots (0 and 1), and PBM B
+		 * supports 4 external slots (0, 1, 2, and 3).  On-board PCI
+		 * devices are wired to device numbers outside of these
+		 * ranges. -DaveM
+ 		 */
 		if (pdev->bus->number == pbm->pci_first_busno) {
-			if (pbm == &pbm->parent->pbm_A)
-				slot = (pdev->devfn >> 3) - 1;
-			else
-				slot = (pdev->devfn >> 3) - 2;
+			slot = (pdev->devfn >> 3) - 1;
 		} else {
-			if (pbm == &pbm->parent->pbm_A)
-				slot = (pdev->bus->self->devfn >> 3) - 1;
-			else
-				slot = (pdev->bus->self->devfn >> 3) - 2;
+			/* Underneath a bridge, use slot number of parent
+			 * bridge.
+			 */
+			slot = (pdev->bus->self->devfn >> 3) - 1;
 		}
 		slot = slot << 2;
 
@@ -819,6 +888,46 @@
 	walk = &pbus->children;
 	for (walk = walk->next; walk != &pbus->children; walk = walk->next)
 		pci_setup_busmastering(pbm, pci_bus_b(walk));
+}
+
+void pci_register_legacy_regions(struct resource *io_res,
+				 struct resource *mem_res)
+{
+	struct resource *p;
+
+	/* VGA Video RAM. */
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memset(p, 0, sizeof(*p));
+	p->name = "Video RAM area";
+	p->start = mem_res->start + 0xa0000UL;
+	p->end = p->start + 0x1ffffUL;
+	p->flags = IORESOURCE_BUSY;
+	request_resource(mem_res, p);
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memset(p, 0, sizeof(*p));
+	p->name = "System ROM";
+	p->start = mem_res->start + 0xf0000UL;
+	p->end = p->start + 0xffffUL;
+	p->flags = IORESOURCE_BUSY;
+	request_resource(mem_res, p);
+
+	p = kmalloc(sizeof(*p), GFP_KERNEL);
+	if (!p)
+		return;
+
+	memset(p, 0, sizeof(*p));
+	p->name = "Video ROM";
+	p->start = mem_res->start + 0xc0000UL;
+	p->end = p->start + 0x7fffUL;
+	p->flags = IORESOURCE_BUSY;
+	request_resource(mem_res, p);
 }
 
 /* Generic helper routines for PCI error reporting. */
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_impl.h linux/arch/sparc64/kernel/pci_impl.h
--- v2.4.5/linux/arch/sparc64/kernel/pci_impl.h	Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/pci_impl.h	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_impl.h,v 1.8 2001/05/15 08:54:30 davem Exp $
+/* $Id: pci_impl.h,v 1.9 2001/06/13 06:34:30 davem Exp $
  * pci_impl.h: Helper definitions for PCI controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -33,6 +33,8 @@
 					    struct pci_bus *pbus);
 extern void pci_setup_busmastering(struct pci_pbm_info *pbm,
 				   struct pci_bus *pbus);
+extern void pci_register_legacy_regions(struct resource *io_res,
+					struct resource *mem_res);
 
 /* Error reporting support. */
 extern void pci_scan_for_target_abort(struct pci_controller_info *, struct pci_pbm_info *, struct pci_bus *);
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.4.5/linux/arch/sparc64/kernel/pci_psycho.c	Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/pci_psycho.c	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.24 2001/05/15 08:54:30 davem Exp $
+/* $Id: pci_psycho.c,v 1.26 2001/06/13 06:34:30 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -353,23 +353,28 @@
 	if (ret == 0 && pdev == NULL) {
 		ret = 1;
 	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0x0f) {
+		switch ((pdev->class >> 16) & 0xff) {
 		case PCI_BASE_CLASS_STORAGE:
 			ret = 4;
+			break;
 
 		case PCI_BASE_CLASS_NETWORK:
 			ret = 6;
+			break;
 
 		case PCI_BASE_CLASS_DISPLAY:
 			ret = 9;
+			break;
 
 		case PCI_BASE_CLASS_MULTIMEDIA:
 		case PCI_BASE_CLASS_MEMORY:
 		case PCI_BASE_CLASS_BRIDGE:
 			ret = 10;
+			break;
 
 		default:
 			ret = 1;
+			break;
 		};
 	}
 
@@ -1404,6 +1409,8 @@
 
 	request_resource(&ioport_resource, &pbm->io_space);
 	request_resource(&iomem_resource, &pbm->mem_space);
+	pci_register_legacy_regions(&pbm->io_space,
+				    &pbm->mem_space);
 }
 
 static void psycho_pbm_strbuf_init(struct pci_controller_info *p,
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.4.5/linux/arch/sparc64/kernel/pci_sabre.c	Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/pci_sabre.c	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.32 2001/05/15 11:10:01 davem Exp $
+/* $Id: pci_sabre.c,v 1.37 2001/06/13 06:34:30 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -16,6 +16,7 @@
 #include <asm/pbm.h>
 #include <asm/iommu.h>
 #include <asm/irq.h>
+#include <asm/smp.h>
 
 #include "pci_impl.h"
 
@@ -196,7 +197,7 @@
 
 #define SABRE_CONFIGSPACE	0x001000000UL
 #define SABRE_IOSPACE		0x002000000UL
-#define SABRE_IOSPACE_SIZE	0x00000ffffUL
+#define SABRE_IOSPACE_SIZE	0x000ffffffUL
 #define SABRE_MEMSPACE		0x100000000UL
 #define SABRE_MEMSPACE_SIZE	0x07fffffffUL
 
@@ -590,23 +591,28 @@
 	if (ret == 0 && pdev == NULL) {
 		ret = 1;
 	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0x0f) {
+		switch ((pdev->class >> 16) & 0xff) {
 		case PCI_BASE_CLASS_STORAGE:
 			ret = 4;
+			break;
 
 		case PCI_BASE_CLASS_NETWORK:
 			ret = 6;
+			break;
 
 		case PCI_BASE_CLASS_DISPLAY:
 			ret = 9;
+			break;
 
 		case PCI_BASE_CLASS_MULTIMEDIA:
 		case PCI_BASE_CLASS_MEMORY:
 		case PCI_BASE_CLASS_BRIDGE:
 			ret = 10;
+			break;
 
 		default:
 			ret = 1;
+			break;
 		};
 	}
 	return ret;
@@ -1025,8 +1031,8 @@
 					 struct resource *res,
 					 struct resource *root)
 {
-	struct pcidev_cookie *pcp = pdev->sysdata;
-	struct pci_controller_info *p = pcp->pbm->parent;
+	struct pci_pbm_info *pbm = pci_bus2pbm[pdev->bus->number];
+	struct pci_controller_info *p = pbm->parent;
 	unsigned long base;
 
 	if (res->flags & IORESOURCE_IO)
@@ -1351,6 +1357,12 @@
 			    (pbm == &p->pbm_A ? 'A' : 'B'));
 		prom_halt();
 	}
+
+	/* Register legacy regions if this PBM covers that area. */
+	if (pbm->io_space.start == ibase &&
+	    pbm->mem_space.start == mbase)
+		pci_register_legacy_regions(&pbm->io_space,
+					    &pbm->mem_space);
 }
 
 static void __init sabre_pbm_init(struct pci_controller_info *p, int sabre_node, u32 dma_begin)
@@ -1476,7 +1488,7 @@
 
 		/* Hack up top-level resources. */
 		pbm->io_space.start = p->controller_regs + SABRE_IOSPACE;
-		pbm->io_space.end   = pbm->io_space.start + (1UL << 16) - 1UL;
+		pbm->io_space.end   = pbm->io_space.start + (1UL << 24) - 1UL;
 		pbm->io_space.flags = IORESOURCE_IO;
 
 		pbm->mem_space.start = p->controller_regs + SABRE_MEMSPACE;
@@ -1491,6 +1503,9 @@
 			prom_printf("Cannot register Hummingbird's MEM space.\n");
 			prom_halt();
 		}
+
+		pci_register_legacy_regions(&pbm->io_space,
+					    &pbm->mem_space);
 	}
 }
 
@@ -1514,8 +1529,19 @@
 
 		if (prom_getproperty(pnode, "compatible",
 				     compat, sizeof(compat)) > 0 &&
-		    !strcmp(compat, "pci108e,a001"))
+		    !strcmp(compat, "pci108e,a001")) {
 			hummingbird_p = 1;
+		} else {
+			int cpu_node = linux_cpus[0].prom_node;
+
+			/* Of course, Sun has to encode things a thousand
+			 * different ways, inconsistently.
+			 */
+			if (prom_getproperty(cpu_node, "name",
+					     compat, sizeof(compat)) > 0 &&
+			    !strcmp(compat, "SUNW,UltraSPARC-IIe"))
+				hummingbird_p = 1;
+		}
 	}
 
 	p = kmalloc(sizeof(*p), GFP_ATOMIC);
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c
--- v2.4.5/linux/arch/sparc64/kernel/pci_schizo.c	Wed May 16 10:31:27 2001
+++ linux/arch/sparc64/kernel/pci_schizo.c	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_schizo.c,v 1.16 2001/05/15 08:54:30 davem Exp $
+/* $Id: pci_schizo.c,v 1.19 2001/06/20 21:31:00 davem Exp $
  * pci_schizo.c: SCHIZO specific PCI controller support.
  *
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
@@ -339,23 +339,28 @@
 	if (ret == 0 && pdev == NULL) {
 		ret = 1;
 	} else if (ret == 0) {
-		switch ((pdev->class >> 16) & 0x0f) {
+		switch ((pdev->class >> 16) & 0xff) {
 		case PCI_BASE_CLASS_STORAGE:
 			ret = 4;
+			break;
 
 		case PCI_BASE_CLASS_NETWORK:
 			ret = 6;
+			break;
 
 		case PCI_BASE_CLASS_DISPLAY:
 			ret = 9;
+			break;
 
 		case PCI_BASE_CLASS_MULTIMEDIA:
 		case PCI_BASE_CLASS_MEMORY:
 		case PCI_BASE_CLASS_BRIDGE:
 			ret = 10;
+			break;
 
 		default:
 			ret = 1;
+			break;
 		};
 	}
 
@@ -1191,17 +1196,38 @@
 	/* Make all Safari error conditions fatal except unmapped errors
 	 * which we make generate interrupts.
 	 */
+#if 1
+	/* XXX Something wrong with some Excalibur systems
+	 * XXX Sun is shipping.  The behavior on a 2-cpu
+	 * XXX machine is that both CPU1 parity error bits
+	 * XXX are set and are immediately set again when
+	 * XXX their error status bits are cleared.  Just
+	 * XXX ignore them for now.  -DaveM
+	 */
+	schizo_write(base + SCHIZO_SAFARI_ERRCTRL,
+		     (SCHIZO_SAFERRCTRL_EN |
+		      (SAFARI_ERROR_BADCMD | SAFARI_ERROR_SSMDIS |
+		       SAFARI_ERROR_BADMA | SAFARI_ERROR_BADMB |
+		       SAFARI_ERROR_BADMC |
+		       SAFARI_ERROR_CIQTO |
+		       SAFARI_ERROR_LPQTO | SAFARI_ERROR_SFPQTO |
+		       SAFARI_ERROR_UFPQTO | SAFARI_ERROR_APERR |
+		       SAFARI_ERROR_BUSERR | SAFARI_ERROR_TIMEOUT |
+		       SAFARI_ERROR_ILL)));
+#else
 	schizo_write(base + SCHIZO_SAFARI_ERRCTRL,
 		     (SCHIZO_SAFERRCTRL_EN |
 		      (SAFARI_ERROR_BADCMD | SAFARI_ERROR_SSMDIS |
 		       SAFARI_ERROR_BADMA | SAFARI_ERROR_BADMB |
-		       SAFARI_ERROR_BADMC | SAFARI_ERROR_CPU1PS |
-		       SAFARI_ERROR_CPU1PB | SAFARI_ERROR_CPU0PS |
-		       SAFARI_ERROR_CPU0PB | SAFARI_ERROR_CIQTO |
+		       SAFARI_ERROR_BADMC |
+		       SAFARI_ERROR_CPU1PS | SAFARI_ERROR_CPU1PB |
+		       SAFARI_ERROR_CPU0PS | SAFARI_ERROR_CPU0PB |
+		       SAFARI_ERROR_CIQTO |
 		       SAFARI_ERROR_LPQTO | SAFARI_ERROR_SFPQTO |
 		       SAFARI_ERROR_UFPQTO | SAFARI_ERROR_APERR |
 		       SAFARI_ERROR_BUSERR | SAFARI_ERROR_TIMEOUT |
 		       SAFARI_ERROR_ILL)));
+#endif
 
 	schizo_write(base + SCHIZO_SAFARI_IRQCTRL,
 		     (SCHIZO_SAFIRQCTRL_EN | (SAFARI_ERROR_UNMAP)));
@@ -1487,6 +1513,8 @@
 
 	request_resource(&ioport_resource, &pbm->io_space);
 	request_resource(&iomem_resource, &pbm->mem_space);
+	pci_register_legacy_regions(&pbm->io_space,
+				    &pbm->mem_space);
 }
 
 #define SCHIZO_STRBUF_CONTROL_A		(SCHIZO_PBM_A_REGS_OFF + 0x02800UL)
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/power.c linux/arch/sparc64/kernel/power.c
--- v2.4.5/linux/arch/sparc64/kernel/power.c	Tue Jul 11 15:46:08 2000
+++ linux/arch/sparc64/kernel/power.c	Tue Jun 12 11:08:46 2001
@@ -1,4 +1,4 @@
-/* $Id: power.c,v 1.8 2000/07/11 22:41:33 davem Exp $
+/* $Id: power.c,v 1.9 2001/06/08 02:28:22 davem Exp $
  * power.c: Power management driver.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -81,6 +81,11 @@
 {
 	struct linux_ebus *ebus;
 	struct linux_ebus_device *edev;
+	static int invoked = 0;
+
+	if (invoked)
+		return;
+	invoked = 1;
 
 	for_each_ebus(ebus) {
 		for_each_ebusdev(edev, ebus) {
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.4.5/linux/arch/sparc64/kernel/process.c	Thu Apr 12 12:10:25 2001
+++ linux/arch/sparc64/kernel/process.c	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.117 2001/03/30 07:10:41 davem Exp $
+/*  $Id: process.c,v 1.118 2001/06/03 13:41:13 ecd Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -111,6 +111,7 @@
 extern void (*prom_palette)(int);
 extern int serial_console;
 #endif
+extern void (*prom_keyboard)(void);
 
 void machine_halt(void)
 {
@@ -121,6 +122,8 @@
 	if (!serial_console && prom_palette)
 		prom_palette (1);
 #endif
+	if (prom_keyboard)
+		prom_keyboard();
 	prom_halt();
 	panic("Halt failed!");
 }
@@ -139,6 +142,8 @@
 	if (!serial_console && prom_palette)
 		prom_palette (1);
 #endif
+	if (prom_keyboard)
+		prom_keyboard();
 	if (cmd)
 		prom_reboot(cmd);
 	if (*reboot_command)
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/rtrap.S linux/arch/sparc64/kernel/rtrap.S
--- v2.4.5/linux/arch/sparc64/kernel/rtrap.S	Sun Mar 25 18:14:21 2001
+++ linux/arch/sparc64/kernel/rtrap.S	Tue Jun 12 11:08:46 2001
@@ -1,4 +1,4 @@
-/* $Id: rtrap.S,v 1.54 2001/03/08 22:08:51 davem Exp $
+/* $Id: rtrap.S,v 1.55 2001/06/05 09:56:06 davem Exp $
  * rtrap.S: Preparing for return from trap on Sparc V9.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -88,9 +88,8 @@
 		sethi			%hi(irq_stat), %l2	! &softirq_active
 		or			%l2, %lo(irq_stat), %l2	! &softirq_active
 		sllx			%l0, 6, %l0
-		ldx			[%l2 + %l0], %l1	! softirq_active + softirq_mask
-		srlx			%l1, 32, %l2
-		andcc			%l1, %l2, %g0
+		lduw			[%l2 + %l0], %l1	! softirq_pending
+		cmp			%l1, 0
 
 		bne,pn			%icc, __handle_softirq
 		 ldx			[%sp + PTREGS_OFF + PT_V9_TSTATE], %l1
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.4.5/linux/arch/sparc64/kernel/setup.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/setup.c	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.64 2001/04/24 21:10:05 davem Exp $
+/*  $Id: setup.c,v 1.65 2001/06/03 13:41:13 ecd Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -64,6 +64,7 @@
 #if CONFIG_SUN_CONSOLE
 void (*prom_palette)(int);
 #endif
+void (*prom_keyboard)(void);
 asmlinkage void sys_sync(void);	/* it's really int */
 
 static void
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/sparc64_ksyms.c linux/arch/sparc64/kernel/sparc64_ksyms.c
--- v2.4.5/linux/arch/sparc64/kernel/sparc64_ksyms.c	Sun May 20 11:32:07 2001
+++ linux/arch/sparc64/kernel/sparc64_ksyms.c	Mon Jun 11 19:15:27 2001
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.107 2001/05/18 08:01:35 davem Exp $
+/* $Id: sparc64_ksyms.c,v 1.108 2001/06/05 03:39:50 davem Exp $
  * arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -24,6 +24,7 @@
 #include <asm/oplib.h>
 #include <asm/delay.h>
 #include <asm/system.h>
+#include <asm/auxio.h>
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -184,6 +185,9 @@
 EXPORT_SYMBOL(mostek_lock);
 EXPORT_SYMBOL(mstk48t02_regs);
 EXPORT_SYMBOL(request_fast_irq);
+#if CONFIG_SUN_AUXIO
+EXPORT_SYMBOL(auxio_register);
+#endif
 #if CONFIG_SBUS
 EXPORT_SYMBOL(sbus_root);
 EXPORT_SYMBOL(dma_chain);
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.4.5/linux/arch/sparc64/kernel/sys_sparc32.c	Fri Apr 13 20:15:55 2001
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.176 2001/04/14 01:12:02 davem Exp $
+/* $Id: sys_sparc32.c,v 1.177 2001/06/10 06:48:46 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -3493,6 +3493,7 @@
 
 #endif  /* CONFIG_MODULES */
 
+#if defined(CONFIG_NFSD) || defined(CONFIG_NFSD_MODULE)
 /* Stuff for NFS server syscalls... */
 struct nfsctl_svc32 {
 	u16			svc32_port;
@@ -3815,6 +3816,13 @@
 		kfree(kres);
 	return err;
 }
+#else /* !NFSD */
+extern asmlinkage long sys_ni_syscall(void);
+int asmlinkage sys32_nfsservctl(int cmd, void *notused, void *notused2)
+{
+	return sys_ni_syscall();
+}
+#endif
 
 /* Translations due to time_t size differences.  Which affects all
    sorts of things, like timeval and itimerval.  */
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.4.5/linux/arch/sparc64/kernel/time.c	Thu Apr 26 22:17:25 2001
+++ linux/arch/sparc64/kernel/time.c	Tue Jun 12 11:08:46 2001
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.37 2001/04/24 01:09:12 davem Exp $
+/* $Id: time.c,v 1.39 2001/06/08 02:33:37 davem Exp $
  * time.c: UltraSparc timer and TOD clock support.
  *
  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -32,6 +32,7 @@
 #include <asm/fhc.h>
 #include <asm/pbm.h>
 #include <asm/ebus.h>
+#include <asm/isa.h>
 #include <asm/starfire.h>
 
 extern rwlock_t xtime_lock;
@@ -408,7 +409,13 @@
 	unsigned long flags;
 #ifdef CONFIG_PCI
 	struct linux_ebus *ebus = NULL;
+	struct isa_bridge *isa_br = NULL;
 #endif
+	static int invoked = 0;
+
+	if (invoked)
+		return;
+	invoked = 1;
 
 
 	if (this_is_starfire) {
@@ -433,6 +440,9 @@
 	else if (ebus_chain != NULL) {
 		ebus = ebus_chain;
 		busnd = ebus->prom_node;
+	} else if (isa_chain != NULL) {
+		isa_br = isa_chain;
+		busnd = isa_br->prom_node;
 	}
 #endif
 	else if (sbus_root != NULL) {
@@ -465,6 +475,13 @@
 					node = prom_getchild(busnd);
 				}
 			}
+			while ((node == 0) && isa_br != NULL) {
+				isa_br = isa_br->next;
+				if (isa_br != NULL) {
+					busnd = isa_br->prom_node;
+					node = prom_getchild(busnd);
+				}
+			}
 #endif
 			if (node == 0) {
 				prom_printf("clock_probe: Cannot find timer chip\n");
@@ -504,6 +521,22 @@
 				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
 			}
 			break;
+		} else if (isa_chain != NULL) {
+			struct isa_device *isadev;
+
+			for_each_isadev(isadev, isa_br)
+				if (isadev->prom_node == node)
+					break;
+			if (isadev == NULL) {
+				prom_printf("%s: Mostek not probed by ISA\n");
+				prom_halt();
+			}
+			if (!strcmp(model, "ds1287")) {
+				ds1287_regs = isadev->resource.start;
+			} else {
+				mstk48t59_regs = isadev->resource.start;
+				mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02;
+			}
 		}
 #endif
 		else {
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/math-emu/sfp-util.h linux/arch/sparc64/math-emu/sfp-util.h
--- v2.4.5/linux/arch/sparc64/math-emu/sfp-util.h	Mon Dec 20 22:05:52 1999
+++ linux/arch/sparc64/math-emu/sfp-util.h	Wed Jun 20 21:00:55 2001
@@ -1,4 +1,4 @@
-/* $Id: sfp-util.h,v 1.4 1999/09/20 12:14:19 jj Exp $
+/* $Id: sfp-util.h,v 1.5 2001/06/10 06:48:46 davem Exp $
  * arch/sparc64/math-emu/sfp-util.h
  *
  * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -12,10 +12,10 @@
 #include <asm/byteorder.h>
 
 #define add_ssaaaa(sh, sl, ah, al, bh, bl) 						\
-  __asm__ ("addcc %4,%5,%1
-  	    add %2,%3,%0
-  	    bcs,a,pn %%xcc, 1f
-  	    add %0, 1, %0
+  __asm__ ("addcc %4,%5,%1\n\
+  	    add %2,%3,%0\n\
+  	    bcs,a,pn %%xcc, 1f\n\
+  	    add %0, 1, %0\n\
   	    1:"										\
 	   : "=r" ((UDItype)(sh)),				      			\
 	     "=&r" ((UDItype)(sl))				      			\
@@ -26,10 +26,10 @@
 	   : "cc")
 	   
 #define sub_ddmmss(sh, sl, ah, al, bh, bl) 						\
-  __asm__ ("subcc %4,%5,%1
-  	    sub %2,%3,%0
-  	    bcs,a,pn %%xcc, 1f
-  	    sub %0, 1, %0
+  __asm__ ("subcc %4,%5,%1\n\
+  	    sub %2,%3,%0\n\
+  	    bcs,a,pn %%xcc, 1f\n\
+  	    sub %0, 1, %0\n\
   	    1:"										\
 	   : "=r" ((UDItype)(sh)),				      			\
 	     "=&r" ((UDItype)(sl))				      			\
@@ -43,26 +43,26 @@
   do {											\
 	  UDItype tmp1, tmp2, tmp3, tmp4;						\
 	  __asm__ __volatile__ (							\
-		   "srl %7,0,%3
-		    mulx %3,%6,%1
-		    srlx %6,32,%2
-		    mulx %2,%3,%4
-		    sllx %4,32,%5
-		    srl %6,0,%3
-		    sub %1,%5,%5
-		    srlx %5,32,%5
-		    addcc %4,%5,%4
-		    srlx %7,32,%5
-		    mulx %3,%5,%3
-		    mulx %2,%5,%5
-		    sethi %%hi(0x80000000),%2
-		    addcc %4,%3,%4
-		    srlx %4,32,%4
-		    add %2,%2,%2
-		    movcc %%xcc,%%g0,%2
-		    addcc %5,%4,%5
-		    sllx %3,32,%3
-		    add %1,%3,%1
+		   "srl %7,0,%3\n\
+		    mulx %3,%6,%1\n\
+		    srlx %6,32,%2\n\
+		    mulx %2,%3,%4\n\
+		    sllx %4,32,%5\n\
+		    srl %6,0,%3\n\
+		    sub %1,%5,%5\n\
+		    srlx %5,32,%5\n\
+		    addcc %4,%5,%4\n\
+		    srlx %7,32,%5\n\
+		    mulx %3,%5,%3\n\
+		    mulx %2,%5,%5\n\
+		    sethi %%hi(0x80000000),%2\n\
+		    addcc %4,%3,%4\n\
+		    srlx %4,32,%4\n\
+		    add %2,%2,%2\n\
+		    movcc %%xcc,%%g0,%2\n\
+		    addcc %5,%4,%5\n\
+		    sllx %3,32,%3\n\
+		    add %1,%3,%1\n\
 		    add %5,%2,%0"							\
 	   : "=r" ((UDItype)(wh)),							\
 	     "=&r" ((UDItype)(wl)),							\
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/vmlinux.lds linux/arch/sparc64/vmlinux.lds
--- v2.4.5/linux/arch/sparc64/vmlinux.lds	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc64/vmlinux.lds	Mon Jul  2 14:40:58 2001
@@ -16,7 +16,7 @@
   } =0
   _etext = .;
   PROVIDE (etext = .);
-  .rodata    : { *(.rodata)  }
+  .rodata    : { *(.rodata) *(.rodata.*) }
   .rodata1   : { *(.rodata1) }
   .data    :
   {
diff -u --recursive --new-file v2.4.5/linux/drivers/Makefile linux/drivers/Makefile
--- v2.4.5/linux/drivers/Makefile	Wed May 16 10:27:02 2001
+++ linux/drivers/Makefile	Mon Jun 11 19:15:27 2001
@@ -7,7 +7,8 @@
 
 
 mod-subdirs :=	dio mtd sbus video macintosh usb input telephony sgi i2o ide \
-		scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi
+		scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi \
+		bluetooth
 
 subdir-y :=	parport char block net sound misc media cdrom
 subdir-m :=	$(subdir-y)
@@ -42,6 +43,8 @@
 subdir-$(CONFIG_HAMRADIO)	+= net/hamradio
 subdir-$(CONFIG_I2C)		+= i2c
 subdir-$(CONFIG_ACPI)		+= acpi
+
+subdir-$(CONFIG_BLUEZ)		+= bluetooth
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/keyb_arc.c linux/drivers/acorn/char/keyb_arc.c
--- v2.4.5/linux/drivers/acorn/char/keyb_arc.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/acorn/char/keyb_arc.c	Wed Jun 27 14:12:04 2001
@@ -390,7 +390,7 @@
 		kbd_state, keyval);
 #endif
 	mdelay(1);
-	inb(IOC_KARTRX);
+	ioc_readb(IOC_KARTRX);
 	a5kkbd_sendbyte (HRST);
 	kbd_state = KBD_INITRST;
 	return 0;
@@ -407,13 +407,13 @@
 static void a5kkbd_rx(int irq, void *dev_id, struct pt_regs *regs)
 {
 	kbd_pt_regs = regs;
-	if (handle_rawcode(inb(IOC_KARTRX)))
+	if (handle_rawcode(ioc_readb(IOC_KARTRX)))
 		tasklet_schedule(&keyboard_tasklet);
 }
 
 static void a5kkbd_tx(int irq, void *dev_id, struct pt_regs *regs)
 {
-	outb (kbd_txval[kbd_txtail], IOC_KARTTX);
+	ioc_writeb (kbd_txval[kbd_txtail], IOC_KARTTX);
 	KBD_INCTXPTR(kbd_txtail);
 	if (kbd_txtail == kbd_txhead)
 		disable_irq(irq);
@@ -431,7 +431,7 @@
 
 	if (request_irq (IRQ_KEYBOARDTX, a5kkbd_tx, 0, "keyboard", NULL) != 0)
 		panic("Could not allocate keyboard transmit IRQ!");
-	(void)inb(IOC_KARTRX);
+	(void)ioc_readb(IOC_KARTRX);
 	if (request_irq (IRQ_KEYBOARDRX, a5kkbd_rx, 0, "keyboard", NULL) != 0)
 		panic("Could not allocate keyboard receive IRQ!");
 
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c
--- v2.4.5/linux/drivers/acorn/char/keyb_ps2.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/acorn/char/keyb_ps2.c	Wed Jun 27 14:12:04 2001
@@ -24,6 +24,7 @@
 #include <linux/random.h>
 #include <linux/ctype.h>
 #include <linux/kbd_ll.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 
 #include <asm/bitops.h>
@@ -37,6 +38,12 @@
 extern void kbd_reset_kdown(void);
 int kbd_read_mask;
 
+#define TX_DONE 0
+#define TX_SENT 1
+#define TX_SEND 2
+
+static volatile int tx_state;
+
 #define VERSION 100
 
 #define KBD_REPORT_ERR
@@ -233,8 +240,33 @@
 
 static inline void ps2kbd_sendbyte(unsigned char val)
 {
-	while(!(inb(IOMD_KCTRL) & (1 << 7)));
-	outb(val, IOMD_KARTTX);
+	int tries = 3, timeout = 1000;
+
+	tx_state = TX_SEND;
+
+	do {
+		switch (tx_state) {
+		case TX_SEND:
+			tx_state = TX_SENT;
+			timeout = 1000;
+			tries --;
+
+			while(!(iomd_readb(IOMD_KCTRL) & (1 << 7)));
+			iomd_writeb(val, IOMD_KARTTX);
+			break;
+
+		case TX_SENT:
+			udelay(1000);
+			if (--timeout == 0) {
+				printk(KERN_ERR "Keyboard timeout\n");
+				tx_state = TX_DONE;
+			}
+			break;
+
+		case TX_DONE:
+			break;
+		}
+	} while (tries > 0 && tx_state != TX_DONE);
 }
 
 static unsigned char status;
@@ -254,18 +286,30 @@
 
 	if (keyval > 0x83) {
 		switch (keyval) {
-			case KBD_ESCAPEE0:
-				ncodes = 2;
-				bi = 0;
-				break;
-			case KBD_ESCAPEE1:
-				ncodes = 3;
-				bi = 0;
-				break;
-			case KBD_BREAK:
-				status |= CODE_BREAK;
-			default:
-				return;
+		case KBD_ESCAPEE0:
+			ncodes = 2;
+			bi = 0;
+			break;
+
+		case KBD_ESCAPEE1:
+			ncodes = 3;
+			bi = 0;
+			break;
+
+		case KBD_ACK:
+			tx_state = TX_DONE;
+			return;
+
+		case KBD_RESEND:
+			tx_state = TX_SEND;
+			return;
+
+		case KBD_BREAK:
+			status |= CODE_BREAK;
+			return;
+
+		default:
+			return;
 		}
 	}
 
@@ -278,6 +322,13 @@
 		switch (buffer[0] << 8 | buffer[1]) {
 		case ESCE0(0x11): keysym = K_RALT; break;
 		case ESCE0(0x14): keysym = K_RCTL; break;
+		/*
+		 * take care of MS extra keys (actually
+		 * 0x7d - 0x7f, but last one is already K_NONE
+		 */
+		case ESCE0(0x1f): keysym = 124;    break;
+		case ESCE0(0x27): keysym = 125;    break;
+		case ESCE0(0x2f): keysym = 126;    break;
 		case ESCE0(0x4a): keysym = KP_SLH; break;
 		case ESCE0(0x5a): keysym = KP_ENT; break;
 		case ESCE0(0x69): keysym = K_END;  break;
@@ -320,8 +371,8 @@
 {
 	kbd_pt_regs = regs;
 
-	while (inb(IOMD_KCTRL) & (1 << 5))
-		handle_rawcode(inb(IOMD_KARTRX));
+	while (iomd_readb(IOMD_KCTRL) & (1 << 5))
+		handle_rawcode(iomd_readb(IOMD_KARTRX));
 	tasklet_schedule(&keyboard_tasklet);
 }
 
@@ -332,10 +383,10 @@
 int __init ps2kbd_init_hw(void)
 {
 	/* Reset the keyboard state machine. */
-	outb(0, IOMD_KCTRL);
-	outb(8, IOMD_KCTRL);
+	iomd_writeb(0, IOMD_KCTRL);
+	iomd_writeb(8, IOMD_KCTRL);
+	iomd_readb(IOMD_KARTRX);
 
-	(void)IOMD_KARTRX;
 	if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0)
 		panic("Could not allocate keyboard receive IRQ!");
 	if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0)
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/mouse_ps2.c linux/drivers/acorn/char/mouse_ps2.c
--- v2.4.5/linux/drivers/acorn/char/mouse_ps2.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/mouse_ps2.c	Wed Jun 27 14:12:04 2001
@@ -0,0 +1,289 @@
+/* 
+ * Driver for PS/2 mouse on IOMD interface
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/kbd_ll.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/hardware/iomd.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+/*
+ *	PS/2 Auxiliary Device
+ */
+
+static struct aux_queue *queue;	/* Mouse data buffer. */
+static int aux_count = 0;
+/* used when we send commands to the mouse that expect an ACK. */
+static unsigned char mouse_reply_expected = 0;
+
+#define MAX_RETRIES	60		/* some aux operations take long time*/
+
+/*
+ *	Mouse Commands
+ */
+
+#define AUX_SET_RES		0xE8	/* Set resolution */
+#define AUX_SET_SCALE11		0xE6	/* Set 1:1 scaling */
+#define AUX_SET_SCALE21		0xE7	/* Set 2:1 scaling */
+#define AUX_GET_SCALE		0xE9	/* Get scaling factor */
+#define AUX_SET_STREAM		0xEA	/* Set stream mode */
+#define AUX_SET_SAMPLE		0xF3	/* Set sample rate */
+#define AUX_ENABLE_DEV		0xF4	/* Enable aux device */
+#define AUX_DISABLE_DEV		0xF5	/* Disable aux device */
+#define AUX_RESET		0xFF	/* Reset aux device */
+#define AUX_ACK			0xFA	/* Command byte ACK. */
+
+#define AUX_BUF_SIZE		2048	/* This might be better divisible by
+					   three to make overruns stay in sync
+					   but then the read function would 
+					   need a lock etc - ick */
+
+struct aux_queue {
+	unsigned long head;
+	unsigned long tail;
+	wait_queue_head_t proc_list;
+	struct fasync_struct *fasync;
+	unsigned char buf[AUX_BUF_SIZE];
+};
+
+/*
+ * Send a byte to the mouse.
+ */
+static void aux_write_dev(int val)
+{
+	while (!(iomd_readb(IOMD_MSECTL) & 0x80));
+	iomd_writeb(val, IOMD_MSEDAT);
+}
+
+/*
+ * Send a byte to the mouse & handle returned ack
+ */
+static void aux_write_ack(int val)
+{
+	while (!(iomd_readb(IOMD_MSECTL) & 0x80));
+	iomd_writeb(val, IOMD_MSEDAT);
+
+	/* we expect an ACK in response. */
+	mouse_reply_expected++;
+}
+
+static unsigned char get_from_queue(void)
+{
+	unsigned char result;
+
+	result = queue->buf[queue->tail];
+	queue->tail = (queue->tail + 1) & (AUX_BUF_SIZE-1);
+	return result;
+}
+
+static void psaux_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	int val = iomd_readb(IOMD_MSEDAT);
+
+	if (mouse_reply_expected) {
+		if (val == AUX_ACK) {
+			mouse_reply_expected--;
+			return;
+		}
+		mouse_reply_expected = 0;
+	}
+
+	add_mouse_randomness(val);
+	if (aux_count) {
+		int head = queue->head;
+
+		queue->buf[head] = val;
+		head = (head + 1) & (AUX_BUF_SIZE-1);
+		if (head != queue->tail) {
+			queue->head = head;
+			kill_fasync(&queue->fasync, SIGIO, POLL_IN);
+			wake_up_interruptible(&queue->proc_list);
+		}
+	}
+}
+
+static inline int queue_empty(void)
+{
+	return queue->head == queue->tail;
+}
+
+static int fasync_aux(int fd, struct file *filp, int on)
+{
+	int retval;
+
+	retval = fasync_helper(fd, filp, on, &queue->fasync);
+	if (retval < 0)
+		return retval;
+	return 0;
+}
+
+
+/*
+ * Random magic cookie for the aux device
+ */
+#define AUX_DEV ((void *)queue)
+
+static int release_aux(struct inode * inode, struct file * file)
+{
+	fasync_aux(-1, file, 0);
+	if (--aux_count)
+		return 0;
+	free_irq(IRQ_MOUSERX, AUX_DEV);
+	return 0;
+}
+
+/*
+ * Install interrupt handler.
+ * Enable auxiliary device.
+ */
+
+static int open_aux(struct inode * inode, struct file * file)
+{
+	if (aux_count++)
+		return 0;
+
+	queue->head = queue->tail = 0;		/* Flush input queue */
+	if (request_irq(IRQ_MOUSERX, psaux_interrupt, SA_SHIRQ, "ps/2 mouse", 
+			AUX_DEV)) {
+		aux_count--;
+		return -EBUSY;
+	}
+
+	aux_write_ack(AUX_ENABLE_DEV); /* Enable aux device */
+
+	return 0;
+}
+
+/*
+ * Put bytes from input queue to buffer.
+ */
+
+static ssize_t read_aux(struct file * file, char * buffer,
+			size_t count, loff_t *ppos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	ssize_t i = count;
+	unsigned char c;
+
+	if (queue_empty()) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+		add_wait_queue(&queue->proc_list, &wait);
+repeat:
+		current->state = TASK_INTERRUPTIBLE;
+		if (queue_empty() && !signal_pending(current)) {
+			schedule();
+			goto repeat;
+		}
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&queue->proc_list, &wait);
+	}
+	while (i > 0 && !queue_empty()) {
+		c = get_from_queue();
+		put_user(c, buffer++);
+		i--;
+	}
+	if (count-i) {
+		file->f_dentry->d_inode->i_atime = CURRENT_TIME;
+		return count-i;
+	}
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+/*
+ * Write to the aux device.
+ */
+
+static ssize_t write_aux(struct file * file, const char * buffer,
+			 size_t count, loff_t *ppos)
+{
+	ssize_t retval = 0;
+
+	if (count) {
+		ssize_t written = 0;
+
+		if (count > 32)
+			count = 32; /* Limit to 32 bytes. */
+		do {
+			char c;
+			get_user(c, buffer++);
+			aux_write_dev(c);
+			written++;
+		} while (--count);
+		retval = -EIO;
+		if (written) {
+			retval = written;
+			file->f_dentry->d_inode->i_mtime = CURRENT_TIME;
+		}
+	}
+
+	return retval;
+}
+
+static unsigned int aux_poll(struct file *file, poll_table * wait)
+{
+	poll_wait(file, &queue->proc_list, wait);
+	if (!queue_empty())
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+struct file_operations psaux_fops = {
+	read:		read_aux,
+	write:		write_aux,
+	poll:		aux_poll,
+	open:		open_aux,
+	release:	release_aux,
+	fasync:		fasync_aux,
+};
+
+/*
+ * Initialize driver.
+ */
+static struct miscdevice psaux_mouse = {
+	PSMOUSE_MINOR, "psaux", &psaux_fops
+};
+
+int __init psaux_init(void)
+{
+	/* Reset the mouse state machine. */
+	iomd_writeb(0, IOMD_MSECTL);
+	iomd_writeb(8, IOMD_MSECTL);
+  
+	misc_register(&psaux_mouse);
+	queue = (struct aux_queue *) kmalloc(sizeof(*queue), GFP_KERNEL);
+	memset(queue, 0, sizeof(*queue));
+	queue->head = queue->tail = 0;
+	init_waitqueue_head(&queue->proc_list);
+
+	aux_write_ack(AUX_SET_SAMPLE);
+	aux_write_ack(100);			/* 100 samples/sec */
+	aux_write_ack(AUX_SET_RES);
+	aux_write_ack(3);			/* 8 counts per mm */
+	aux_write_ack(AUX_SET_SCALE21);		/* 2:1 scaling */
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/char/mouse_rpc.c linux/drivers/acorn/char/mouse_rpc.c
--- v2.4.5/linux/drivers/acorn/char/mouse_rpc.c	Mon Sep 18 15:15:21 2000
+++ linux/drivers/acorn/char/mouse_rpc.c	Wed Jun 27 14:12:04 2001
@@ -34,9 +34,9 @@
 	short x, y, dx, dy;
 	int buttons;
 
-	x = (short)inl(IOMD_MOUSEX);
-	y = (short)inl(IOMD_MOUSEY);
-	buttons = (inl (0x800C4000) >> 4) & 7;
+	x = (short)iomd_readl(IOMD_MOUSEX);
+	y = (short)iomd_readl(IOMD_MOUSEY);
+	buttons = (__raw_readl(0xe0310000) >> 4) & 7;
 
 	dx = x - old_x;
 	old_x = x;
@@ -60,9 +60,9 @@
 	if (mousedev < 0)
 		printk("rpcmouse: could not register mouse driver\n");
 	else {
-		old_x = (short)inl(IOMD_MOUSEX);
-		old_y = (short)inl(IOMD_MOUSEY);
-		old_b = (inl (0x800C4000) >> 4) & 7;
+		old_x = (short)iomd_readl(IOMD_MOUSEX);
+		old_y = (short)iomd_readl(IOMD_MOUSEY);
+		old_b = (__raw_readl(0xe0310000) >> 4) & 7;
 		if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) {
 			printk("rpcmouse: unable to allocate VSYNC interrupt\n");
 			unregister_busmouse(mousedev);
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c
--- v2.4.5/linux/drivers/acorn/net/ether1.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/acorn/net/ether1.c	Wed Jun 27 14:12:04 2001
@@ -75,7 +75,7 @@
 
 /* ------------------------------------------------------------------------- */
 
-static const char version[] __initdata = KERN_INFO "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
+static char version[] __initdata = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
 
 #define BUS_16 16
 #define BUS_8  8
@@ -990,7 +990,7 @@
 	static unsigned int version_printed = 0;
 
 	if (net_debug && version_printed++ == 0)
-		printk (version);
+		printk(KERN_INFO "%s", version);
 }
 
 static struct net_device * __init ether1_init_one(struct expansion_card *ec)
@@ -1045,7 +1045,6 @@
 release:
 	release_region(dev->base_addr, 16);
 	release_region(dev->base_addr + 0x800, 4096);
-free:
 	unregister_netdev(dev);
 	kfree(dev);
 out:
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.4.5/linux/drivers/acorn/net/ether3.c	Fri Feb  9 11:30:22 2001
+++ linux/drivers/acorn/net/ether3.c	Wed Jun 27 14:12:04 2001
@@ -70,7 +70,7 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-static const char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
+static char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
 
 #include "ether3.h"
 
@@ -777,7 +777,7 @@
 	static unsigned version_printed = 0;
 
 	if (net_debug && version_printed++ == 0)
-		printk(version);
+		printk(KERN_INFO "%s", version);
 }
 
 static const char * __init
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c
--- v2.4.5/linux/drivers/acorn/scsi/acornscsi.c	Fri Mar  2 18:38:37 2001
+++ linux/drivers/acorn/scsi/acornscsi.c	Wed Jun 27 14:12:04 2001
@@ -144,6 +144,7 @@
 #include <linux/ioport.h>
 #include <linux/blk.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/bitops.h>
 #include <asm/system.h>
@@ -157,6 +158,8 @@
 #include "acornscsi.h"
 #include "msgqueue.h"
 
+#include <scsi/scsicam.h>
+
 #define VER_MAJOR 2
 #define VER_MINOR 0
 #define VER_PATCH 6
@@ -206,24 +209,24 @@
 static inline void
 sbic_arm_write(unsigned int io_port, int reg, int value)
 {
-    outb_t(reg, io_port);
-    outb_t(value, io_port + 4);
+    __raw_writeb(reg, io_port);
+    __raw_writeb(value, io_port + 4);
 }
 
 #define sbic_arm_writenext(io,val) \
-	outb_t((val), (io) + 4)
+	__raw_writeb((val), (io) + 4)
 
 static inline
 int sbic_arm_read(unsigned int io_port, int reg)
 {
     if(reg == ASR)
-	   return inl_t(io_port) & 255;
-    outb_t(reg, io_port);
-    return inl_t(io_port + 4) & 255;
+	   return __raw_readl(io_port) & 255;
+    __raw_writeb(reg, io_port);
+    return __raw_readl(io_port + 4) & 255;
 }
 
 #define sbic_arm_readnext(io) \
-	inb_t((io) + 4)
+	__raw_readb((io) + 4)
 
 #ifdef USE_DMAC
 #define dmac_read(io_port,reg) \
@@ -2858,7 +2861,7 @@
  * Params   : host - host to setup
  */
 static
-void acornscsi_init(AS_Host *host)
+void acornscsi_host_init(AS_Host *host)
 {
     memset(&host->stats, 0, sizeof (host->stats));
     queue_initialise(&host->queues.issue);
@@ -2926,7 +2929,7 @@
 	    host->scsi.irq = NO_IRQ;
 	}
 
-	acornscsi_init(host);
+	acornscsi_host_init(host);
 
 	++count;
     }
@@ -3118,9 +3121,40 @@
     return pos;
 }
 
-#ifdef MODULE
+static Scsi_Host_Template acornscsi_template = {
+	module:			THIS_MODULE,
+	proc_info:		acornscsi_proc_info,
+	name:			"AcornSCSI",
+	detect:			acornscsi_detect,
+	release:		acornscsi_release,
+	info:			acornscsi_info,
+	queuecommand:		acornscsi_queuecmd,
+	abort:			acornscsi_abort,
+	reset:			acornscsi_reset,
+	bios_param:		scsicam_bios_param,
+	can_queue:		16,
+	this_id:		7,
+	sg_tablesize:		SG_ALL,
+	cmd_per_lun:		2,
+	unchecked_isa_dma:	0,
+	use_clustering:		DISABLE_CLUSTERING
+};
 
-Scsi_Host_Template driver_template = ACORNSCSI_3;
+static int __init acornscsi_init(void)
+{
+	acornscsi_template.module = THIS_MODULE;
+	scsi_register_module(MODULE_SCSI_HA, &acornscsi_template);
+	if (acornscsi_template.present)
+		return 0;
 
-#include "../../scsi/scsi_module.c"
-#endif
+	scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
+	return -ENODEV;
+}
+
+static void __exit acornscsi_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template);
+}
+
+module_init(acornscsi_init);
+module_exit(acornscsi_exit);
diff -u --recursive --new-file v2.4.5/linux/drivers/acorn/scsi/acornscsi.h linux/drivers/acorn/scsi/acornscsi.h
--- v2.4.5/linux/drivers/acorn/scsi/acornscsi.h	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/acornscsi.h	Wed Jun 27 14:12:04 2001
@@ -12,52 +12,6 @@
 #ifndef ACORNSCSI_H
 #define ACORNSCSI_H
 
-#ifndef ASM
-extern int acornscsi_detect (Scsi_Host_Template *);
-extern int acornscsi_release (struct Scsi_Host *);
-extern const char *acornscsi_info (struct Scsi_Host *);
-extern int acornscsi_queuecmd (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-extern int acornscsi_abort (Scsi_Cmnd *);
-extern int acornscsi_reset (Scsi_Cmnd *, unsigned int);
-extern int acornscsi_proc_info (char *, char **, off_t, int, int, int);
-extern int acornscsi_biosparam (Disk *, kdev_t, int []);
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#include "linux/proc_fs.h"
-
-#include <scsi/scsicam.h>
-
-#define ACORNSCSI_3 {							\
-proc_info:		acornscsi_proc_info,				\
-name:			"AcornSCSI",					\
-detect:			acornscsi_detect,				\
-release:		acornscsi_release,	/* Release */		\
-info:			acornscsi_info,					\
-queuecommand:		acornscsi_queuecmd,				\
-abort:			acornscsi_abort,				\
-reset:			acornscsi_reset,				\
-bios_param:		scsicam_bios_param,				\
-can_queue:		CAN_QUEUE,		/* can_queue */		\
-this_id:		7,			/* this id */		\
-sg_tablesize:		SG_ALL,			/* sg_tablesize */	\
-cmd_per_lun:		CMD_PER_LUN,		/* cmd_per_lun */	\
-unchecked_isa_dma:	0,			/* unchecked isa dma */	\
-use_clustering:		DISABLE_CLUSTERING				\
-	}
-
-#ifndef HOSTS_C
-
 /* SBIC registers */
 #define OWNID			0
 #define OWNID_FS1		(1<<7)
@@ -405,7 +359,4 @@
     struct status_entry status[9][STATUS_BUFFER_SIZE];
 } AS_Host;
 
-#endif /* ndef HOSTS_C */
-
-#endif /* ndef ASM */
 #endif /* ACORNSCSI_H */
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/Config.in linux/drivers/acpi/Config.in
--- v2.4.5/linux/drivers/acpi/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/Config.in	Wed Jun 20 17:47:39 2001
@@ -0,0 +1,17 @@
+#
+# ACPI configuration
+#
+#mainmenu_option next_comment
+#comment 'ACPI Configuration'
+
+dep_bool     '    ACPI Debug Statements' CONFIG_ACPI_DEBUG $CONFIG_ACPI
+dep_tristate '    ACPI Bus Manager' CONFIG_ACPI_BUSMGR $CONFIG_ACPI
+
+dep_tristate '      System' CONFIG_ACPI_SYS $CONFIG_ACPI_BUSMGR $CONFIG_ACPI
+dep_tristate '      Processor' CONFIG_ACPI_CPU $CONFIG_ACPI_BUSMGR $CONFIG_ACPI
+dep_tristate '      Button' CONFIG_ACPI_BUTTON $CONFIG_ACPI_BUSMGR $CONFIG_ACPI
+dep_tristate '      AC Adapter' CONFIG_ACPI_AC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI
+dep_tristate '      Embedded Controller' CONFIG_ACPI_EC $CONFIG_ACPI_BUSMGR $CONFIG_ACPI
+dep_tristate '      Control Method Battery' CONFIG_ACPI_CMBATT $CONFIG_ACPI_BUSMGR $CONFIG_ACPI $CONFIG_ACPI_EC
+dep_tristate '      Thermal' CONFIG_ACPI_THERMAL $CONFIG_ACPI_BUSMGR $CONFIG_ACPI  $CONFIG_ACPI_EC
+#endmenu
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/Makefile linux/drivers/acpi/Makefile
--- v2.4.5/linux/drivers/acpi/Makefile	Sat Mar  3 17:46:47 2001
+++ linux/drivers/acpi/Makefile	Wed Jun 20 17:47:39 2001
@@ -1,13 +1,15 @@
 #
 # Makefile for the Linux ACPI interpreter
-#
+# (It's a mess, but it's all here for a reason.)
+# 
 
 O_TARGET := acpi.o
 
 export-objs := acpi_ksyms.o
 
 export ACPI_CFLAGS
-ACPI_CFLAGS := -D_LINUX
+
+ACPI_CFLAGS := -D_LINUX -I$(CURDIR)/include
 
 #
 # CONFIG_ACPI_KERNEL_CONFIG is currently only IA64
@@ -16,25 +18,37 @@
   ACPI_CFLAGS += -DCONFIG_ACPI_KERNEL_CONFIG_ONLY
 endif
 
-EXTRA_CFLAGS += -I./include
+acpi-subdirs := utilities dispatcher events hardware \
+		executer namespace parser resources tables
 
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
+ifdef CONFIG_ACPI_DEBUG
+  ACPI_CFLAGS += -DACPI_DEBUG -Wno-unused #-DENABLE_DEBUGGER
+
+  #acpi-subdirs += debugger
+endif
 
-acpi-subdirs := common dispatcher events hardware \
-		interpreter namespace parser resources tables
+EXTRA_CFLAGS += $(ACPI_CFLAGS)
 
-subdir-$(CONFIG_ACPI) += $(acpi-subdirs)
+mod-subdirs  := ospm
 
-obj-$(CONFIG_ACPI) := $(patsubst %,%.o,$(acpi-subdirs))
-obj-$(CONFIG_ACPI) += os.o acpi_ksyms.o
+subdir-$(CONFIG_ACPI) 		+= $(acpi-subdirs)
+subdir-$(CONFIG_ACPI_BUSMGR)	+= ospm
 
+obj-$(CONFIG_ACPI)	+= os.o acpi_ksyms.o
+obj-$(CONFIG_ACPI)	+= $(foreach dir,$(acpi-subdirs),$(dir)/$(dir).o) 
 ifdef CONFIG_ACPI_KERNEL_CONFIG
-  obj-$(CONFIG_ACPI) += acpiconf.o osconf.o
+   obj-$(CONFIG_ACPI) 	+= acpiconf.o osconf.o
 else
-  obj-$(CONFIG_ACPI) += driver.o cmbatt.o cpu.o ec.o acpi_ksyms.o sys.o table.o power.o
+   obj-$(CONFIG_ACPI)	+= driver.o
 endif
 
-include $(TOPDIR)/Rules.make
+ifeq ($(CONFIG_ACPI_BUSMGR),y)
+	obj-y			+= ospm/ospm.o
+endif
 
-clean:
-	$(RM) *.o */*.o
+# commented out until we distribute it -ASG
+#ifeq ($(CONFIG_KDB),y)
+#	obj-m	+= kdb/kdbm_acpi.o
+#endif
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/acpi_ksyms.c linux/drivers/acpi/acpi_ksyms.c
--- v2.4.5/linux/drivers/acpi/acpi_ksyms.c	Fri Feb 16 16:06:17 2001
+++ linux/drivers/acpi/acpi_ksyms.c	Wed Jun 20 17:47:39 2001
@@ -18,6 +18,7 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -27,6 +28,7 @@
 #include "acdebug.h"
 
 extern int acpi_in_debugger;
+extern FADT_DESCRIPTOR acpi_fadt;
 
 #define _COMPONENT	OS_DEPENDENT
 	MODULE_NAME	("symbols")
@@ -55,9 +57,7 @@
 EXPORT_SYMBOL(debug_print_raw);
 EXPORT_SYMBOL(debug_print_prefix);
 
-EXPORT_SYMBOL(acpi_cm_strncmp);
-EXPORT_SYMBOL(acpi_cm_memcpy);
-EXPORT_SYMBOL(acpi_cm_memset);
+EXPORT_SYMBOL(acpi_ut_format_exception);
 
 EXPORT_SYMBOL(acpi_get_handle);
 EXPORT_SYMBOL(acpi_get_parent);
@@ -66,6 +66,7 @@
 EXPORT_SYMBOL(acpi_get_object_info);
 EXPORT_SYMBOL(acpi_get_next_object);
 EXPORT_SYMBOL(acpi_evaluate_object);
+EXPORT_SYMBOL(acpi_get_table);
 
 EXPORT_SYMBOL(acpi_install_notify_handler);
 EXPORT_SYMBOL(acpi_remove_notify_handler);
@@ -73,6 +74,11 @@
 EXPORT_SYMBOL(acpi_remove_gpe_handler);
 EXPORT_SYMBOL(acpi_install_address_space_handler);
 EXPORT_SYMBOL(acpi_remove_address_space_handler);
+EXPORT_SYMBOL(acpi_install_fixed_event_handler);
+EXPORT_SYMBOL(acpi_remove_fixed_event_handler);
+
+EXPORT_SYMBOL(acpi_acquire_global_lock);
+EXPORT_SYMBOL(acpi_release_global_lock);
 
 EXPORT_SYMBOL(acpi_get_current_resources);
 EXPORT_SYMBOL(acpi_get_possible_resources);
@@ -81,3 +87,20 @@
 EXPORT_SYMBOL(acpi_enable_event);
 EXPORT_SYMBOL(acpi_disable_event);
 EXPORT_SYMBOL(acpi_clear_event);
+
+EXPORT_SYMBOL(acpi_get_timer_duration);
+EXPORT_SYMBOL(acpi_get_timer);
+
+EXPORT_SYMBOL(acpi_os_signal_semaphore);
+EXPORT_SYMBOL(acpi_os_create_semaphore);
+EXPORT_SYMBOL(acpi_os_delete_semaphore);
+EXPORT_SYMBOL(acpi_os_wait_semaphore);
+
+EXPORT_SYMBOL(acpi_os_in32);
+EXPORT_SYMBOL(acpi_os_out32);
+EXPORT_SYMBOL(acpi_fadt);
+EXPORT_SYMBOL(acpi_hw_register_bit_access);
+EXPORT_SYMBOL(acpi_hw_obtain_sleep_type_register_data);
+EXPORT_SYMBOL(acpi_enter_sleep_state);
+EXPORT_SYMBOL(acpi_get_system_info);
+
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/cmbatt.c linux/drivers/acpi/cmbatt.c
--- v2.4.5/linux/drivers/acpi/cmbatt.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/cmbatt.c	Wed Dec 31 16:00:00 1969
@@ -1,390 +0,0 @@
-/*
- *  cmbatt.c - Control Method Battery driver
- *
- *  Copyright (C) 2000 Andrew Grover
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-/*
- * Changes:
- * Brendan Burns <bburns@wso.williams.edu> 2000-11-15
- * - added proc battery interface
- * - parse returned data from _BST and _BIF
- * Andy Grover <andrew.grover@intel.com> 2000-12-8
- * - improved proc interface
- * Pavel Machek <pavel@suse.cz> 2001-1-31
- * - fixed oops on NULLs in return from _BIF
- */
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include "acpi.h"
-#include "driver.h"
-
-#define _COMPONENT	OS_DEPENDENT
-	MODULE_NAME	("cmbatt")
-
-/* ACPI-specific defines */
-#define ACPI_CMBATT_HID		"PNP0C0A"
-#define ACPI_BATT_PRESENT	0x10
-#define ACPI_BATT_UNKNOWN	0xFFFFFFFF
-
-/* driver-specific defines */
-#define MAX_CM_BATTERIES	0x8
-#define MAX_BATT_STRLEN		0x20
-
-#define Xstrncpy(a, b, c) if (b) strncpy(a,b,c); else strncpy(a, "unknown", c)
-
-struct cmbatt_info
-{
-	u32  power_unit;
-	u32  design_capacity;
-	u32  last_full_capacity;
-	u32  battery_technology;
-	u32  design_voltage;
-	u32  design_capacity_warning;
-	u32  design_capacity_low;
-	u32  battery_capacity_granularity_1;
-	u32  battery_capacity_granularity_2;
-
-	char model_number[MAX_BATT_STRLEN];
-	char serial_number[MAX_BATT_STRLEN];
-	char battery_type[MAX_BATT_STRLEN];
-	char oem_info[MAX_BATT_STRLEN];
-};
-
-struct cmbatt_context
-{
-	u32			is_present;
-	ACPI_HANDLE		handle;
-	char			UID[9];
-	char			*power_unit;
-	struct cmbatt_info	info;
-};
-
-struct cmbatt_status
-{
-	u32			state;
-	u32			present_rate;
-	u32			remaining_capacity;
-	u32			present_voltage;
-};
-
-static u32 batt_count = 0;
-
-static struct cmbatt_context batt_list[MAX_CM_BATTERIES];
-
-static ACPI_STATUS
-acpi_get_battery_status(ACPI_HANDLE handle, struct cmbatt_status *result)
-{
-	ACPI_OBJECT       *obj;
-	ACPI_OBJECT       *objs;
-	ACPI_BUFFER       buf;
-
-	buf.length = 0;
-	buf.pointer = NULL;		
-
-	/* determine buffer length needed */
-	if (acpi_evaluate_object(handle, "_BST", NULL, &buf) != AE_BUFFER_OVERFLOW) {
-		printk(KERN_ERR "Cmbatt: Could not get battery status struct length\n");
-		return AE_NOT_FOUND;
-	}
-
-	buf.pointer = kmalloc(buf.length, GFP_KERNEL);
-	if (!buf.pointer)
-		return AE_NO_MEMORY;
-
-	/* get the data */
-	if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_BST", NULL, &buf))) {
-		printk(KERN_ERR "Cmbatt: Could not get battery status\n");
-		kfree (buf.pointer);
-		return AE_NOT_FOUND;
-	}
-
-	obj = (ACPI_OBJECT *) buf.pointer;
-	objs = obj->package.elements;
-
-	result->state = objs[0].integer.value;
-	result->present_rate = objs[1].integer.value;
-	result->remaining_capacity = objs[2].integer.value;
-	result->present_voltage = objs[3].integer.value;
-
-	kfree(buf.pointer);
-
-	return AE_OK;
-}
-
-static ACPI_STATUS
-acpi_get_battery_info(ACPI_HANDLE handle, struct cmbatt_info *result)
-{
-	ACPI_OBJECT       *obj;
-	ACPI_OBJECT       *objs;
-	ACPI_BUFFER       buf;
-
-	buf.length = 0;
-	buf.pointer = NULL;
-
-	/* determine the length of the data */
-	if (acpi_evaluate_object(handle, "_BIF", NULL, &buf) != AE_BUFFER_OVERFLOW) {
-		printk(KERN_ERR "Cmbatt: Could not get battery info struct length\n");
-		return AE_NOT_FOUND;
-	}
-
-	buf.pointer = kmalloc(buf.length, GFP_KERNEL);
-	if (!buf.pointer)
-		return AE_NO_MEMORY;
-
-	/* get the data */
-	if (!ACPI_SUCCESS(acpi_evaluate_object(handle, "_BIF", NULL, &buf))) {
-		printk(KERN_ERR "Cmbatt: Could not get battery info\n");
-		kfree (buf.pointer);
-		return AE_NOT_FOUND;
-	}
-	
-	obj = (ACPI_OBJECT *) buf.pointer;
-	objs = obj->package.elements;
-	
-	result->power_unit=objs[0].integer.value;
-	result->design_capacity=objs[1].integer.value;
-	result->last_full_capacity=objs[2].integer.value;
-	result->battery_technology=objs[3].integer.value;
-	result->design_voltage=objs[4].integer.value;
-	result->design_capacity_warning=objs[5].integer.value;
-	result->design_capacity_low=objs[6].integer.value;
-	result->battery_capacity_granularity_1=objs[7].integer.value;
-	result->battery_capacity_granularity_2=objs[8].integer.value;
-
- 	/* BUG: trailing NULL issue */
-	Xstrncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
-	Xstrncpy(result->serial_number, objs[10].string.pointer, MAX_BATT_STRLEN-1);
-	Xstrncpy(result->battery_type, objs[11].string.pointer, MAX_BATT_STRLEN-1);
-	Xstrncpy(result->oem_info, objs[12].string.pointer, MAX_BATT_STRLEN-1);
-	
-	kfree(buf.pointer);
-
-	return AE_OK;
-}
-
-/*
- * We found a device with the correct HID
- */
-static ACPI_STATUS
-acpi_found_cmbatt(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
-{
-	ACPI_DEVICE_INFO	info;
-
-	if (batt_count >= MAX_CM_BATTERIES) {
-		printk(KERN_ERR "Cmbatt: MAX_CM_BATTERIES exceeded\n");
-		return AE_OK;
-	}
-
-	if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-		printk(KERN_ERR "Cmbatt: Could not get battery object info\n");
-		return (AE_OK);
-	}
-
-	if (info.valid & ACPI_VALID_UID) {
-		strncpy(batt_list[batt_count].UID, info.unique_id, 9);
-	}
-	else if (batt_count > 1) {
-		printk(KERN_WARNING "Cmbatt: No UID but more than 1 battery\n");
-	}
-	
-	if (!(info.valid & ACPI_VALID_STA)) {
-		printk(KERN_ERR "Cmbatt: Battery _STA invalid\n");
-		return AE_OK;
-	}
-
-	if (!(info.current_status & ACPI_BATT_PRESENT)) {
-		printk(KERN_INFO "Cmbatt: Battery socket %d empty\n", batt_count);
-		batt_list[batt_count].is_present = FALSE;
-	}
-	else {
-		printk(KERN_INFO "Cmbatt: Battery socket %d occupied\n", batt_count);
-		batt_list[batt_count].is_present = TRUE;
-		if (acpi_get_battery_info(handle, &batt_list[batt_count].info) != AE_OK) {
-			printk(KERN_ERR "acpi_get_battery_info failed\n");
-			return AE_OK;
-		}
-
-		batt_list[batt_count].power_unit = (batt_list[batt_count].info.power_unit) ? "mA" : "mW";
-	}
-	
-	batt_list[batt_count].handle = handle;
-
-	batt_count++;
-
-	return AE_OK;
-}
-
-static int
-proc_read_batt_info(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	struct cmbatt_info *info;
-	u32 batt_num = (u32) data;
-	char *p = page;
-	int len;
-
-	info = &batt_list[batt_num].info;
-
-	/* don't get info more than once for a single proc read */
-	if (off != 0)
-		goto end;
-
-	if (!batt_list[batt_num].is_present) {
-		p += sprintf(p, "battery %d not present\n", batt_num);
-		goto end;
-	}
-
-	if (info->last_full_capacity != ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Last Full Capacity: %d %sh\n", 
-		     info->last_full_capacity, batt_list[batt_num].power_unit);
-
-	if (info->design_capacity != ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Design Capacity:    %d %sh\n", 
-		     info->design_capacity, batt_list[batt_num].power_unit);
-	
-	if (info->battery_technology)
-		p += sprintf(p, "Battery Technology: Secondary\n");
-	else
-		p += sprintf(p, "Battery Technology: Primary\n");
-	
-	if (info->design_voltage != ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Design Voltage:     %d mV\n", 
-		     info->design_voltage);
-	
-	p += sprintf(p, "Design Capacity Warning:    %d %sh\n",
-		info->design_capacity_warning, batt_list[batt_num].power_unit);
-	p += sprintf(p, "Design Capacity Low:        %d %sh\n",
-		info->design_capacity_low, batt_list[batt_num].power_unit);
-	p += sprintf(p, "Battery Capacity Granularity 1: %d\n",
-		info->battery_capacity_granularity_1);
-	p += sprintf(p, "Battery Capacity Granularity 2: %d\n",
-		info->battery_capacity_granularity_2);
-	p += sprintf(p, "Model number; %s\nSerial number: %s\nBattery type: %s\nOEM info: %s\n",
-		info->model_number,info->serial_number,
-		info->battery_type,info->oem_info);
-end:
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-	return len;
-}
-
-static int
-proc_read_batt_status(char *page, char **start, off_t off,
-			int count, int *eof, void *data)
-{
-	struct cmbatt_status status;
-	u32 batt_num = (u32) data;
-	char *p = page;
-	int len;
-
-	/* don't get status more than once for a single proc read */
-	if (off != 0)
-		goto end;
-
-	if (!batt_list[batt_num].is_present) {
-		p += sprintf(p, "battery %d not present\n", batt_num);
-		goto end;
-	}
-
-	if (acpi_get_battery_status(batt_list[batt_num].handle, &status) != AE_OK) {
-		printk(KERN_ERR "Cmbatt: acpi_get_battery_status failed\n");
-		goto end;
-	}
-
-	p += sprintf(p, "Battery discharging:        %s\n",
-		     (status.state & 0x1)?"yes":"no");
-	p += sprintf(p, "Battery charging:           %s\n",
-		     (status.state & 0x2)?"yes":"no");
-	p += sprintf(p, "Battery critically low:     %s\n",
-		     (status.state & 0x4)?"yes":"no");
-
-	if (status.present_rate != ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Battery rate:               %d %s\n",
-			status.present_rate, batt_list[batt_num].power_unit);
-
-	if (status.remaining_capacity != ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Battery capacity:           %d %sh\n",
-			status.remaining_capacity, batt_list[batt_num].power_unit);
-
-	if (status.present_voltage != ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Battery voltage:            %d mV\n",
-			status.present_voltage);
-
-end:
-
-	len = (p - page);
-	if (len <= off+count) *eof = 1;
-	*start = page + off;
-	len -= off;
-	if (len>count) len = count;
-	if (len<0) len = 0;
-	return len;
-}
-
-
-
-int
-acpi_cmbatt_init(void)
-{
-	int i;
-
-	acpi_get_devices(ACPI_CMBATT_HID, 
-			acpi_found_cmbatt,
-			NULL,
-			NULL);
-
-	for (i = 0; i < batt_count; i++) {
-
-		char batt_name[20];
-
-		sprintf(batt_name, "power/batt%d_info", i);
-		create_proc_read_entry(batt_name, 0, NULL,
-			proc_read_batt_info, (void *) i);
-
-		sprintf(batt_name, "power/batt%d_status", i);
-		create_proc_read_entry(batt_name, 0, NULL,
-			proc_read_batt_status, (void *) i);
-
-	}
-
-	return 0;
-}
-
-int
-acpi_cmbatt_terminate(void)
-{
-	int i;
-
-	for (i = 0; i < batt_count; i++) {
-
-		char batt_name[20];
-
-		sprintf(batt_name, "power/batt%d_info", i);
-		remove_proc_entry(batt_name, NULL);
-
-		sprintf(batt_name, "power/batt%d_status", i);
-		remove_proc_entry(batt_name, NULL);
-	}
-
-	return 0;
-}
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/Makefile linux/drivers/acpi/common/Makefile
--- v2.4.5/linux/drivers/acpi/common/Makefile	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/common/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,16 +0,0 @@
-#
-# Makefile for all Linux ACPI interpreter subdirectories
-#
-
-O_TARGET := ../$(shell basename `pwd`).o
-
-obj-$(CONFIG_ACPI) := $(patsubst %.c,%.o,$(wildcard *.c))
-
-EXTRA_CFLAGS += -I../include
-
-EXTRA_CFLAGS += $(ACPI_CFLAGS)
-
-include $(TOPDIR)/Rules.make
-
-clean:
-	$(RM) *.o 
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmalloc.c linux/drivers/acpi/common/cmalloc.c
--- v2.4.5/linux/drivers/acpi/common/cmalloc.c	Mon Jan 29 10:15:58 2001
+++ linux/drivers/acpi/common/cmalloc.c	Wed Dec 31 16:00:00 1969
@@ -1,170 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmalloc - local memory allocation routines
- *              $Revision: 84 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acparser.h"
-#include "acinterp.h"
-#include "acnamesp.h"
-#include "acglobal.h"
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmalloc")
-
-
-/*****************************************************************************
- *
- * FUNCTION:    _Cm_allocate
- *
- * PARAMETERS:  Size                - Size of the allocation
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: The subsystem's equivalent of malloc.
- *
- ****************************************************************************/
-
-void *
-_cm_allocate (
-	u32                     size,
-	u32                     component,
-	NATIVE_CHAR             *module,
-	u32                     line)
-{
-	void                    *address = NULL;
-
-
-	/* Check for an inadvertent size of zero bytes */
-
-	if (!size) {
-		_REPORT_ERROR (module, line, component,
-				("Cm_allocate: Attempt to allocate zero bytes\n"));
-		size = 1;
-	}
-
-	address = acpi_os_allocate (size);
-	if (!address) {
-		/* Report allocation error */
-
-		_REPORT_ERROR (module, line, component,
-				("Cm_allocate: Could not allocate size %X\n", size));
-
-		return (NULL);
-	}
-
-
-	return (address);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    _Cm_callocate
- *
- * PARAMETERS:  Size                - Size of the allocation
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      Address of the allocated memory on success, NULL on failure.
- *
- * DESCRIPTION: Subsystem equivalent of calloc.
- *
- ****************************************************************************/
-
-void *
-_cm_callocate (
-	u32                     size,
-	u32                     component,
-	NATIVE_CHAR             *module,
-	u32                     line)
-{
-	void                    *address = NULL;
-
-
-	/* Check for an inadvertent size of zero bytes */
-
-	if (!size) {
-		_REPORT_ERROR (module, line, component,
-				("Cm_callocate: Attempt to allocate zero bytes\n"));
-		return (NULL);
-	}
-
-
-	address = acpi_os_callocate (size);
-
-	if (!address) {
-		/* Report allocation error */
-
-		_REPORT_ERROR (module, line, component,
-				("Cm_callocate: Could not allocate size %X\n", size));
-		return (NULL);
-	}
-
-
-	return (address);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    _Cm_free
- *
- * PARAMETERS:  Address             - Address of the memory to deallocate
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *
- * RETURN:      None
- *
- * DESCRIPTION: Frees the memory at Address
- *
- ****************************************************************************/
-
-void
-_cm_free (
-	void                    *address,
-	u32                     component,
-	NATIVE_CHAR             *module,
-	u32                     line)
-{
-
-	if (NULL == address) {
-		_REPORT_ERROR (module, line, component,
-			("_Cm_free: Trying to delete a NULL address\n"));
-
-		return;
-	}
-
-
-	acpi_os_free (address);
-
-	return;
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmclib.c linux/drivers/acpi/common/cmclib.c
--- v2.4.5/linux/drivers/acpi/common/cmclib.c	Mon Jan 22 13:23:42 2001
+++ linux/drivers/acpi/common/cmclib.c	Wed Dec 31 16:00:00 1969
@@ -1,818 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmclib - Local implementation of C library functions
- * $Revision: 32 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acevents.h"
-#include "achware.h"
-#include "acnamesp.h"
-#include "acinterp.h"
-#include "amlcode.h"
-
-/*
- * These implementations of standard C Library routines can optionally be
- * used if a C library is not available.  In general, they are less efficient
- * than an inline or assembly implementation
- */
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmclib")
-
-
-#ifndef ACPI_USE_SYSTEM_CLIBRARY
-
-/*******************************************************************************
- *
- * FUNCTION:    strlen
- *
- * PARAMETERS:  String              - Null terminated string
- *
- * RETURN:      Length
- *
- * DESCRIPTION: Returns the length of the input string
- *
- ******************************************************************************/
-
-
-NATIVE_UINT
-acpi_cm_strlen (
-	const NATIVE_CHAR       *string)
-{
-	NATIVE_UINT             length = 0;
-
-
-	/* Count the string until a null is encountered */
-
-	while (*string) {
-		length++;
-		string++;
-	}
-
-	return (length);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strcpy
- *
- * PARAMETERS:  Dst_string      - Target of the copy
- *              Src_string      - The source string to copy
- *
- * RETURN:      Dst_string
- *
- * DESCRIPTION: Copy a null terminated string
- *
- ******************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_strcpy (
-	NATIVE_CHAR             *dst_string,
-	const NATIVE_CHAR       *src_string)
-{
-	NATIVE_CHAR             *string = dst_string;
-
-
-	/* Move bytes brute force */
-
-	while (*src_string) {
-		*string = *src_string;
-
-		string++;
-		src_string++;
-	}
-
-	/* Null terminate */
-
-	*string = 0;
-
-	return (dst_string);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strncpy
- *
- * PARAMETERS:  Dst_string      - Target of the copy
- *              Src_string      - The source string to copy
- *              Count           - Maximum # of bytes to copy
- *
- * RETURN:      Dst_string
- *
- * DESCRIPTION: Copy a null terminated string, with a maximum length
- *
- ******************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_strncpy (
-	NATIVE_CHAR             *dst_string,
-	const NATIVE_CHAR       *src_string,
-	NATIVE_UINT             count)
-{
-	NATIVE_CHAR             *string = dst_string;
-
-
-	/* Copy the string */
-
-	for (string = dst_string;
-		count && (count--, (*string++ = *src_string++)); )
-	{;}
-
-	/* Pad with nulls if necessary */
-
-	while (count--) {
-		*string = 0;
-		string++;
-	}
-
-	/* Return original pointer */
-
-	return (dst_string);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strcmp
- *
- * PARAMETERS:  String1         - First string
- *              String2         - Second string
- *
- * RETURN:      Index where strings mismatched, or 0 if strings matched
- *
- * DESCRIPTION: Compare two null terminated strings
- *
- ******************************************************************************/
-
-u32
-acpi_cm_strcmp (
-	const NATIVE_CHAR       *string1,
-	const NATIVE_CHAR       *string2)
-{
-
-
-	for ( ; (*string1 == *string2); string2++) {
-		if (!*string1++) {
-			return (0);
-		}
-	}
-
-
-	return ((unsigned char) *string1 - (unsigned char) *string2);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strncmp
- *
- * PARAMETERS:  String1         - First string
- *              String2         - Second string
- *              Count           - Maximum # of bytes to compare
- *
- * RETURN:      Index where strings mismatched, or 0 if strings matched
- *
- * DESCRIPTION: Compare two null terminated strings, with a maximum length
- *
- ******************************************************************************/
-
-u32
-acpi_cm_strncmp (
-	const NATIVE_CHAR       *string1,
-	const NATIVE_CHAR       *string2,
-	NATIVE_UINT             count)
-{
-
-
-	for ( ; count-- && (*string1 == *string2); string2++) {
-		if (!*string1++) {
-			return (0);
-		}
-	}
-
-	return ((count == -1) ? 0 : ((unsigned char) *string1 -
-		(unsigned char) *string2));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Strcat
- *
- * PARAMETERS:  Dst_string      - Target of the copy
- *              Src_string      - The source string to copy
- *
- * RETURN:      Dst_string
- *
- * DESCRIPTION: Append a null terminated string to a null terminated string
- *
- ******************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_strcat (
-	NATIVE_CHAR             *dst_string,
-	const NATIVE_CHAR       *src_string)
-{
-	NATIVE_CHAR             *string;
-
-
-	/* Find end of the destination string */
-
-	for (string = dst_string; *string++; ) { ; }
-
-	/* Concatinate the string */
-
-	for (--string; (*string++ = *src_string++); ) { ; }
-
-	return (dst_string);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strncat
- *
- * PARAMETERS:  Dst_string      - Target of the copy
- *              Src_string      - The source string to copy
- *              Count           - Maximum # of bytes to copy
- *
- * RETURN:      Dst_string
- *
- * DESCRIPTION: Append a null terminated string to a null terminated string,
- *              with a maximum count.
- *
- ******************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_strncat (
-	NATIVE_CHAR             *dst_string,
-	const NATIVE_CHAR       *src_string,
-	NATIVE_UINT             count)
-{
-	NATIVE_CHAR             *string;
-
-
-	if (count) {
-		/* Find end of the destination string */
-
-		for (string = dst_string; *string++; ) { ; }
-
-		/* Concatinate the string */
-
-		for (--string; (*string++ = *src_string++) && --count; ) { ; }
-
-		/* Null terminate if necessary */
-
-		if (!count) {
-			*string = 0;
-		}
-	}
-
-	return (dst_string);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    memcpy
- *
- * PARAMETERS:  Dest        - Target of the copy
- *              Src         - Source buffer to copy
- *              Count       - Number of bytes to copy
- *
- * RETURN:      Dest
- *
- * DESCRIPTION: Copy arbitrary bytes of memory
- *
- ******************************************************************************/
-
-void *
-acpi_cm_memcpy (
-	void                    *dest,
-	const void              *src,
-	NATIVE_UINT             count)
-{
-	NATIVE_CHAR             *new = (NATIVE_CHAR *) dest;
-	NATIVE_CHAR             *old = (NATIVE_CHAR *) src;
-
-
-	while (count) {
-		*new = *old;
-		new++;
-		old++;
-		count--;
-	}
-
-	return (dest);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    memset
- *
- * PARAMETERS:  Dest        - Buffer to set
- *              Value       - Value to set each byte of memory
- *              Count       - Number of bytes to set
- *
- * RETURN:      Dest
- *
- * DESCRIPTION: Initialize a buffer to a known value.
- *
- ******************************************************************************/
-
-void *
-acpi_cm_memset (
-	void                    *dest,
-	NATIVE_UINT             value,
-	NATIVE_UINT             count)
-{
-	NATIVE_CHAR             *new = (NATIVE_CHAR *) dest;
-
-
-	while (count) {
-		*new = (char) value;
-		new++;
-		count--;
-	}
-
-	return (dest);
-}
-
-
-#define NEGATIVE    1
-#define POSITIVE    0
-
-
-#define _ACPI_XA     0x00    /* extra alphabetic - not supported */
-#define _ACPI_XS     0x40    /* extra space */
-#define _ACPI_BB     0x00    /* BEL, BS, etc. - not supported */
-#define _ACPI_CN     0x20    /* CR, FF, HT, NL, VT */
-#define _ACPI_DI     0x04    /* '0'-'9' */
-#define _ACPI_LO     0x02    /* 'a'-'z' */
-#define _ACPI_PU     0x10    /* punctuation */
-#define _ACPI_SP     0x08    /* space */
-#define _ACPI_UP     0x01    /* 'A'-'Z' */
-#define _ACPI_XD     0x80    /* '0'-'9', 'A'-'F', 'a'-'f' */
-
-static const u8 _acpi_ctype[257] = {
-	_ACPI_CN,            /* 0x0      0.     */
-	_ACPI_CN,            /* 0x1      1.     */
-	_ACPI_CN,            /* 0x2      2.     */
-	_ACPI_CN,            /* 0x3      3.     */
-	_ACPI_CN,            /* 0x4      4.     */
-	_ACPI_CN,            /* 0x5      5.     */
-	_ACPI_CN,            /* 0x6      6.     */
-	_ACPI_CN,            /* 0x7      7.     */
-	_ACPI_CN,            /* 0x8      8.     */
-	_ACPI_CN|_ACPI_SP,   /* 0x9      9.     */
-	_ACPI_CN|_ACPI_SP,   /* 0xA     10.     */
-	_ACPI_CN|_ACPI_SP,   /* 0xB     11.     */
-	_ACPI_CN|_ACPI_SP,   /* 0xC     12.     */
-	_ACPI_CN|_ACPI_SP,   /* 0xD     13.     */
-	_ACPI_CN,            /* 0xE     14.     */
-	_ACPI_CN,            /* 0xF     15.     */
-	_ACPI_CN,            /* 0x10    16.     */
-	_ACPI_CN,            /* 0x11    17.     */
-	_ACPI_CN,            /* 0x12    18.     */
-	_ACPI_CN,            /* 0x13    19.     */
-	_ACPI_CN,            /* 0x14    20.     */
-	_ACPI_CN,            /* 0x15    21.     */
-	_ACPI_CN,            /* 0x16    22.     */
-	_ACPI_CN,            /* 0x17    23.     */
-	_ACPI_CN,            /* 0x18    24.     */
-	_ACPI_CN,            /* 0x19    25.     */
-	_ACPI_CN,            /* 0x1A    26.     */
-	_ACPI_CN,            /* 0x1B    27.     */
-	_ACPI_CN,            /* 0x1C    28.     */
-	_ACPI_CN,            /* 0x1D    29.     */
-	_ACPI_CN,            /* 0x1E    30.     */
-	_ACPI_CN,            /* 0x1F    31.     */
-	_ACPI_XS|_ACPI_SP,   /* 0x20    32. ' ' */
-	_ACPI_PU,            /* 0x21    33. '!' */
-	_ACPI_PU,            /* 0x22    34. '"' */
-	_ACPI_PU,            /* 0x23    35. '#' */
-	_ACPI_PU,            /* 0x24    36. '$' */
-	_ACPI_PU,            /* 0x25    37. '%' */
-	_ACPI_PU,            /* 0x26    38. '&' */
-	_ACPI_PU,            /* 0x27    39. ''' */
-	_ACPI_PU,            /* 0x28    40. '(' */
-	_ACPI_PU,            /* 0x29    41. ')' */
-	_ACPI_PU,            /* 0x2A    42. '*' */
-	_ACPI_PU,            /* 0x2B    43. '+' */
-	_ACPI_PU,            /* 0x2C    44. ',' */
-	_ACPI_PU,            /* 0x2D    45. '-' */
-	_ACPI_PU,            /* 0x2E    46. '.' */
-	_ACPI_PU,            /* 0x2F    47. '/' */
-	_ACPI_XD|_ACPI_DI,   /* 0x30    48. '0' */
-	_ACPI_XD|_ACPI_DI,   /* 0x31    49. '1' */
-	_ACPI_XD|_ACPI_DI,   /* 0x32    50. '2' */
-	_ACPI_XD|_ACPI_DI,   /* 0x33    51. '3' */
-	_ACPI_XD|_ACPI_DI,   /* 0x34    52. '4' */
-	_ACPI_XD|_ACPI_DI,   /* 0x35    53. '5' */
-	_ACPI_XD|_ACPI_DI,   /* 0x36    54. '6' */
-	_ACPI_XD|_ACPI_DI,   /* 0x37    55. '7' */
-	_ACPI_XD|_ACPI_DI,   /* 0x38    56. '8' */
-	_ACPI_XD|_ACPI_DI,   /* 0x39    57. '9' */
-	_ACPI_PU,            /* 0x3A    58. ':' */
-	_ACPI_PU,            /* 0x3B    59. ';' */
-	_ACPI_PU,            /* 0x3C    60. '<' */
-	_ACPI_PU,            /* 0x3D    61. '=' */
-	_ACPI_PU,            /* 0x3E    62. '>' */
-	_ACPI_PU,            /* 0x3F    63. '?' */
-	_ACPI_PU,            /* 0x40    64. '@' */
-	_ACPI_XD|_ACPI_UP,   /* 0x41    65. 'A' */
-	_ACPI_XD|_ACPI_UP,   /* 0x42    66. 'B' */
-	_ACPI_XD|_ACPI_UP,   /* 0x43    67. 'C' */
-	_ACPI_XD|_ACPI_UP,   /* 0x44    68. 'D' */
-	_ACPI_XD|_ACPI_UP,   /* 0x45    69. 'E' */
-	_ACPI_XD|_ACPI_UP,   /* 0x46    70. 'F' */
-	_ACPI_UP,            /* 0x47    71. 'G' */
-	_ACPI_UP,            /* 0x48    72. 'H' */
-	_ACPI_UP,            /* 0x49    73. 'I' */
-	_ACPI_UP,            /* 0x4A    74. 'J' */
-	_ACPI_UP,            /* 0x4B    75. 'K' */
-	_ACPI_UP,            /* 0x4C    76. 'L' */
-	_ACPI_UP,            /* 0x4D    77. 'M' */
-	_ACPI_UP,            /* 0x4E    78. 'N' */
-	_ACPI_UP,            /* 0x4F    79. 'O' */
-	_ACPI_UP,            /* 0x50    80. 'P' */
-	_ACPI_UP,            /* 0x51    81. 'Q' */
-	_ACPI_UP,            /* 0x52    82. 'R' */
-	_ACPI_UP,            /* 0x53    83. 'S' */
-	_ACPI_UP,            /* 0x54    84. 'T' */
-	_ACPI_UP,            /* 0x55    85. 'U' */
-	_ACPI_UP,            /* 0x56    86. 'V' */
-	_ACPI_UP,            /* 0x57    87. 'W' */
-	_ACPI_UP,            /* 0x58    88. 'X' */
-	_ACPI_UP,            /* 0x59    89. 'Y' */
-	_ACPI_UP,            /* 0x5A    90. 'Z' */
-	_ACPI_PU,            /* 0x5B    91. '[' */
-	_ACPI_PU,            /* 0x5C    92. '\' */
-	_ACPI_PU,            /* 0x5D    93. ']' */
-	_ACPI_PU,            /* 0x5E    94. '^' */
-	_ACPI_PU,            /* 0x5F    95. '_' */
-	_ACPI_PU,            /* 0x60    96. '`' */
-	_ACPI_XD|_ACPI_LO,   /* 0x61    97. 'a' */
-	_ACPI_XD|_ACPI_LO,   /* 0x62    98. 'b' */
-	_ACPI_XD|_ACPI_LO,   /* 0x63    99. 'c' */
-	_ACPI_XD|_ACPI_LO,   /* 0x64   100. 'd' */
-	_ACPI_XD|_ACPI_LO,   /* 0x65   101. 'e' */
-	_ACPI_XD|_ACPI_LO,   /* 0x66   102. 'f' */
-	_ACPI_LO,            /* 0x67   103. 'g' */
-	_ACPI_LO,            /* 0x68   104. 'h' */
-	_ACPI_LO,            /* 0x69   105. 'i' */
-	_ACPI_LO,            /* 0x6A   106. 'j' */
-	_ACPI_LO,            /* 0x6B   107. 'k' */
-	_ACPI_LO,            /* 0x6C   108. 'l' */
-	_ACPI_LO,            /* 0x6D   109. 'm' */
-	_ACPI_LO,            /* 0x6E   110. 'n' */
-	_ACPI_LO,            /* 0x6F   111. 'o' */
-	_ACPI_LO,            /* 0x70   112. 'p' */
-	_ACPI_LO,            /* 0x71   113. 'q' */
-	_ACPI_LO,            /* 0x72   114. 'r' */
-	_ACPI_LO,            /* 0x73   115. 's' */
-	_ACPI_LO,            /* 0x74   116. 't' */
-	_ACPI_LO,            /* 0x75   117. 'u' */
-	_ACPI_LO,            /* 0x76   118. 'v' */
-	_ACPI_LO,            /* 0x77   119. 'w' */
-	_ACPI_LO,            /* 0x78   120. 'x' */
-	_ACPI_LO,            /* 0x79   121. 'y' */
-	_ACPI_LO,            /* 0x7A   122. 'z' */
-	_ACPI_PU,            /* 0x7B   123. '{' */
-	_ACPI_PU,            /* 0x7C   124. '|' */
-	_ACPI_PU,            /* 0x7D   125. '}' */
-	_ACPI_PU,            /* 0x7E   126. '~' */
-	_ACPI_CN,            /* 0x7F   127.     */
-
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0x80 to 0x8F    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0x90 to 0x9F    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xA0 to 0xAF    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xB0 to 0xBF    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xC0 to 0xCF    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xD0 to 0xDF    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,  /* 0xE0 to 0xEF    */
-	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xF0 to 0x100   */
-};
-
-#define IS_UPPER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_UP))
-#define IS_LOWER(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_LO))
-#define IS_DIGIT(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_DI))
-#define IS_SPACE(c)  (_acpi_ctype[(unsigned char)(c)] & (_ACPI_SP))
-#define IS_XDIGIT(c) (_acpi_ctype[(unsigned char)(c)] & (_ACPI_XD))
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_to_upper
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION: Convert character to uppercase
- *
- ******************************************************************************/
-
-u32
-acpi_cm_to_upper (
-	u32                     c)
-{
-
-	return (IS_LOWER(c) ? ((c)-0x20) : (c));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_to_lower
- *
- * PARAMETERS:
- *
- * RETURN:
- *
- * DESCRIPTION: Convert character to lowercase
- *
- ******************************************************************************/
-
-u32
-acpi_cm_to_lower (
-	u32                     c)
-{
-
-	return (IS_UPPER(c) ? ((c)+0x20) : (c));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strupr
- *
- * PARAMETERS:  Src_string      - The source string to convert to
- *
- * RETURN:      Src_string
- *
- * DESCRIPTION: Convert string to uppercase
- *
- ******************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_strupr (
-	NATIVE_CHAR             *src_string)
-{
-	NATIVE_CHAR             *string;
-
-
-	/* Walk entire string, uppercasing the letters */
-
-	for (string = src_string; *string; ) {
-		*string = (char) acpi_cm_to_upper (*string);
-		string++;
-	}
-
-
-	return (src_string);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strstr
- *
- * PARAMETERS:  String1       -
- *              String2
- *
- * RETURN:
- *
- * DESCRIPTION: Checks if String2 occurs in String1. This is not really a
- *              full implementation of strstr, only sufficient for command
- *              matching
- *
- ******************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_strstr (
-	NATIVE_CHAR             *string1,
-	NATIVE_CHAR             *string2)
-{
-	NATIVE_CHAR             *string;
-
-
-	if (acpi_cm_strlen (string2) > acpi_cm_strlen (string1)) {
-		return (NULL);
-	}
-
-	/* Walk entire string, comparing the letters */
-
-	for (string = string1; *string2; ) {
-		if (*string2 != *string) {
-			return (NULL);
-		}
-
-		string2++;
-		string++;
-	}
-
-
-	return (string1);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    strtoul
- *
- * PARAMETERS:  String          - Null terminated string
- *              Terminater      - Where a pointer to the terminating byte is returned
- *              Base            - Radix of the string
- *
- * RETURN:      Converted value
- *
- * DESCRIPTION: Convert a string into an unsigned value.
- *
- ******************************************************************************/
-
-u32
-acpi_cm_strtoul (
-	const NATIVE_CHAR       *string,
-	NATIVE_CHAR             **terminator,
-	NATIVE_UINT             base)
-{
-	u32                     converted = 0;
-	u32                     index;
-	u32                     sign;
-	const NATIVE_CHAR       *string_start;
-	u32                     return_value = 0;
-	ACPI_STATUS             status = AE_OK;
-
-
-	/*
-	 * Save the value of the pointer to the buffer's first
-	 * character, save the current errno value, and then
-	 * skip over any white space in the buffer:
-	 */
-	string_start = string;
-	while (IS_SPACE (*string) || *string == '\t') {
-		++string;
-	}
-
-	/*
-	 * The buffer may contain an optional plus or minus sign.
-	 * If it does, then skip over it but remember what is was:
-	 */
-	if (*string == '-') {
-		sign = NEGATIVE;
-		++string;
-	}
-
-	else if (*string == '+') {
-		++string;
-		sign = POSITIVE;
-	}
-
-	else {
-		sign = POSITIVE;
-	}
-
-	/*
-	 * If the input parameter Base is zero, then we need to
-	 * determine if it is octal, decimal, or hexadecimal:
-	 */
-	if (base == 0) {
-		if (*string == '0') {
-			if (acpi_cm_to_lower (*(++string)) == 'x') {
-				base = 16;
-				++string;
-			}
-
-			else {
-				base = 8;
-			}
-		}
-
-		else {
-			base = 10;
-		}
-	}
-
-	else if (base < 2 || base > 36) {
-		/*
-		 * The specified Base parameter is not in the domain of
-		 * this function:
-		 */
-		goto done;
-	}
-
-	/*
-	 * For octal and hexadecimal bases, skip over the leading
-	 * 0 or 0x, if they are present.
-	 */
-	if (base == 8 && *string == '0') {
-		string++;
-	}
-
-	if (base == 16 &&
-		*string == '0' &&
-		acpi_cm_to_lower (*(++string)) == 'x')
-	{
-		string++;
-	}
-
-
-	/*
-	 * Main loop: convert the string to an unsigned long:
-	 */
-	while (*string) {
-		if (IS_DIGIT (*string)) {
-			index = *string - '0';
-		}
-
-		else {
-			index = acpi_cm_to_upper (*string);
-			if (IS_UPPER (index)) {
-				index = index - 'A' + 10;
-			}
-
-			else {
-				goto done;
-			}
-		}
-
-		if (index >= base) {
-			goto done;
-		}
-
-		/*
-		 * Check to see if value is out of range:
-		 */
-
-		if (return_value > ((ACPI_UINT32_MAX - (u32) index) /
-				   (u32) base))
-		{
-			status = AE_ERROR;
-			return_value = 0L;          /* reset */
-		}
-
-		else {
-			return_value *= base;
-			return_value += index;
-			converted = 1;
-		}
-
-		++string;
-	}
-
-done:
-	/*
-	 * If appropriate, update the caller's pointer to the next
-	 * unconverted character in the buffer.
-	 */
-	if (terminator) {
-		if (converted == 0 && return_value == 0L && string != NULL) {
-			*terminator = (NATIVE_CHAR *) string_start;
-		}
-
-		else {
-			*terminator = (NATIVE_CHAR *) string;
-		}
-	}
-
-	if (status == AE_ERROR) {
-		return_value = ACPI_UINT32_MAX;
-	}
-
-	/*
-	 * If a minus sign was present, then "the conversion is negated":
-	 */
-	if (sign == NEGATIVE) {
-		return_value = (ACPI_UINT32_MAX - return_value) + 1;
-	}
-
-	return (return_value);
-}
-
-#endif /* ACPI_USE_SYSTEM_CLIBRARY */
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmcopy.c linux/drivers/acpi/common/cmcopy.c
--- v2.4.5/linux/drivers/acpi/common/cmcopy.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/common/cmcopy.c	Wed Dec 31 16:00:00 1969
@@ -1,708 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmcopy - Internal to external object translation utilities
- *              $Revision: 66 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acinterp.h"
-#include "acnamesp.h"
-#include "amlcode.h"
-
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmcopy")
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_isimple_to_esimple
- *
- * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
- *              *Buffer             - Where the object is returned
- *              *Space_used         - Where the data length is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to place a simple object in a user
- *              buffer.
- *
- *              The buffer is assumed to have sufficient space for the object.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-acpi_cm_copy_isimple_to_esimple (
-	ACPI_OPERAND_OBJECT     *internal_object,
-	ACPI_OBJECT             *external_object,
-	u8                      *data_space,
-	u32                     *buffer_space_used)
-{
-	u32                     length = 0;
-	ACPI_STATUS             status = AE_OK;
-
-
-	/*
-	 * Check for NULL object case (could be an uninitialized
-	 * package element
-	 */
-
-	if (!internal_object) {
-		*buffer_space_used = 0;
-		return (AE_OK);
-	}
-
-	/* Always clear the external object */
-
-	MEMSET (external_object, 0, sizeof (ACPI_OBJECT));
-
-	/*
-	 * In general, the external object will be the same type as
-	 * the internal object
-	 */
-
-	external_object->type = internal_object->common.type;
-
-	/* However, only a limited number of external types are supported */
-
-	switch (internal_object->common.type)
-	{
-
-	case ACPI_TYPE_STRING:
-
-		length = internal_object->string.length + 1;
-		external_object->string.length = internal_object->string.length;
-		external_object->string.pointer = (NATIVE_CHAR *) data_space;
-		MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, length);
-		break;
-
-
-	case ACPI_TYPE_BUFFER:
-
-		length = internal_object->buffer.length;
-		external_object->buffer.length = internal_object->buffer.length;
-		external_object->buffer.pointer = data_space;
-		MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer, length);
-		break;
-
-
-	case ACPI_TYPE_INTEGER:
-
-		external_object->integer.value= internal_object->integer.value;
-		break;
-
-
-	case INTERNAL_TYPE_REFERENCE:
-
-		/*
-		 * This is an object reference.  Attempt to dereference it.
-		 */
-
-		switch (internal_object->reference.op_code)
-		{
-		case AML_ZERO_OP:
-			external_object->type = ACPI_TYPE_INTEGER;
-			external_object->integer.value = 0;
-			break;
-
-		case AML_ONE_OP:
-			external_object->type = ACPI_TYPE_INTEGER;
-			external_object->integer.value = 1;
-			break;
-
-		case AML_ONES_OP:
-			external_object->type = ACPI_TYPE_INTEGER;
-			external_object->integer.value = ACPI_INTEGER_MAX;
-			break;
-
-		case AML_NAMEPATH_OP:
-			/*
-			 * This is a named reference, get the string.  We already know that
-			 * we have room for it, use max length
-			 */
-			length = MAX_STRING_LENGTH;
-			external_object->type = ACPI_TYPE_STRING;
-			external_object->string.pointer = (NATIVE_CHAR *) data_space;
-			status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) internal_object->reference.node,
-					 &length, (char *) data_space);
-			break;
-
-		default:
-			/*
-			 * Use the object type of "Any" to indicate a reference
-			 * to object containing a handle to an ACPI named object.
-			 */
-			external_object->type = ACPI_TYPE_ANY;
-			external_object->reference.handle = internal_object->reference.node;
-			break;
-		}
-		break;
-
-
-	case ACPI_TYPE_PROCESSOR:
-
-		external_object->processor.proc_id = internal_object->processor.proc_id;
-		external_object->processor.pblk_address = internal_object->processor.address;
-		external_object->processor.pblk_length = internal_object->processor.length;
-		break;
-
-
-	case ACPI_TYPE_POWER:
-
-		external_object->power_resource.system_level =
-				   internal_object->power_resource.system_level;
-
-		external_object->power_resource.resource_order =
-				   internal_object->power_resource.resource_order;
-		break;
-
-
-	default:
-		/*
-		 * There is no corresponding external object type
-		 */
-		return (AE_SUPPORT);
-		break;
-	}
-
-
-	*buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length);
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_ielement_to_eelement
- *
- * PARAMETERS:  ACPI_PKG_CALLBACK
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Copy one package element to another package element
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_copy_ielement_to_eelement (
-	u8                      object_type,
-	ACPI_OPERAND_OBJECT     *source_object,
-	ACPI_GENERIC_STATE      *state,
-	void                    *context)
-{
-	ACPI_STATUS             status = AE_OK;
-	ACPI_PKG_INFO           *info = (ACPI_PKG_INFO *) context;
-	u32                     object_space;
-	u32                     this_index;
-	ACPI_OBJECT             *target_object;
-
-
-	this_index      = state->pkg.index;
-	target_object   = (ACPI_OBJECT *)
-			   &((ACPI_OBJECT *)(state->pkg.dest_object))->package.elements[this_index];
-
-
-	switch (object_type)
-	{
-	case 0:
-
-		/*
-		 * This is a simple or null object -- get the size
-		 */
-
-		status = acpi_cm_copy_isimple_to_esimple (source_object,
-				  target_object, info->free_space, &object_space);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-
-		break;
-
-	case 1:
-
-		/*
-		 * Build the package object
-		 */
-		target_object->type             = ACPI_TYPE_PACKAGE;
-		target_object->package.count    = source_object->package.count;
-		target_object->package.elements = (ACPI_OBJECT *) info->free_space;
-
-		/*
-		 * Pass the new package object back to the package walk routine
-		 */
-		state->pkg.this_target_obj = target_object;
-
-		/*
-		 * Save space for the array of objects (Package elements)
-		 * update the buffer length counter
-		 */
-		object_space = (u32) ROUND_UP_TO_NATIVE_WORD (
-				   target_object->package.count * sizeof (ACPI_OBJECT));
-		break;
-
-	default:
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	info->free_space  += object_space;
-	info->length      += object_space;
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_ipackage_to_epackage
- *
- * PARAMETERS:  *Internal_object    - Pointer to the object we are returning
- *              *Buffer             - Where the object is returned
- *              *Space_used         - Where the object length is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to place a package object in a user
- *              buffer.  A package object by definition contains other objects.
- *
- *              The buffer is assumed to have sufficient space for the object.
- *              The caller must have verified the buffer length needed using the
- *              Acpi_cm_get_object_size function before calling this function.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-acpi_cm_copy_ipackage_to_epackage (
-	ACPI_OPERAND_OBJECT     *internal_object,
-	u8                      *buffer,
-	u32                     *space_used)
-{
-	ACPI_OBJECT             *external_object;
-	ACPI_STATUS             status;
-	ACPI_PKG_INFO           info;
-
-
-	/*
-	 * First package at head of the buffer
-	 */
-	external_object = (ACPI_OBJECT *) buffer;
-
-	/*
-	 * Free space begins right after the first package
-	 */
-	info.length      = 0;
-	info.object_space = 0;
-	info.num_packages = 1;
-	info.free_space  = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
-
-
-	external_object->type              = internal_object->common.type;
-	external_object->package.count     = internal_object->package.count;
-	external_object->package.elements  = (ACPI_OBJECT *) info.free_space;
-
-
-	/*
-	 * Build an array of ACPI_OBJECTS in the buffer
-	 * and move the free space past it
-	 */
-
-	info.free_space += external_object->package.count *
-			  ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
-
-
-	status = acpi_cm_walk_package_tree (internal_object, external_object,
-			 acpi_cm_copy_ielement_to_eelement, &info);
-
-	*space_used = info.length;
-
-	return (status);
-
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_iobject_to_eobject
- *
- * PARAMETERS:  *Internal_object    - The internal object to be converted
- *              *Buffer_ptr         - Where the object is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to build an API object to be returned to
- *              the caller.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_copy_iobject_to_eobject (
-	ACPI_OPERAND_OBJECT     *internal_object,
-	ACPI_BUFFER             *ret_buffer)
-{
-	ACPI_STATUS             status;
-
-
-	if (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)) {
-		/*
-		 * Package object:  Copy all subobjects (including
-		 * nested packages)
-		 */
-		status = acpi_cm_copy_ipackage_to_epackage (internal_object,
-				  ret_buffer->pointer, &ret_buffer->length);
-	}
-
-	else {
-		/*
-		 * Build a simple object (no nested objects)
-		 */
-		status = acpi_cm_copy_isimple_to_esimple (internal_object,
-				  (ACPI_OBJECT *) ret_buffer->pointer,
-				  ((u8 *) ret_buffer->pointer +
-				  ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
-				  &ret_buffer->length);
-		/*
-		 * build simple does not include the object size in the length
-		 * so we add it in here
-		 */
-		ret_buffer->length += sizeof (ACPI_OBJECT);
-	}
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_esimple_to_isimple
- *
- * PARAMETERS:  *External_object   - The external object to be converted
- *              *Internal_object   - Where the internal object is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function copies an external object to an internal one.
- *              NOTE: Pointers can be copied, we don't need to copy data.
- *              (The pointers have to be valid in our address space no matter
- *              what we do with them!)
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_copy_esimple_to_isimple (
-	ACPI_OBJECT             *external_object,
-	ACPI_OPERAND_OBJECT     *internal_object)
-{
-
-
-	internal_object->common.type = (u8) external_object->type;
-
-	switch (external_object->type)
-	{
-
-	case ACPI_TYPE_STRING:
-
-		internal_object->string.length = external_object->string.length;
-		internal_object->string.pointer = external_object->string.pointer;
-		break;
-
-
-	case ACPI_TYPE_BUFFER:
-
-		internal_object->buffer.length = external_object->buffer.length;
-		internal_object->buffer.pointer = external_object->buffer.pointer;
-		break;
-
-
-	case ACPI_TYPE_INTEGER:
-		/*
-		 * Number is included in the object itself
-		 */
-		internal_object->integer.value  = external_object->integer.value;
-		break;
-
-
-	default:
-		return (AE_CTRL_RETURN_VALUE);
-		break;
-	}
-
-
-	return (AE_OK);
-}
-
-
-#ifdef ACPI_FUTURE_IMPLEMENTATION
-
-/* Code to convert packages that are parameters to control methods */
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_epackage_to_ipackage
- *
- * PARAMETERS:  *Internal_object   - Pointer to the object we are returning
- *              *Buffer         - Where the object is returned
- *              *Space_used     - Where the length of the object is returned
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: This function is called to place a package object in a user
- *              buffer.  A package object by definition contains other objects.
- *
- *              The buffer is assumed to have sufficient space for the object.
- *              The caller must have verified the buffer length needed using the
- *              Acpi_cm_get_object_size function before calling this function.
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-acpi_cm_copy_epackage_to_ipackage (
-	ACPI_OPERAND_OBJECT     *internal_object,
-	u8                      *buffer,
-	u32                     *space_used)
-{
-	u8                      *free_space;
-	ACPI_OBJECT             *external_object;
-	u32                     length = 0;
-	u32                     this_index;
-	u32                     object_space = 0;
-	ACPI_OPERAND_OBJECT     *this_internal_obj;
-	ACPI_OBJECT             *this_external_obj;
-
-
-	/*
-	 * First package at head of the buffer
-	 */
-	external_object = (ACPI_OBJECT *)buffer;
-
-	/*
-	 * Free space begins right after the first package
-	 */
-	free_space = buffer + sizeof(ACPI_OBJECT);
-
-
-	external_object->type              = internal_object->common.type;
-	external_object->package.count     = internal_object->package.count;
-	external_object->package.elements  = (ACPI_OBJECT *)free_space;
-
-
-	/*
-	 * Build an array of ACPI_OBJECTS in the buffer
-	 * and move the free space past it
-	 */
-
-	free_space += external_object->package.count * sizeof(ACPI_OBJECT);
-
-
-	/* Call Walk_package */
-
-}
-
-#endif /* Future implementation */
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_eobject_to_iobject
- *
- * PARAMETERS:  *Internal_object   - The external object to be converted
- *              *Buffer_ptr     - Where the internal object is returned
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: Converts an external object to an internal object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_copy_eobject_to_iobject (
-	ACPI_OBJECT             *external_object,
-	ACPI_OPERAND_OBJECT     *internal_object)
-{
-	ACPI_STATUS             status;
-
-
-	if (external_object->type == ACPI_TYPE_PACKAGE) {
-		/*
-		 * Package objects contain other objects (which can be objects)
-		 * buildpackage does it all
-		 *
-		 * TBD: Package conversion must be completed and tested
-		 * NOTE: this code converts packages as input parameters to
-		 * control methods only.  This is a very, very rare case.
-		 */
-/*
-		Status = Acpi_cm_copy_epackage_to_ipackage(Internal_object,
-				 Ret_buffer->Pointer,
-				 &Ret_buffer->Length);
-*/
-		return (AE_NOT_IMPLEMENTED);
-	}
-
-	else {
-		/*
-		 * Build a simple object (no nested objects)
-		 */
-		status = acpi_cm_copy_esimple_to_isimple (external_object, internal_object);
-		/*
-		 * build simple does not include the object size in the length
-		 * so we add it in here
-		 */
-	}
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_ielement_to_ielement
- *
- * PARAMETERS:  ACPI_PKG_CALLBACK
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: Copy one package element to another package element
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_copy_ielement_to_ielement (
-	u8                      object_type,
-	ACPI_OPERAND_OBJECT     *source_object,
-	ACPI_GENERIC_STATE      *state,
-	void                    *context)
-{
-	ACPI_STATUS             status = AE_OK;
-	u32                     this_index;
-	ACPI_OPERAND_OBJECT     **this_target_ptr;
-	ACPI_OPERAND_OBJECT     *target_object;
-
-
-	this_index    = state->pkg.index;
-	this_target_ptr = (ACPI_OPERAND_OBJECT **)
-			   &state->pkg.dest_object->package.elements[this_index];
-
-	switch (object_type)
-	{
-	case 0:
-
-		/*
-		 * This is a simple object, just copy it
-		 */
-		target_object = acpi_cm_create_internal_object (source_object->common.type);
-		if (!target_object) {
-			return (AE_NO_MEMORY);
-		}
-
-		status = acpi_aml_store_object_to_object (source_object, target_object,
-				  (ACPI_WALK_STATE *) context);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-
-		*this_target_ptr = target_object;
-		break;
-
-
-	case 1:
-		/*
-		 * This object is a package - go down another nesting level
-		 * Create and build the package object
-		 */
-		target_object = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
-		if (!target_object) {
-			/* TBD: must delete package created up to this point */
-
-			return (AE_NO_MEMORY);
-		}
-
-		target_object->package.count = source_object->package.count;
-
-		/*
-		 * Pass the new package object back to the package walk routine
-		 */
-		state->pkg.this_target_obj = target_object;
-
-		/*
-		 * Store the object pointer in the parent package object
-		 */
-		*this_target_ptr = target_object;
-		break;
-
-	default:
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_ipackage_to_ipackage
- *
- * PARAMETERS:  *Source_obj     - Pointer to the source package object
- *              *Dest_obj       - Where the internal object is returned
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: This function is called to copy an internal package object
- *              into another internal package object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_copy_ipackage_to_ipackage (
-	ACPI_OPERAND_OBJECT     *source_obj,
-	ACPI_OPERAND_OBJECT     *dest_obj,
-	ACPI_WALK_STATE         *walk_state)
-{
-	ACPI_STATUS             status = AE_OK;
-
-
-	dest_obj->common.type   = source_obj->common.type;
-	dest_obj->package.count = source_obj->package.count;
-
-
-	/*
-	 * Create the object array and walk the source package tree
-	 */
-
-	dest_obj->package.elements = acpi_cm_callocate ((source_obj->package.count + 1) *
-			 sizeof (void *));
-	dest_obj->package.next_element = dest_obj->package.elements;
-
-	if (!dest_obj->package.elements) {
-		REPORT_ERROR (
-			("Aml_build_copy_internal_package_object: Package allocation failure\n"));
-		return (AE_NO_MEMORY);
-	}
-
-
-	status = acpi_cm_walk_package_tree (source_obj, dest_obj,
-			 acpi_cm_copy_ielement_to_ielement, walk_state);
-
-	return (status);
-}
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmdebug.c linux/drivers/acpi/common/cmdebug.c
--- v2.4.5/linux/drivers/acpi/common/cmdebug.c	Mon Jan 22 13:23:42 2001
+++ linux/drivers/acpi/common/cmdebug.c	Wed Dec 31 16:00:00 1969
@@ -1,559 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmdebug - Debug print routines
- *              $Revision: 64 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmdebug")
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Get/Set debug level
- *
- * DESCRIPTION: Get or set value of the debug flag
- *
- *              These are used to allow user's to get/set the debug level
- *
- ****************************************************************************/
-
-
-u32
-get_debug_level (void)
-{
-
-	return (acpi_dbg_level);
-}
-
-void
-set_debug_level (
-	u32                     new_debug_level)
-{
-
-	acpi_dbg_level = new_debug_level;
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_trace
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level
- *
- ****************************************************************************/
-
-void
-function_trace (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name)
-{
-
-	acpi_gbl_nesting_level++;
-
-	debug_print (module_name, line_number, component_id,
-			 TRACE_FUNCTIONS,
-			 " %2.2ld Entered Function: %s\n",
-			 acpi_gbl_nesting_level, function_name);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_trace_ptr
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *              Pointer             - Pointer to display
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level
- *
- ****************************************************************************/
-
-void
-function_trace_ptr (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name,
-	void                    *pointer)
-{
-
-	acpi_gbl_nesting_level++;
-	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
-			 " %2.2ld Entered Function: %s, %p\n",
-			 acpi_gbl_nesting_level, function_name, pointer);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_trace_str
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *              String              - Additional string to display
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level
- *
- ****************************************************************************/
-
-void
-function_trace_str (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name,
-	NATIVE_CHAR             *string)
-{
-
-	acpi_gbl_nesting_level++;
-	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
-			 " %2.2ld Entered Function: %s, %s\n",
-			 acpi_gbl_nesting_level, function_name, string);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_trace_u32
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *              Integer             - Integer to display
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function entry trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level
- *
- ****************************************************************************/
-
-void
-function_trace_u32 (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name,
-	u32                     integer)
-{
-
-	acpi_gbl_nesting_level++;
-	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
-			 " %2.2ld Entered Function: %s, %lX\n",
-			 acpi_gbl_nesting_level, function_name, integer);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_exit
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level
- *
- ****************************************************************************/
-
-void
-function_exit (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name)
-{
-
-	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
-			 " %2.2ld Exiting Function: %s\n",
-			 acpi_gbl_nesting_level, function_name);
-
-	acpi_gbl_nesting_level--;
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_status_exit
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *              Status              - Exit status code
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level. Prints exit status also.
- *
- ****************************************************************************/
-
-void
-function_status_exit (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name,
-	ACPI_STATUS             status)
-{
-
-	debug_print (module_name, line_number, component_id,
-		TRACE_FUNCTIONS,
-		" %2.2ld Exiting Function: %s, %s\n",
-		acpi_gbl_nesting_level,
-		function_name,
-		acpi_cm_format_exception (status));
-
-	acpi_gbl_nesting_level--;
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_value_exit
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *              Value               - Value to be printed with exit msg
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level. Prints exit value also.
- *
- ****************************************************************************/
-
-void
-function_value_exit (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name,
-	ACPI_INTEGER            value)
-{
-
-	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
-			 " %2.2ld Exiting Function: %s, %X\n",
-			 acpi_gbl_nesting_level, function_name, value);
-
-	acpi_gbl_nesting_level--;
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Function_ptr_exit
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Function_name       - Name of Caller's function
- *              Value               - Value to be printed with exit msg
- *
- * RETURN:      None
- *
- * DESCRIPTION: Function exit trace.  Prints only if TRACE_FUNCTIONS bit is
- *              set in Debug_level. Prints exit value also.
- *
- ****************************************************************************/
-
-void
-function_ptr_exit (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	NATIVE_CHAR             *function_name,
-	u8                      *ptr)
-{
-
-	debug_print (module_name, line_number, component_id, TRACE_FUNCTIONS,
-			 " %2.2ld Exiting Function: %s, %p\n",
-			 acpi_gbl_nesting_level, function_name, ptr);
-
-	acpi_gbl_nesting_level--;
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Debug_print
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Print_level         - Requested debug print level
- *              Format              - Printf format field
- *              ...                 - Optional printf arguments
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print error message with prefix consisting of the module name,
- *              line number, and component ID.
- *
- ****************************************************************************/
-
-void
-debug_print (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	u32                     print_level,
-	NATIVE_CHAR             *format,
-	...)
-{
-	va_list                 args;
-
-
-	/* Both the level and the component must be enabled */
-
-	if ((print_level & acpi_dbg_level) &&
-		(component_id & acpi_dbg_layer))
-	{
-		va_start (args, format);
-
-		acpi_os_printf ("%8s-%04d: ", module_name, line_number);
-		acpi_os_vprintf (format, args);
-	}
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Debug_print_prefix
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print the prefix part of an error message, consisting of the
- *              module name, and line number
- *
- ****************************************************************************/
-
-void
-debug_print_prefix (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number)
-{
-
-
-	acpi_os_printf ("%8s-%04d: ", module_name, line_number);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Debug_print_raw
- *
- * PARAMETERS:  Format              - Printf format field
- *              ...                 - Optional printf arguments
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print error message -- without module/line indentifiers
- *
- ****************************************************************************/
-
-void
-debug_print_raw (
-	NATIVE_CHAR             *format,
-	...)
-{
-	va_list                 args;
-
-
-	va_start (args, format);
-
-	acpi_os_vprintf (format, args);
-
-	va_end (args);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Acpi_cm_dump_buffer
- *
- * PARAMETERS:  Buffer              - Buffer to dump
- *              Count               - Amount to dump, in bytes
- *              Component_iD        - Caller's component ID
- *
- * RETURN:      None
- *
- * DESCRIPTION: Generic dump buffer in both hex and ascii.
- *
- ****************************************************************************/
-
-void
-acpi_cm_dump_buffer (
-	u8                      *buffer,
-	u32                     count,
-	u32                     display,
-	u32                     component_id)
-{
-	u32                     i = 0;
-	u32                     j;
-	u32                     temp32;
-	u8                      buf_char;
-
-
-	/* Only dump the buffer if tracing is enabled */
-
-	if (!((TRACE_TABLES & acpi_dbg_level) &&
-		(component_id & acpi_dbg_layer)))
-	{
-		return;
-	}
-
-
-	/*
-	 * Nasty little dump buffer routine!
-	 */
-	while (i < count) {
-		/* Print current offset */
-
-		acpi_os_printf ("%05X  ", i);
-
-
-		/* Print 16 hex chars */
-
-		for (j = 0; j < 16;) {
-			if (i + j >= count) {
-				acpi_os_printf ("\n");
-				return;
-			}
-
-			/* Make sure that the s8 doesn't get sign-extended! */
-
-			switch (display)
-			{
-			/* Default is BYTE display */
-
-			default:
-
-				acpi_os_printf ("%02X ",
-						*((u8 *) &buffer[i + j]));
-				j += 1;
-				break;
-
-
-			case DB_WORD_DISPLAY:
-
-				MOVE_UNALIGNED16_TO_32 (&temp32,
-						 &buffer[i + j]);
-				acpi_os_printf ("%04X ", temp32);
-				j += 2;
-				break;
-
-
-			case DB_DWORD_DISPLAY:
-
-				MOVE_UNALIGNED32_TO_32 (&temp32,
-						 &buffer[i + j]);
-				acpi_os_printf ("%08X ", temp32);
-				j += 4;
-				break;
-
-
-			case DB_QWORD_DISPLAY:
-
-				MOVE_UNALIGNED32_TO_32 (&temp32,
-						 &buffer[i + j]);
-				acpi_os_printf ("%08X", temp32);
-
-				MOVE_UNALIGNED32_TO_32 (&temp32,
-						 &buffer[i + j + 4]);
-				acpi_os_printf ("%08X ", temp32);
-				j += 8;
-				break;
-			}
-		}
-
-
-		/*
-		 * Print the ASCII equivalent characters
-		 * But watch out for the bad unprintable ones...
-		 */
-
-		for (j = 0; j < 16; j++) {
-			if (i + j >= count) {
-				acpi_os_printf ("\n");
-				return;
-			}
-
-			buf_char = buffer[i + j];
-			if ((buf_char > 0x1F && buf_char < 0x2E) ||
-				(buf_char > 0x2F && buf_char < 0x61) ||
-				(buf_char > 0x60 && buf_char < 0x7F))
-			{
-				acpi_os_printf ("%c", buf_char);
-			}
-			else {
-				acpi_os_printf (".");
-			}
-		}
-
-		/* Done with that line. */
-
-		acpi_os_printf ("\n");
-		i += 16;
-	}
-
-	return;
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmdelete.c linux/drivers/acpi/common/cmdelete.c
--- v2.4.5/linux/drivers/acpi/common/cmdelete.c	Mon Jan 22 13:23:42 2001
+++ linux/drivers/acpi/common/cmdelete.c	Wed Dec 31 16:00:00 1969
@@ -1,591 +0,0 @@
-/*******************************************************************************
- *
- * Module Name: cmdelete - object deletion and reference count utilities
- *              $Revision: 62 $
- *
- ******************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acinterp.h"
-#include "acnamesp.h"
-#include "actables.h"
-#include "acparser.h"
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmdelete")
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_internal_obj
- *
- * PARAMETERS:  *Object        - Pointer to the list to be deleted
- *
- * RETURN:      None
- *
- * DESCRIPTION: Low level object deletion, after reference counts have been
- *              updated (All reference counts, including sub-objects!)
- *
- ******************************************************************************/
-
-void
-acpi_cm_delete_internal_obj (
-	ACPI_OPERAND_OBJECT     *object)
-{
-	void                    *obj_pointer = NULL;
-	ACPI_OPERAND_OBJECT     *handler_desc;
-
-
-	if (!object) {
-		return;
-	}
-
-	/*
-	 * Must delete or free any pointers within the object that are not
-	 * actual ACPI objects (for example, a raw buffer pointer).
-	 */
-
-	switch (object->common.type)
-	{
-
-	case ACPI_TYPE_STRING:
-
-		/* Free the actual string buffer */
-
-		obj_pointer = object->string.pointer;
-		break;
-
-
-	case ACPI_TYPE_BUFFER:
-
-		/* Free the actual buffer */
-
-		obj_pointer = object->buffer.pointer;
-		break;
-
-
-	case ACPI_TYPE_PACKAGE:
-
-		/*
-		 * Elements of the package are not handled here, they are deleted
-		 * separately
-		 */
-
-		/* Free the (variable length) element pointer array */
-
-		obj_pointer = object->package.elements;
-		break;
-
-
-	case ACPI_TYPE_MUTEX:
-
-		acpi_os_delete_semaphore (object->mutex.semaphore);
-		break;
-
-
-	case ACPI_TYPE_EVENT:
-
-		acpi_os_delete_semaphore (object->event.semaphore);
-		object->event.semaphore = NULL;
-		break;
-
-
-	case ACPI_TYPE_METHOD:
-
-		/* Delete the method semaphore if it exists */
-
-		if (object->method.semaphore) {
-			acpi_os_delete_semaphore (object->method.semaphore);
-			object->method.semaphore = NULL;
-		}
-
-		break;
-
-
-	case ACPI_TYPE_REGION:
-
-
-		if (object->region.extra) {
-			/*
-			 * Free the Region_context if and only if the handler is one of the
-			 * default handlers -- and therefore, we created the context object
-			 * locally, it was not created by an external caller.
-			 */
-			handler_desc = object->region.addr_handler;
-			if ((handler_desc) &&
-				(handler_desc->addr_handler.hflags == ADDR_HANDLER_DEFAULT_INSTALLED))
-			{
-				obj_pointer = object->region.extra->extra.region_context;
-			}
-
-			/* Now we can free the Extra object */
-
-			acpi_cm_delete_object_desc (object->region.extra);
-		}
-		break;
-
-
-	case ACPI_TYPE_FIELD_UNIT:
-
-		if (object->field_unit.extra) {
-			acpi_cm_delete_object_desc (object->field_unit.extra);
-		}
-		break;
-
-	default:
-		break;
-	}
-
-
-	/*
-	 * Delete any allocated memory found above
-	 */
-
-	if (obj_pointer) {
-		if (!acpi_tb_system_table_pointer (obj_pointer)) {
-			acpi_cm_free (obj_pointer);
-		}
-	}
-
-
-	/* Only delete the object if it was dynamically allocated */
-
-
-	if (!(object->common.flags & AOPOBJ_STATIC_ALLOCATION)) {
-		acpi_cm_delete_object_desc (object);
-
-	}
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_internal_object_list
- *
- * PARAMETERS:  *Obj_list       - Pointer to the list to be deleted
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: This function deletes an internal object list, including both
- *              simple objects and package objects
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_delete_internal_object_list (
-	ACPI_OPERAND_OBJECT     **obj_list)
-{
-	ACPI_OPERAND_OBJECT     **internal_obj;
-
-
-	/* Walk the null-terminated internal list */
-
-	for (internal_obj = obj_list; *internal_obj; internal_obj++) {
-		/*
-		 * Check for a package
-		 * Simple objects are simply stored in the array and do not
-		 * need to be deleted separately.
-		 */
-
-		if (IS_THIS_OBJECT_TYPE ((*internal_obj), ACPI_TYPE_PACKAGE)) {
-			/* Delete the package */
-
-			/*
-			 * TBD: [Investigate] This might not be the right thing to do,
-			 * depending on how the internal package object was allocated!!!
-			 */
-			acpi_cm_delete_internal_obj (*internal_obj);
-		}
-
-	}
-
-	/* Free the combined parameter pointer list and object array */
-
-	acpi_cm_free (obj_list);
-
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_update_ref_count
- *
- * PARAMETERS:  *Object         - Object whose ref count is to be updated
- *              Action          - What to do
- *
- * RETURN:      New ref count
- *
- * DESCRIPTION: Modify the ref count and return it.
- *
- ******************************************************************************/
-
-static void
-acpi_cm_update_ref_count (
-	ACPI_OPERAND_OBJECT     *object,
-	u32                     action)
-{
-	u16                     count;
-	u16                     new_count;
-
-
-	if (!object) {
-		return;
-	}
-
-
-	count = object->common.reference_count;
-	new_count = count;
-
-	/*
-	 * Reference count action (increment, decrement, or force delete)
-	 */
-
-	switch (action)
-	{
-
-	case REF_INCREMENT:
-
-		new_count++;
-		object->common.reference_count = new_count;
-
-		break;
-
-
-	case REF_DECREMENT:
-
-		if (count < 1) {
-			new_count = 0;
-		}
-
-		else {
-			new_count--;
-
-		}
-
-
-		object->common.reference_count = new_count;
-		if (new_count == 0) {
-			acpi_cm_delete_internal_obj (object);
-		}
-
-		break;
-
-
-	case REF_FORCE_DELETE:
-
-		new_count = 0;
-		object->common.reference_count = new_count;
-		acpi_cm_delete_internal_obj (object);
-		break;
-
-
-	default:
-
-		break;
-	}
-
-
-	/*
-	 * Sanity check the reference count, for debug purposes only.
-	 * (A deleted object will have a huge reference count)
-	 */
-
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_update_object_reference
- *
- * PARAMETERS:  *Object             - Increment ref count for this object
- *                                    and all sub-objects
- *              Action              - Either REF_INCREMENT or REF_DECREMENT or
- *                                    REF_FORCE_DELETE
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Increment the object reference count
- *
- * Object references are incremented when:
- * 1) An object is attached to a Node (namespace object)
- * 2) An object is copied (all subobjects must be incremented)
- *
- * Object references are decremented when:
- * 1) An object is detached from an Node
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_update_object_reference (
-	ACPI_OPERAND_OBJECT     *object,
-	u16                     action)
-{
-	ACPI_STATUS             status;
-	u32                     i;
-	ACPI_OPERAND_OBJECT     *next;
-	ACPI_OPERAND_OBJECT     *new;
-	ACPI_GENERIC_STATE       *state_list = NULL;
-	ACPI_GENERIC_STATE       *state;
-
-
-	/* Ignore a null object ptr */
-
-	if (!object) {
-		return (AE_OK);
-	}
-
-
-	/*
-	 * Make sure that this isn't a namespace handle or an AML pointer
-	 */
-
-	if (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_NAMED)) {
-		return (AE_OK);
-	}
-
-	if (acpi_tb_system_table_pointer (object)) {
-		return (AE_OK);
-	}
-
-
-	state = acpi_cm_create_update_state (object, action);
-
-	while (state) {
-
-		object = state->update.object;
-		action = state->update.value;
-		acpi_cm_delete_generic_state (state);
-
-		/*
-		 * All sub-objects must have their reference count incremented also.
-		 * Different object types have different subobjects.
-		 */
-		switch (object->common.type)
-		{
-
-		case ACPI_TYPE_DEVICE:
-
-			status = acpi_cm_create_update_state_and_push (object->device.addr_handler,
-					   action, &state_list);
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-
-			acpi_cm_update_ref_count (object->device.sys_handler, action);
-			acpi_cm_update_ref_count (object->device.drv_handler, action);
-			break;
-
-
-		case INTERNAL_TYPE_ADDRESS_HANDLER:
-
-			/* Must walk list of address handlers */
-
-			next = object->addr_handler.next;
-			while (next) {
-				new = next->addr_handler.next;
-				acpi_cm_update_ref_count (next, action);
-
-				next = new;
-			}
-			break;
-
-
-		case ACPI_TYPE_PACKAGE:
-
-			/*
-			 * We must update all the sub-objects of the package
-			 * (Each of whom may have their own sub-objects, etc.
-			 */
-			for (i = 0; i < object->package.count; i++) {
-				/*
-				 * Push each element onto the stack for later processing.
-				 * Note: There can be null elements within the package,
-				 * these are simply ignored
-				 */
-
-				status = acpi_cm_create_update_state_and_push (
-						 object->package.elements[i], action, &state_list);
-				if (ACPI_FAILURE (status)) {
-					return (status);
-				}
-			}
-			break;
-
-
-		case ACPI_TYPE_FIELD_UNIT:
-
-			status = acpi_cm_create_update_state_and_push (
-					 object->field_unit.container, action, &state_list);
-
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-			break;
-
-
-		case INTERNAL_TYPE_DEF_FIELD:
-
-			status = acpi_cm_create_update_state_and_push (
-					 object->field.container, action, &state_list);
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-		   break;
-
-
-		case INTERNAL_TYPE_BANK_FIELD:
-
-			status = acpi_cm_create_update_state_and_push (
-					 object->bank_field.bank_select, action, &state_list);
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-
-			status = acpi_cm_create_update_state_and_push (
-					 object->bank_field.container, action, &state_list);
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-			break;
-
-
-		case ACPI_TYPE_REGION:
-
-	/* TBD: [Investigate]
-			Acpi_cm_update_ref_count (Object->Region.Addr_handler, Action);
-	*/
-/*
-			Status =
-				Acpi_cm_create_update_state_and_push (Object->Region.Addr_handler,
-						   Action, &State_list);
-			if (ACPI_FAILURE (Status)) {
-				return (Status);
-			}
-*/
-			break;
-
-
-		case INTERNAL_TYPE_REFERENCE:
-
-			break;
-		}
-
-
-		/*
-		 * Now we can update the count in the main object.  This can only
-		 * happen after we update the sub-objects in case this causes the
-		 * main object to be deleted.
-		 */
-
-		acpi_cm_update_ref_count (object, action);
-
-
-		/* Move on to the next object to be updated */
-
-		state = acpi_cm_pop_generic_state (&state_list);
-	}
-
-
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_add_reference
- *
- * PARAMETERS:  *Object        - Object whose reference count is to be
- *                                  incremented
- *
- * RETURN:      None
- *
- * DESCRIPTION: Add one reference to an ACPI object
- *
- ******************************************************************************/
-
-void
-acpi_cm_add_reference (
-	ACPI_OPERAND_OBJECT     *object)
-{
-
-
-	/*
-	 * Ensure that we have a valid object
-	 */
-
-	if (!acpi_cm_valid_internal_object (object)) {
-		return;
-	}
-
-	/*
-	 * We have a valid ACPI internal object, now increment the reference count
-	 */
-
-	acpi_cm_update_object_reference (object, REF_INCREMENT);
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_remove_reference
- *
- * PARAMETERS:  *Object        - Object whose ref count will be decremented
- *
- * RETURN:      None
- *
- * DESCRIPTION: Decrement the reference count of an ACPI internal object
- *
- ******************************************************************************/
-
-void
-acpi_cm_remove_reference (
-	ACPI_OPERAND_OBJECT     *object)
-{
-
-
-	/*
-	 * Ensure that we have a valid object
-	 */
-
-	if (!acpi_cm_valid_internal_object (object)) {
-		return;
-	}
-
-	/*
-	 * Decrement the reference count, and only actually delete the object
-	 * if the reference count becomes 0.  (Must also decrement the ref count
-	 * of all subobjects!)
-	 */
-
-	acpi_cm_update_object_reference (object, REF_DECREMENT);
-
-	return;
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmeval.c linux/drivers/acpi/common/cmeval.c
--- v2.4.5/linux/drivers/acpi/common/cmeval.c	Mon Jan 22 13:23:42 2001
+++ linux/drivers/acpi/common/cmeval.c	Wed Dec 31 16:00:00 1969
@@ -1,308 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmeval - Object evaluation
- *              $Revision: 21 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acnamesp.h"
-#include "acinterp.h"
-
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmeval")
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_cm_evaluate_numeric_object
- *
- * PARAMETERS:  *Object_name        - Object name to be evaluated
- *              Device_node         - Node for the device
- *              *Address            - Where the value is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: evaluates a numeric namespace object for a selected device
- *              and stores results in *Address.
- *
- *              NOTE: Internal function, no parameter validation
- *
- ***************************************************************************/
-
-ACPI_STATUS
-acpi_cm_evaluate_numeric_object (
-	NATIVE_CHAR             *object_name,
-	ACPI_NAMESPACE_NODE     *device_node,
-	ACPI_INTEGER            *address)
-{
-	ACPI_OPERAND_OBJECT     *obj_desc;
-	ACPI_STATUS             status;
-
-
-	/* Execute the method */
-
-	status = acpi_ns_evaluate_relative (device_node, object_name, NULL, &obj_desc);
-	if (ACPI_FAILURE (status)) {
-
-		return (status);
-	}
-
-
-	/* Did we get a return object? */
-
-	if (!obj_desc) {
-		return (AE_TYPE);
-	}
-
-	/* Is the return object of the correct type? */
-
-	if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
-		status = AE_TYPE;
-	}
-	else {
-		/*
-		 * Since the structure is a union, setting any field will set all
-		 * of the variables in the union
-		 */
-		*address = obj_desc->integer.value;
-	}
-
-	/* On exit, we must delete the return object */
-
-	acpi_cm_remove_reference (obj_desc);
-
-	return (status);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_cm_execute_HID
- *
- * PARAMETERS:  Device_node         - Node for the device
- *              *Hid                - Where the HID is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Executes the _HID control method that returns the hardware
- *              ID of the device.
- *
- *              NOTE: Internal function, no parameter validation
- *
- ***************************************************************************/
-
-ACPI_STATUS
-acpi_cm_execute_HID (
-	ACPI_NAMESPACE_NODE     *device_node,
-	DEVICE_ID               *hid)
-{
-	ACPI_OPERAND_OBJECT     *obj_desc;
-	ACPI_STATUS             status;
-
-
-	/* Execute the method */
-
-	status = acpi_ns_evaluate_relative (device_node,
-			 METHOD_NAME__HID, NULL, &obj_desc);
-	if (ACPI_FAILURE (status)) {
-
-
-		return (status);
-	}
-
-	/* Did we get a return object? */
-
-	if (!obj_desc) {
-		return (AE_TYPE);
-	}
-
-	/*
-	 *  A _HID can return either a Number (32 bit compressed EISA ID) or
-	 *  a string
-	 */
-
-	if ((obj_desc->common.type != ACPI_TYPE_INTEGER) &&
-		(obj_desc->common.type != ACPI_TYPE_STRING))
-	{
-		status = AE_TYPE;
-	}
-
-	else {
-		if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
-			/* Convert the Numeric HID to string */
-
-			acpi_aml_eisa_id_to_string ((u32) obj_desc->integer.value, hid->buffer);
-		}
-
-		else {
-			/* Copy the String HID from the returned object */
-
-			STRNCPY(hid->buffer, obj_desc->string.pointer, sizeof(hid->buffer));
-		}
-	}
-
-
-	/* On exit, we must delete the return object */
-
-	acpi_cm_remove_reference (obj_desc);
-
-	return (status);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_cm_execute_UID
- *
- * PARAMETERS:  Device_node         - Node for the device
- *              *Uid                - Where the UID is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Executes the _UID control method that returns the hardware
- *              ID of the device.
- *
- *              NOTE: Internal function, no parameter validation
- *
- ***************************************************************************/
-
-ACPI_STATUS
-acpi_cm_execute_UID (
-	ACPI_NAMESPACE_NODE     *device_node,
-	DEVICE_ID               *uid)
-{
-	ACPI_OPERAND_OBJECT     *obj_desc;
-	ACPI_STATUS             status;
-
-
-	/* Execute the method */
-
-	status = acpi_ns_evaluate_relative (device_node,
-			 METHOD_NAME__UID, NULL, &obj_desc);
-	if (ACPI_FAILURE (status)) {
-
-
-		return (status);
-	}
-
-	/* Did we get a return object? */
-
-	if (!obj_desc) {
-		return (AE_TYPE);
-	}
-
-	/*
-	 *  A _UID can return either a Number (32 bit compressed EISA ID) or
-	 *  a string
-	 */
-
-	if ((obj_desc->common.type != ACPI_TYPE_INTEGER) &&
-		(obj_desc->common.type != ACPI_TYPE_STRING))
-	{
-		status = AE_TYPE;
-	}
-
-	else {
-		if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
-			/* Convert the Numeric UID to string */
-
-			acpi_aml_unsigned_integer_to_string (obj_desc->integer.value, uid->buffer);
-		}
-
-		else {
-			/* Copy the String UID from the returned object */
-
-			STRNCPY(uid->buffer, obj_desc->string.pointer, sizeof(uid->buffer));
-		}
-	}
-
-
-	/* On exit, we must delete the return object */
-
-	acpi_cm_remove_reference (obj_desc);
-
-	return (status);
-}
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_cm_execute_STA
- *
- * PARAMETERS:  Device_node         - Node for the device
- *              *Flags              - Where the status flags are returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Executes _STA for selected device and stores results in
- *              *Flags.
- *
- *              NOTE: Internal function, no parameter validation
- *
- ***************************************************************************/
-
-ACPI_STATUS
-acpi_cm_execute_STA (
-	ACPI_NAMESPACE_NODE     *device_node,
-	u32                     *flags)
-{
-	ACPI_OPERAND_OBJECT     *obj_desc;
-	ACPI_STATUS             status;
-
-
-	/* Execute the method */
-
-	status = acpi_ns_evaluate_relative (device_node,
-			 METHOD_NAME__STA, NULL, &obj_desc);
-	if (AE_NOT_FOUND == status) {
-		*flags = 0x0F;
-		status = AE_OK;
-	}
-
-
-	else /* success */ {
-		/* Did we get a return object? */
-
-		if (!obj_desc) {
-			return (AE_TYPE);
-		}
-
-		/* Is the return object of the correct type? */
-
-		if (obj_desc->common.type != ACPI_TYPE_INTEGER) {
-			status = AE_TYPE;
-		}
-
-		else {
-			/* Extract the status flags */
-
-			*flags = (u32) obj_desc->integer.value;
-		}
-
-		/* On exit, we must delete the return object */
-
-		acpi_cm_remove_reference (obj_desc);
-	}
-
-	return (status);
-}
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmglobal.c linux/drivers/acpi/common/cmglobal.c
--- v2.4.5/linux/drivers/acpi/common/cmglobal.c	Mon Jan 22 13:23:42 2001
+++ linux/drivers/acpi/common/cmglobal.c	Wed Dec 31 16:00:00 1969
@@ -1,472 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmglobal - Global variables for the ACPI subsystem
- *              $Revision: 116 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#define DEFINE_ACPI_GLOBALS
-
-#include "acpi.h"
-#include "acevents.h"
-#include "acnamesp.h"
-#include "acinterp.h"
-#include "amlcode.h"
-
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmglobal")
-
-
-/******************************************************************************
- *
- * Static global variable initialization.
- *
- ******************************************************************************/
-
-/*
- * We want the debug switches statically initialized so they
- * are already set when the debugger is entered.
- */
-
-/* Debug switch - level and trace mask */
-
-u32                         acpi_dbg_level = NORMAL_DEFAULT;
-
-/* Debug switch - layer (component) mask */
-
-u32                         acpi_dbg_layer = COMPONENT_DEFAULT;
-u32                         acpi_gbl_nesting_level = 0;
-
-
-/* Debugger globals */
-
-u8                          acpi_gbl_db_terminate_threads = FALSE;
-u8                          acpi_gbl_method_executing = FALSE;
-
-/* System flags */
-
-u32                         acpi_gbl_system_flags = 0;
-u32                         acpi_gbl_startup_flags = 0;
-
-/* System starts unitialized! */
-u8                          acpi_gbl_shutdown = TRUE;
-
-
-u8                          acpi_gbl_decode_to8bit [8] = {1,2,4,8,16,32,64,128};
-
-
-/******************************************************************************
- *
- * Namespace globals
- *
- ******************************************************************************/
-
-
-/*
- * Names built-in to the interpreter
- *
- * Initial values are currently supported only for types String and Number.
- * To avoid type punning, both are specified as strings in this table.
- */
-
-PREDEFINED_NAMES            acpi_gbl_pre_defined_names[] =
-{
-	{"_GPE",    INTERNAL_TYPE_DEF_ANY},
-	{"_PR_",    INTERNAL_TYPE_DEF_ANY},
-	{"_SB_",    INTERNAL_TYPE_DEF_ANY},
-	{"_SI_",    INTERNAL_TYPE_DEF_ANY},
-	{"_TZ_",    INTERNAL_TYPE_DEF_ANY},
-	{"_REV",    ACPI_TYPE_INTEGER, "2"},
-	{"_OS_",    ACPI_TYPE_STRING, ACPI_OS_NAME},
-	{"_GL_",    ACPI_TYPE_MUTEX, "0"},
-
-	/* Table terminator */
-
-	{NULL,      ACPI_TYPE_ANY}
-};
-
-
-/*
- * Properties of the ACPI Object Types, both internal and external.
- *
- * Elements of Acpi_ns_properties are bit significant
- * and the table is indexed by values of ACPI_OBJECT_TYPE
- */
-
-u8                          acpi_gbl_ns_properties[] =
-{
-	NSP_NORMAL,                 /* 00 Any              */
-	NSP_NORMAL,                 /* 01 Number           */
-	NSP_NORMAL,                 /* 02 String           */
-	NSP_NORMAL,                 /* 03 Buffer           */
-	NSP_LOCAL,                  /* 04 Package          */
-	NSP_NORMAL,                 /* 05 Field_unit       */
-	NSP_NEWSCOPE | NSP_LOCAL,   /* 06 Device           */
-	NSP_LOCAL,                  /* 07 Acpi_event       */
-	NSP_NEWSCOPE | NSP_LOCAL,   /* 08 Method           */
-	NSP_LOCAL,                  /* 09 Mutex            */
-	NSP_LOCAL,                  /* 10 Region           */
-	NSP_NEWSCOPE | NSP_LOCAL,   /* 11 Power            */
-	NSP_NEWSCOPE | NSP_LOCAL,   /* 12 Processor        */
-	NSP_NEWSCOPE | NSP_LOCAL,   /* 13 Thermal          */
-	NSP_NORMAL,                 /* 14 Buffer_field     */
-	NSP_NORMAL,                 /* 15 Ddb_handle       */
-	NSP_NORMAL,                 /* 16 Debug Object     */
-	NSP_NORMAL,                 /* 17 Def_field        */
-	NSP_NORMAL,                 /* 18 Bank_field       */
-	NSP_NORMAL,                 /* 19 Index_field      */
-	NSP_NORMAL,                 /* 20 Reference        */
-	NSP_NORMAL,                 /* 21 Alias            */
-	NSP_NORMAL,                 /* 22 Notify           */
-	NSP_NORMAL,                 /* 23 Address Handler  */
-	NSP_NEWSCOPE | NSP_LOCAL,   /* 24 Resource         */
-	NSP_NORMAL,                 /* 25 Def_field_defn   */
-	NSP_NORMAL,                 /* 26 Bank_field_defn  */
-	NSP_NORMAL,                 /* 27 Index_field_defn */
-	NSP_NORMAL,                 /* 28 If               */
-	NSP_NORMAL,                 /* 29 Else             */
-	NSP_NORMAL,                 /* 30 While            */
-	NSP_NEWSCOPE,               /* 31 Scope            */
-	NSP_LOCAL,                  /* 32 Def_any          */
-	NSP_NORMAL,                 /* 33 Extra            */
-	NSP_NORMAL                  /* 34 Invalid          */
-};
-
-
-/* Hex to ASCII conversion table */
-
-NATIVE_CHAR                 acpi_gbl_hex_to_ascii[] =
-			  {'0','1','2','3','4','5','6','7',
-			  '8','9','A','B','C','D','E','F'};
-
-
-/******************************************************************************
- *
- * Table globals
- *
- * NOTE: This table includes ONLY the ACPI tables that the subsystem consumes.
- * it is NOT an exhaustive list of all possible ACPI tables.  All ACPI tables
- * that are not used by the subsystem are simply ignored.
- *
- ******************************************************************************/
-
-
-ACPI_TABLE_DESC             acpi_gbl_acpi_tables[NUM_ACPI_TABLES];
-
-
-ACPI_TABLE_SUPPORT          acpi_gbl_acpi_table_data[NUM_ACPI_TABLES] =
-{
-	/***********    Name,    Signature,  Signature size,    How many allowed?,   Supported?  Global typed pointer */
-
-	/* RSDP 0 */ {RSDP_NAME, RSDP_SIG, sizeof (RSDP_SIG)-1, ACPI_TABLE_SINGLE,   AE_OK,      NULL},
-	/* DSDT 1 */ {DSDT_SIG,  DSDT_SIG, sizeof (DSDT_SIG)-1, ACPI_TABLE_SINGLE,   AE_OK,      (void **) &acpi_gbl_DSDT},
-	/* FADT 2 */ {FADT_SIG,  FADT_SIG, sizeof (FADT_SIG)-1, ACPI_TABLE_SINGLE,   AE_OK,      (void **) &acpi_gbl_FADT},
-	/* FACS 3 */ {FACS_SIG,  FACS_SIG, sizeof (FACS_SIG)-1, ACPI_TABLE_SINGLE,   AE_OK,      (void **) &acpi_gbl_FACS},
-	/* PSDT 4 */ {PSDT_SIG,  PSDT_SIG, sizeof (PSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK,      NULL},
-	/* SSDT 5 */ {SSDT_SIG,  SSDT_SIG, sizeof (SSDT_SIG)-1, ACPI_TABLE_MULTIPLE, AE_OK,      NULL},
-	/* XSDT 6 */ {XSDT_SIG,  XSDT_SIG, sizeof (RSDT_SIG)-1, ACPI_TABLE_SINGLE,   AE_OK,      NULL},
-};
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Acpi_cm_valid_object_type
- *
- * PARAMETERS:  None.
- *
- * RETURN:      TRUE if valid object type
- *
- * DESCRIPTION: Validate an object type
- *
- ****************************************************************************/
-
-u8
-acpi_cm_valid_object_type (
-	u32                     type)
-{
-
-	if (type > ACPI_TYPE_MAX) {
-		if ((type < INTERNAL_TYPE_BEGIN) ||
-			(type > INTERNAL_TYPE_MAX))
-		{
-			return (FALSE);
-		}
-	}
-
-	return (TRUE);
-}
-
-
-/*****************************************************************************
- *
- * FUNCTION:    Acpi_cm_format_exception
- *
- * PARAMETERS:  Status              - Acpi status to be formatted
- *
- * RETURN:      Formatted status string
- *
- * DESCRIPTION: Convert an ACPI exception to a string
- *
- ****************************************************************************/
-
-NATIVE_CHAR *
-acpi_cm_format_exception (
-	ACPI_STATUS             status)
-{
-	NATIVE_CHAR             *exception = "UNKNOWN_STATUS";
-	ACPI_STATUS             sub_status;
-
-
-	sub_status = (status & ~AE_CODE_MASK);
-
-
-	switch (status & AE_CODE_MASK)
-	{
-	case AE_CODE_ENVIRONMENTAL:
-
-		if (sub_status <= AE_CODE_ENV_MAX) {
-			exception = acpi_gbl_exception_names_env [sub_status];
-		}
-		break;
-
-	case AE_CODE_PROGRAMMER:
-
-		if (sub_status <= AE_CODE_PGM_MAX) {
-			exception = acpi_gbl_exception_names_pgm [sub_status -1];
-		}
-		break;
-
-	case AE_CODE_ACPI_TABLES:
-
-		if (sub_status <= AE_CODE_TBL_MAX) {
-			exception = acpi_gbl_exception_names_tbl [sub_status -1];
-		}
-		break;
-
-	case AE_CODE_AML:
-
-		if (sub_status <= AE_CODE_AML_MAX) {
-			exception = acpi_gbl_exception_names_aml [sub_status -1];
-		}
-		break;
-
-	case AE_CODE_CONTROL:
-
-		if (sub_status <= AE_CODE_CTRL_MAX) {
-			exception = acpi_gbl_exception_names_ctrl [sub_status -1];
-		}
-		break;
-
-	default:
-		break;
-	}
-
-
-	return (exception);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_cm_allocate_owner_id
- *
- * PARAMETERS:  Id_type         - Type of ID (method or table)
- *
- * DESCRIPTION: Allocate a table or method owner id
- *
- ***************************************************************************/
-
-ACPI_OWNER_ID
-acpi_cm_allocate_owner_id (
-	u32                     id_type)
-{
-	ACPI_OWNER_ID           owner_id = 0xFFFF;
-
-
-	acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
-
-	switch (id_type)
-	{
-	case OWNER_TYPE_TABLE:
-
-		owner_id = acpi_gbl_next_table_owner_id;
-		acpi_gbl_next_table_owner_id++;
-
-		if (acpi_gbl_next_table_owner_id == FIRST_METHOD_ID) {
-			acpi_gbl_next_table_owner_id = FIRST_TABLE_ID;
-		}
-		break;
-
-
-	case OWNER_TYPE_METHOD:
-
-		owner_id = acpi_gbl_next_method_owner_id;
-		acpi_gbl_next_method_owner_id++;
-
-		if (acpi_gbl_next_method_owner_id == FIRST_TABLE_ID) {
-			acpi_gbl_next_method_owner_id = FIRST_METHOD_ID;
-		}
-		break;
-	}
-
-
-	acpi_cm_release_mutex (ACPI_MTX_CACHES);
-
-	return (owner_id);
-}
-
-
-/****************************************************************************
- *
- * FUNCTION:    Acpi_cm_init_globals
- *
- * PARAMETERS:  none
- *
- * DESCRIPTION: Init library globals.  All globals that require specific
- *              initialization should be initialized here!
- *
- ***************************************************************************/
-
-void
-acpi_cm_init_globals (
-	void)
-{
-	u32                     i;
-
-
-	/* ACPI table structure */
-
-	for (i = 0; i < NUM_ACPI_TABLES; i++) {
-		acpi_gbl_acpi_tables[i].prev        = &acpi_gbl_acpi_tables[i];
-		acpi_gbl_acpi_tables[i].next        = &acpi_gbl_acpi_tables[i];
-		acpi_gbl_acpi_tables[i].pointer     = NULL;
-		acpi_gbl_acpi_tables[i].length      = 0;
-		acpi_gbl_acpi_tables[i].allocation  = ACPI_MEM_NOT_ALLOCATED;
-		acpi_gbl_acpi_tables[i].count       = 0;
-	}
-
-
-	/* Address Space handler array */
-
-	for (i = 0; i < ACPI_NUM_ADDRESS_SPACES; i++) {
-		acpi_gbl_address_spaces[i].handler  = NULL;
-		acpi_gbl_address_spaces[i].context  = NULL;
-	}
-
-	/* Mutex locked flags */
-
-	for (i = 0; i < NUM_MTX; i++) {
-		acpi_gbl_acpi_mutex_info[i].mutex   = NULL;
-		acpi_gbl_acpi_mutex_info[i].locked  = FALSE;
-		acpi_gbl_acpi_mutex_info[i].use_count = 0;
-	}
-
-	/* Global notify handlers */
-
-	acpi_gbl_sys_notify.handler         = NULL;
-	acpi_gbl_drv_notify.handler         = NULL;
-
-	/* Global "typed" ACPI table pointers */
-
-	acpi_gbl_RSDP                       = NULL;
-	acpi_gbl_XSDT                       = NULL;
-	acpi_gbl_FACS                       = NULL;
-	acpi_gbl_FADT                       = NULL;
-	acpi_gbl_DSDT                       = NULL;
-
-
-	/* Global Lock support */
-
-	acpi_gbl_global_lock_acquired       = FALSE;
-	acpi_gbl_global_lock_thread_count   = 0;
-
-	/* Miscellaneous variables */
-
-	acpi_gbl_system_flags               = 0;
-	acpi_gbl_startup_flags              = 0;
-	acpi_gbl_global_lock_set            = FALSE;
-	acpi_gbl_rsdp_original_location     = 0;
-	acpi_gbl_cm_single_step             = FALSE;
-	acpi_gbl_db_terminate_threads       = FALSE;
-	acpi_gbl_shutdown                   = FALSE;
-	acpi_gbl_ns_lookup_count            = 0;
-	acpi_gbl_ps_find_count              = 0;
-	acpi_gbl_acpi_hardware_present      = TRUE;
-	acpi_gbl_next_table_owner_id        = FIRST_TABLE_ID;
-	acpi_gbl_next_method_owner_id       = FIRST_METHOD_ID;
-	acpi_gbl_debugger_configuration     = DEBUGGER_THREADING;
-
-	/* Cache of small "state" objects */
-
-	acpi_gbl_generic_state_cache        = NULL;
-	acpi_gbl_generic_state_cache_depth  = 0;
-	acpi_gbl_state_cache_requests       = 0;
-	acpi_gbl_state_cache_hits           = 0;
-
-	acpi_gbl_parse_cache                = NULL;
-	acpi_gbl_parse_cache_depth          = 0;
-	acpi_gbl_parse_cache_requests       = 0;
-	acpi_gbl_parse_cache_hits           = 0;
-
-	acpi_gbl_ext_parse_cache            = NULL;
-	acpi_gbl_ext_parse_cache_depth      = 0;
-	acpi_gbl_ext_parse_cache_requests   = 0;
-	acpi_gbl_ext_parse_cache_hits       = 0;
-
-	acpi_gbl_object_cache               = NULL;
-	acpi_gbl_object_cache_depth         = 0;
-	acpi_gbl_object_cache_requests      = 0;
-	acpi_gbl_object_cache_hits          = 0;
-
-	acpi_gbl_walk_state_cache           = NULL;
-	acpi_gbl_walk_state_cache_depth     = 0;
-	acpi_gbl_walk_state_cache_requests  = 0;
-	acpi_gbl_walk_state_cache_hits      = 0;
-
-	/* Hardware oriented */
-
-	acpi_gbl_gpe0enable_register_save   = NULL;
-	acpi_gbl_gpe1_enable_register_save  = NULL;
-	acpi_gbl_original_mode              = SYS_MODE_UNKNOWN;   /*  original ACPI/legacy mode   */
-	acpi_gbl_gpe_registers              = NULL;
-	acpi_gbl_gpe_info                   = NULL;
-
-	/* Namespace */
-
-	acpi_gbl_root_node                  = NULL;
-
-	acpi_gbl_root_node_struct.name      = ACPI_ROOT_NAME;
-	acpi_gbl_root_node_struct.data_type = ACPI_DESC_TYPE_NAMED;
-	acpi_gbl_root_node_struct.type      = ACPI_TYPE_ANY;
-	acpi_gbl_root_node_struct.child     = NULL;
-	acpi_gbl_root_node_struct.peer      = NULL;
-	acpi_gbl_root_node_struct.object    = NULL;
-	acpi_gbl_root_node_struct.flags     = ANOBJ_END_OF_PEER_LIST;
-
-	/* Memory allocation metrics - compiled out in non-debug mode. */
-
-	INITIALIZE_ALLOCATION_METRICS();
-
-	return;
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cminit.c linux/drivers/acpi/common/cminit.c
--- v2.4.5/linux/drivers/acpi/common/cminit.c	Mon Jan 22 13:23:42 2001
+++ linux/drivers/acpi/common/cminit.c	Wed Dec 31 16:00:00 1969
@@ -1,250 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cminit - Common ACPI subsystem initialization
- *              $Revision: 93 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "achware.h"
-#include "acnamesp.h"
-#include "acevents.h"
-#include "acparser.h"
-#include "acdispat.h"
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cminit")
-
-
-#define ACPI_OFFSET(d,o)    ((u32) &(((d *)0)->o))
-#define ACPI_FADT_OFFSET(o) ACPI_OFFSET (FADT_DESCRIPTOR, o)
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_fadt_register_error
- *
- * PARAMETERS:  *Register_name          - Pointer to string identifying register
- *              Value                   - Actual register contents value
- *              Acpi_test_spec_section  - TDS section containing assertion
- *              Acpi_assertion          - Assertion number being tested
- *
- * RETURN:      AE_BAD_VALUE
- *
- * DESCRIPTION: Display failure message and link failure to TDS assertion
- *
- ******************************************************************************/
-
-static ACPI_STATUS
-acpi_cm_fadt_register_error (
-	NATIVE_CHAR             *register_name,
-	u32                     value,
-	u32                     offset)
-{
-
-	REPORT_ERROR (
-		("Invalid FADT value %s=%lX at offset %lX FADT=%p\n",
-		register_name, value, offset, acpi_gbl_FADT));
-
-
-	return (AE_BAD_VALUE);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_cm_validate_fadt
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Validate various ACPI registers in the FADT
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_validate_fadt (
-	void)
-{
-	ACPI_STATUS                 status = AE_OK;
-
-
-	/*
-	 * Verify Fixed ACPI Description Table fields,
-	 * but don't abort on any problems, just display error
-	 */
-
-	if (acpi_gbl_FADT->pm1_evt_len < 4) {
-		status = acpi_cm_fadt_register_error ("PM1_EVT_LEN",
-				  (u32) acpi_gbl_FADT->pm1_evt_len,
-				  ACPI_FADT_OFFSET (pm1_evt_len));
-	}
-
-	if (!acpi_gbl_FADT->pm1_cnt_len) {
-		status = acpi_cm_fadt_register_error ("PM1_CNT_LEN", 0,
-				  ACPI_FADT_OFFSET (pm1_cnt_len));
-	}
-
-	if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_evt_blk.address)) {
-		status = acpi_cm_fadt_register_error ("X_PM1a_EVT_BLK", 0,
-				  ACPI_FADT_OFFSET (Xpm1a_evt_blk.address));
-	}
-
-	if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm1a_cnt_blk.address)) {
-		status = acpi_cm_fadt_register_error ("X_PM1a_CNT_BLK", 0,
-				  ACPI_FADT_OFFSET (Xpm1a_cnt_blk.address));
-	}
-
-	if (!ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm_tmr_blk.address)) {
-		status = acpi_cm_fadt_register_error ("X_PM_TMR_BLK", 0,
-				  ACPI_FADT_OFFSET (Xpm_tmr_blk.address));
-	}
-
-	if ((ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xpm2_cnt_blk.address) &&
-		!acpi_gbl_FADT->pm2_cnt_len))
-	{
-		status = acpi_cm_fadt_register_error ("PM2_CNT_LEN",
-				  (u32) acpi_gbl_FADT->pm2_cnt_len,
-				  ACPI_FADT_OFFSET (pm2_cnt_len));
-	}
-
-	if (acpi_gbl_FADT->pm_tm_len < 4) {
-		status = acpi_cm_fadt_register_error ("PM_TM_LEN",
-				  (u32) acpi_gbl_FADT->pm_tm_len,
-				  ACPI_FADT_OFFSET (pm_tm_len));
-	}
-
-	/* length of GPE blocks must be a multiple of 2 */
-
-
-	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe0blk.address) &&
-		(acpi_gbl_FADT->gpe0blk_len & 1))
-	{
-		status = acpi_cm_fadt_register_error ("(x)GPE0_BLK_LEN",
-				  (u32) acpi_gbl_FADT->gpe0blk_len,
-				  ACPI_FADT_OFFSET (gpe0blk_len));
-	}
-
-	if (ACPI_VALID_ADDRESS (acpi_gbl_FADT->Xgpe1_blk.address) &&
-		(acpi_gbl_FADT->gpe1_blk_len & 1))
-	{
-		status = acpi_cm_fadt_register_error ("(x)GPE1_BLK_LEN",
-				  (u32) acpi_gbl_FADT->gpe1_blk_len,
-				  ACPI_FADT_OFFSET (gpe1_blk_len));
-	}
-
-	return (status);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_cm_terminate
- *
- * PARAMETERS:  none
- *
- * RETURN:      none
- *
- * DESCRIPTION: free memory allocated for table storage.
- *
- ******************************************************************************/
-
-void
-acpi_cm_terminate (void)
-{
-
-
-	/* Free global tables, etc. */
-
-	if (acpi_gbl_gpe0enable_register_save) {
-		acpi_cm_free (acpi_gbl_gpe0enable_register_save);
-	}
-
-	if (acpi_gbl_gpe1_enable_register_save) {
-		acpi_cm_free (acpi_gbl_gpe1_enable_register_save);
-	}
-
-
-	return;
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_cm_subsystem_shutdown
- *
- * PARAMETERS:  none
- *
- * RETURN:      none
- *
- * DESCRIPTION: Shutdown the various subsystems.  Don't delete the mutex
- *              objects here -- because the AML debugger may be still running.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_subsystem_shutdown (void)
-{
-
-	/* Just exit if subsystem is already shutdown */
-
-	if (acpi_gbl_shutdown) {
-		return (AE_OK);
-	}
-
-	/* Subsystem appears active, go ahead and shut it down */
-
-	acpi_gbl_shutdown = TRUE;
-
-	/* Close the Namespace */
-
-	acpi_ns_terminate ();
-
-	/* Close the Acpi_event Handling */
-
-	acpi_ev_terminate ();
-
-	/* Close the globals */
-
-	acpi_cm_terminate ();
-
-	/* Flush the local cache(s) */
-
-	acpi_cm_delete_generic_state_cache ();
-	acpi_cm_delete_object_cache ();
-	acpi_ds_delete_walk_state_cache ();
-
-	/* Close the Parser */
-
-	/* TBD: [Restructure] Acpi_ps_terminate () */
-
-	acpi_ps_delete_parse_cache ();
-
-	/* Debug only - display leftover memory allocation, if any */
-#ifdef ENABLE_DEBUGGER
-	acpi_cm_dump_current_allocations (ACPI_UINT32_MAX, NULL);
-#endif
-
-	return (AE_OK);
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmobject.c linux/drivers/acpi/common/cmobject.c
--- v2.4.5/linux/drivers/acpi/common/cmobject.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/common/cmobject.c	Wed Dec 31 16:00:00 1969
@@ -1,618 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmobject - ACPI object create/delete/size/cache routines
- *              $Revision: 36 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acinterp.h"
-#include "acnamesp.h"
-#include "actables.h"
-#include "amlcode.h"
-
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmobject")
-
-
-/*******************************************************************************
- *
- * FUNCTION:    _Cm_create_internal_object
- *
- * PARAMETERS:  Address             - Address of the memory to deallocate
- *              Component           - Component type of caller
- *              Module              - Source file name of caller
- *              Line                - Line number of caller
- *              Type                - ACPI Type of the new object
- *
- * RETURN:      Object              - The new object.  Null on failure
- *
- * DESCRIPTION: Create and initialize a new internal object.
- *
- * NOTE:        We always allocate the worst-case object descriptor because
- *              these objects are cached, and we want them to be
- *              one-size-satisifies-any-request.  This in itself may not be
- *              the most memory efficient, but the efficiency of the object
- *              cache should more than make up for this!
- *
- ******************************************************************************/
-
-ACPI_OPERAND_OBJECT  *
-_cm_create_internal_object (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id,
-	OBJECT_TYPE_INTERNAL    type)
-{
-	ACPI_OPERAND_OBJECT     *object;
-
-
-	/* Allocate the raw object descriptor */
-
-	object = _cm_allocate_object_desc (module_name, line_number, component_id);
-	if (!object) {
-		/* Allocation failure */
-
-		return (NULL);
-	}
-
-	/* Save the object type in the object descriptor */
-
-	object->common.type = type;
-
-	/* Init the reference count */
-
-	object->common.reference_count = 1;
-
-	/* Any per-type initialization should go here */
-
-
-	return (object);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_valid_internal_object
- *
- * PARAMETERS:  Operand             - Object to be validated
- *
- * RETURN:      Validate a pointer to be an ACPI_OPERAND_OBJECT
- *
- ******************************************************************************/
-
-u8
-acpi_cm_valid_internal_object (
-	void                    *object)
-{
-
-	/* Check for a null pointer */
-
-	if (!object) {
-		return (FALSE);
-	}
-
-	/* Check for a pointer within one of the ACPI tables */
-
-	if (acpi_tb_system_table_pointer (object)) {
-		return (FALSE);
-	}
-
-	/* Check the descriptor type field */
-
-	if (!VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL)) {
-		/* Not an ACPI internal object, do some further checking */
-
-
-
-
-		return (FALSE);
-	}
-
-
-	/* The object appears to be a valid ACPI_OPERAND_OBJECT  */
-
-	return (TRUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    _Cm_allocate_object_desc
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Message             - Error message to use on failure
- *
- * RETURN:      Pointer to newly allocated object descriptor.  Null on error
- *
- * DESCRIPTION: Allocate a new object descriptor.  Gracefully handle
- *              error conditions.
- *
- ******************************************************************************/
-
-void *
-_cm_allocate_object_desc (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id)
-{
-	ACPI_OPERAND_OBJECT     *object;
-
-
-	acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
-
-	acpi_gbl_object_cache_requests++;
-
-	/* Check the cache first */
-
-	if (acpi_gbl_object_cache) {
-		/* There is an object available, use it */
-
-		object = acpi_gbl_object_cache;
-		acpi_gbl_object_cache = object->cache.next;
-		object->cache.next = NULL;
-
-		acpi_gbl_object_cache_hits++;
-		acpi_gbl_object_cache_depth--;
-
-		acpi_cm_release_mutex (ACPI_MTX_CACHES);
-	}
-
-	else {
-		/* The cache is empty, create a new object */
-
-		acpi_cm_release_mutex (ACPI_MTX_CACHES);
-
-		/* Attempt to allocate new descriptor */
-
-		object = _cm_callocate (sizeof (ACPI_OPERAND_OBJECT), component_id,
-				  module_name, line_number);
-		if (!object) {
-			/* Allocation failed */
-
-			_REPORT_ERROR (module_name, line_number, component_id,
-					  ("Could not allocate an object descriptor\n"));
-
-			return (NULL);
-		}
-
-		/* Memory allocation metrics - compiled out in non debug mode. */
-
-		INCREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT));
-	}
-
-	/* Mark the descriptor type */
-
-	object->common.data_type = ACPI_DESC_TYPE_INTERNAL;
-
-	return (object);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_object_desc
- *
- * PARAMETERS:  Object          - Acpi internal object to be deleted
- *
- * RETURN:      None.
- *
- * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache
- *
- ******************************************************************************/
-
-void
-acpi_cm_delete_object_desc (
-	ACPI_OPERAND_OBJECT     *object)
-{
-
-
-	/* Make sure that the object isn't already in the cache */
-
-	if (object->common.data_type == (ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT)) {
-		return;
-	}
-
-	/* Object must be an ACPI_OPERAND_OBJECT  */
-
-	if (object->common.data_type != ACPI_DESC_TYPE_INTERNAL) {
-		return;
-	}
-
-
-	/* If cache is full, just free this object */
-
-	if (acpi_gbl_object_cache_depth >= MAX_OBJECT_CACHE_DEPTH) {
-		/*
-		 * Memory allocation metrics.  Call the macro here since we only
-		 * care about dynamically allocated objects.
-		 */
-		DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT));
-
-		acpi_cm_free (object);
-		return;
-	}
-
-	acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
-
-	/* Clear the entire object.  This is important! */
-
-	MEMSET (object, 0, sizeof (ACPI_OPERAND_OBJECT));
-	object->common.data_type = ACPI_DESC_TYPE_INTERNAL | ACPI_CACHED_OBJECT;
-
-	/* Put the object at the head of the global cache list */
-
-	object->cache.next = acpi_gbl_object_cache;
-	acpi_gbl_object_cache = object;
-	acpi_gbl_object_cache_depth++;
-
-
-	acpi_cm_release_mutex (ACPI_MTX_CACHES);
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_object_cache
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Purge the global state object cache.  Used during subsystem
- *              termination.
- *
- ******************************************************************************/
-
-void
-acpi_cm_delete_object_cache (
-	void)
-{
-	ACPI_OPERAND_OBJECT     *next;
-
-
-	/* Traverse the global cache list */
-
-	while (acpi_gbl_object_cache) {
-		/* Delete one cached state object */
-
-		next = acpi_gbl_object_cache->cache.next;
-		acpi_gbl_object_cache->cache.next = NULL;
-
-		/*
-		 * Memory allocation metrics.  Call the macro here since we only
-		 * care about dynamically allocated objects.
-		 */
-		DECREMENT_OBJECT_METRICS (sizeof (ACPI_OPERAND_OBJECT));
-
-		acpi_cm_free (acpi_gbl_object_cache);
-		acpi_gbl_object_cache = next;
-		acpi_gbl_object_cache_depth--;
-	}
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_init_static_object
- *
- * PARAMETERS:  Obj_desc            - Pointer to a "static" object - on stack
- *                                    or in the data segment.
- *
- * RETURN:      None.
- *
- * DESCRIPTION: Initialize a static object.  Sets flags to disallow dynamic
- *              deletion of the object.
- *
- ******************************************************************************/
-
-void
-acpi_cm_init_static_object (
-	ACPI_OPERAND_OBJECT     *obj_desc)
-{
-
-
-	if (!obj_desc) {
-		return;
-	}
-
-
-	/*
-	 * Clear the entire descriptor
-	 */
-	MEMSET ((void *) obj_desc, 0, sizeof (ACPI_OPERAND_OBJECT));
-
-
-	/*
-	 * Initialize the header fields
-	 * 1) This is an ACPI_OPERAND_OBJECT  descriptor
-	 * 2) The size is the full object (worst case)
-	 * 3) The flags field indicates static allocation
-	 * 4) Reference count starts at one (not really necessary since the
-	 *    object can't be deleted, but keeps everything sane)
-	 */
-
-	obj_desc->common.data_type      = ACPI_DESC_TYPE_INTERNAL;
-	obj_desc->common.flags          = AOPOBJ_STATIC_ALLOCATION;
-	obj_desc->common.reference_count = 1;
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_get_simple_object_size
- *
- * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
- *              *Ret_length         - Where the length is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to determine the space required to
- *              contain a simple object for return to an API user.
- *
- *              The length includes the object structure plus any additional
- *              needed space.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_get_simple_object_size (
-	ACPI_OPERAND_OBJECT     *internal_object,
-	u32                     *obj_length)
-{
-	u32                     length;
-	ACPI_STATUS             status = AE_OK;
-
-
-	/* Handle a null object (Could be a uninitialized package element -- which is legal) */
-
-	if (!internal_object) {
-		*obj_length = 0;
-		return (AE_OK);
-	}
-
-
-	/* Start with the length of the Acpi object */
-
-	length = sizeof (ACPI_OBJECT);
-
-	if (VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_NAMED)) {
-		/* Object is a named object (reference), just return the length */
-
-		*obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length);
-		return (status);
-	}
-
-
-	/*
-	 * The final length depends on the object type
-	 * Strings and Buffers are packed right up against the parent object and
-	 * must be accessed bytewise or there may be alignment problems.
-	 *
-	 * TBD:[Investigate] do strings and buffers require alignment also?
-	 */
-
-	switch (internal_object->common.type)
-	{
-
-	case ACPI_TYPE_STRING:
-
-		length += internal_object->string.length + 1;
-		break;
-
-
-	case ACPI_TYPE_BUFFER:
-
-		length += internal_object->buffer.length;
-		break;
-
-
-	case ACPI_TYPE_INTEGER:
-	case ACPI_TYPE_PROCESSOR:
-	case ACPI_TYPE_POWER:
-
-		/*
-		 * No extra data for these types
-		 */
-		break;
-
-
-	case INTERNAL_TYPE_REFERENCE:
-
-		/*
-		 * The only type that should be here is opcode AML_NAMEPATH_OP -- since
-		 * this means an object reference
-		 */
-		if (internal_object->reference.op_code != AML_NAMEPATH_OP) {
-			status = AE_TYPE;
-		}
-		break;
-
-
-	default:
-
-		status = AE_TYPE;
-		break;
-	}
-
-
-	/*
-	 * Account for the space required by the object rounded up to the next
-	 * multiple of the machine word size.  This keeps each object aligned
-	 * on a machine word boundary. (preventing alignment faults on some
-	 * machines.)
-	 */
-	*obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length);
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_copy_package_to_internal
- *
- * PARAMETERS:  ACPI_PKG_CALLBACK
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION:
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_get_element_length (
-	u8                      object_type,
-	ACPI_OPERAND_OBJECT     *source_object,
-	ACPI_GENERIC_STATE      *state,
-	void                    *context)
-{
-	ACPI_STATUS             status = AE_OK;
-	ACPI_PKG_INFO           *info = (ACPI_PKG_INFO *) context;
-	u32                     object_space;
-
-
-	switch (object_type)
-	{
-	case 0:
-
-		/*
-		 * Simple object - just get the size (Null object/entry is handled
-		 * here also) and sum it into the running package length
-		 */
-		status = acpi_cm_get_simple_object_size (source_object, &object_space);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-
-		info->length += object_space;
-		break;
-
-
-	case 1:
-		/* Package - nothing much to do here, let the walk handle it */
-
-		info->num_packages++;
-		state->pkg.this_target_obj = NULL;
-		break;
-
-	default:
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_get_package_object_size
- *
- * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
- *              *Ret_length         - Where the length is returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to determine the space required to
- *              contain a package object for return to an API user.
- *
- *              This is moderately complex since a package contains other
- *              objects including packages.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_get_package_object_size (
-	ACPI_OPERAND_OBJECT     *internal_object,
-	u32                     *obj_length)
-{
-	ACPI_STATUS             status;
-	ACPI_PKG_INFO           info;
-
-
-	info.length      = 0;
-	info.object_space = 0;
-	info.num_packages = 1;
-
-	status = acpi_cm_walk_package_tree (internal_object, NULL,
-			 acpi_cm_get_element_length, &info);
-
-	/*
-	 * We have handled all of the objects in all levels of the package.
-	 * just add the length of the package objects themselves.
-	 * Round up to the next machine word.
-	 */
-	info.length += ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) *
-			  info.num_packages;
-
-	/* Return the total package length */
-
-	*obj_length = info.length;
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_get_object_size
- *
- * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
- *              *Ret_length         - Where the length will be returned
- *
- * RETURN:      Status
- *
- * DESCRIPTION: This function is called to determine the space required to
- *              contain an object for return to an API user.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_get_object_size(
-	ACPI_OPERAND_OBJECT     *internal_object,
-	u32                     *obj_length)
-{
-	ACPI_STATUS             status;
-
-
-	if ((VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_INTERNAL)) &&
-		(IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)))
-	{
-		status = acpi_cm_get_package_object_size (internal_object, obj_length);
-	}
-
-	else {
-		status = acpi_cm_get_simple_object_size (internal_object, obj_length);
-	}
-
-	return (status);
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmutils.c linux/drivers/acpi/common/cmutils.c
--- v2.4.5/linux/drivers/acpi/common/cmutils.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/common/cmutils.c	Wed Dec 31 16:00:00 1969
@@ -1,952 +0,0 @@
-/*******************************************************************************
- *
- * Module Name: cmutils - common utility procedures
- *              $Revision: 27 $
- *
- ******************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acevents.h"
-#include "achware.h"
-#include "acnamesp.h"
-#include "acinterp.h"
-#include "amlcode.h"
-#include "acdebug.h"
-
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmutils")
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_valid_acpi_name
- *
- * PARAMETERS:  Character           - The character to be examined
- *
- * RETURN:      1 if Character may appear in a name, else 0
- *
- * DESCRIPTION: Check for a valid ACPI name.  Each character must be one of:
- *              1) Upper case alpha
- *              2) numeric
- *              3) underscore
- *
- ******************************************************************************/
-
-u8
-acpi_cm_valid_acpi_name (
-	u32                     name)
-{
-	NATIVE_CHAR             *name_ptr = (NATIVE_CHAR *) &name;
-	u32                     i;
-
-
-	for (i = 0; i < ACPI_NAME_SIZE; i++) {
-		if (!((name_ptr[i] == '_') ||
-			  (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') ||
-			  (name_ptr[i] >= '0' && name_ptr[i] <= '9')))
-		{
-			return (FALSE);
-		}
-	}
-
-
-	return (TRUE);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_valid_acpi_character
- *
- * PARAMETERS:  Character           - The character to be examined
- *
- * RETURN:      1 if Character may appear in a name, else 0
- *
- * DESCRIPTION: Check for a printable character
- *
- ******************************************************************************/
-
-u8
-acpi_cm_valid_acpi_character (
-	NATIVE_CHAR             character)
-{
-
-	return ((u8)   ((character == '_') ||
-			   (character >= 'A' && character <= 'Z') ||
-			   (character >= '0' && character <= '9')));
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_mutex_initialize
- *
- * PARAMETERS:  None.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create the system mutex objects.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_mutex_initialize (
-	void)
-{
-	u32                     i;
-	ACPI_STATUS             status;
-
-
-	/*
-	 * Create each of the predefined mutex objects
-	 */
-	for (i = 0; i < NUM_MTX; i++) {
-		status = acpi_cm_create_mutex (i);
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_mutex_terminate
- *
- * PARAMETERS:  None.
- *
- * RETURN:      None.
- *
- * DESCRIPTION: Delete all of the system mutex objects.
- *
- ******************************************************************************/
-
-void
-acpi_cm_mutex_terminate (
-	void)
-{
-	u32                     i;
-
-
-	/*
-	 * Delete each predefined mutex object
-	 */
-	for (i = 0; i < NUM_MTX; i++) {
-		acpi_cm_delete_mutex (i);
-	}
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_mutex
- *
- * PARAMETERS:  Mutex_iD        - ID of the mutex to be created
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create a mutex object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_create_mutex (
-	ACPI_MUTEX_HANDLE       mutex_id)
-{
-	ACPI_STATUS             status = AE_OK;
-
-
-	if (mutex_id > MAX_MTX) {
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) {
-		status = acpi_os_create_semaphore (1, 1,
-				   &acpi_gbl_acpi_mutex_info[mutex_id].mutex);
-		acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE;
-		acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0;
-	}
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_mutex
- *
- * PARAMETERS:  Mutex_iD        - ID of the mutex to be deleted
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Delete a mutex object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_delete_mutex (
-	ACPI_MUTEX_HANDLE       mutex_id)
-{
-	ACPI_STATUS             status;
-
-
-	if (mutex_id > MAX_MTX) {
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex);
-
-	acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL;
-	acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE;
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_acquire_mutex
- *
- * PARAMETERS:  Mutex_iD        - ID of the mutex to be acquired
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Acquire a mutex object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_acquire_mutex (
-	ACPI_MUTEX_HANDLE       mutex_id)
-{
-	ACPI_STATUS             status;
-
-
-	if (mutex_id > MAX_MTX) {
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex,
-			   1, WAIT_FOREVER);
-
-	if (ACPI_SUCCESS (status)) {
-		acpi_gbl_acpi_mutex_info[mutex_id].locked = TRUE;
-		acpi_gbl_acpi_mutex_info[mutex_id].use_count++;
-	}
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_release_mutex
- *
- * PARAMETERS:  Mutex_iD        - ID of the mutex to be released
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Release a mutex object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_release_mutex (
-	ACPI_MUTEX_HANDLE       mutex_id)
-{
-	ACPI_STATUS             status;
-
-
-	if (mutex_id > MAX_MTX) {
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; /* Mark before unlocking */
-
-	status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1);
-
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_update_state_and_push
- *
- * PARAMETERS:  *Object         - Object to be added to the new state
- *              Action          - Increment/Decrement
- *              State_list      - List the state will be added to
- *
- * RETURN:      None
- *
- * DESCRIPTION: Create a new state and push it
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_create_update_state_and_push (
-	ACPI_OPERAND_OBJECT     *object,
-	u16                     action,
-	ACPI_GENERIC_STATE      **state_list)
-{
-	ACPI_GENERIC_STATE       *state;
-
-
-	/* Ignore null objects; these are expected */
-
-	if (!object) {
-		return (AE_OK);
-	}
-
-	state = acpi_cm_create_update_state (object, action);
-	if (!state) {
-		return (AE_NO_MEMORY);
-	}
-
-
-	acpi_cm_push_generic_state (state_list, state);
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_pkg_state_and_push
- *
- * PARAMETERS:  *Object         - Object to be added to the new state
- *              Action          - Increment/Decrement
- *              State_list      - List the state will be added to
- *
- * RETURN:      None
- *
- * DESCRIPTION: Create a new state and push it
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_create_pkg_state_and_push (
-	void                    *internal_object,
-	void                    *external_object,
-	u16                     index,
-	ACPI_GENERIC_STATE      **state_list)
-{
-	ACPI_GENERIC_STATE       *state;
-
-
-	state = acpi_cm_create_pkg_state (internal_object, external_object, index);
-	if (!state) {
-		return (AE_NO_MEMORY);
-	}
-
-
-	acpi_cm_push_generic_state (state_list, state);
-	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_push_generic_state
- *
- * PARAMETERS:  List_head           - Head of the state stack
- *              State               - State object to push
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Push a state object onto a state stack
- *
- ******************************************************************************/
-
-void
-acpi_cm_push_generic_state (
-	ACPI_GENERIC_STATE      **list_head,
-	ACPI_GENERIC_STATE      *state)
-{
-	/* Push the state object onto the front of the list (stack) */
-
-	state->common.next = *list_head;
-	*list_head = state;
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_pop_generic_state
- *
- * PARAMETERS:  List_head           - Head of the state stack
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Pop a state object from a state stack
- *
- ******************************************************************************/
-
-ACPI_GENERIC_STATE *
-acpi_cm_pop_generic_state (
-	ACPI_GENERIC_STATE      **list_head)
-{
-	ACPI_GENERIC_STATE      *state;
-
-
-	/* Remove the state object at the head of the list (stack) */
-
-	state = *list_head;
-	if (state) {
-		/* Update the list head */
-
-		*list_head = state->common.next;
-	}
-
-	return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_generic_state
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create a generic state object.  Attempt to obtain one from
- *              the global state cache;  If none available, create a new one.
- *
- ******************************************************************************/
-
-ACPI_GENERIC_STATE *
-acpi_cm_create_generic_state (void)
-{
-	ACPI_GENERIC_STATE      *state;
-
-
-	acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
-
-	acpi_gbl_state_cache_requests++;
-
-	/* Check the cache first */
-
-	if (acpi_gbl_generic_state_cache) {
-		/* There is an object available, use it */
-
-		state = acpi_gbl_generic_state_cache;
-		acpi_gbl_generic_state_cache = state->common.next;
-		state->common.next = NULL;
-
-		acpi_gbl_state_cache_hits++;
-		acpi_gbl_generic_state_cache_depth--;
-
-		acpi_cm_release_mutex (ACPI_MTX_CACHES);
-
-	}
-
-	else {
-		/* The cache is empty, create a new object */
-
-		acpi_cm_release_mutex (ACPI_MTX_CACHES);
-
-		state = acpi_cm_callocate (sizeof (ACPI_GENERIC_STATE));
-	}
-
-	/* Initialize */
-
-	if (state) {
-		/* Always zero out the object before init */
-
-		MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE));
-
-		state->common.data_type = ACPI_DESC_TYPE_STATE;
-	}
-
-	return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_update_state
- *
- * PARAMETERS:  Object              - Initial Object to be installed in the
- *                                    state
- *              Action              - Update action to be performed
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
- *              to update reference counts and delete complex objects such
- *              as packages.
- *
- ******************************************************************************/
-
-ACPI_GENERIC_STATE *
-acpi_cm_create_update_state (
-	ACPI_OPERAND_OBJECT     *object,
-	u16                     action)
-{
-	ACPI_GENERIC_STATE      *state;
-
-
-	/* Create the generic state object */
-
-	state = acpi_cm_create_generic_state ();
-	if (!state) {
-		return (NULL);
-	}
-
-	/* Init fields specific to the update struct */
-
-	state->update.object = object;
-	state->update.value  = action;
-
-	return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_pkg_state
- *
- * PARAMETERS:  Object              - Initial Object to be installed in the
- *                                    state
- *              Action              - Update action to be performed
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
- *              to update reference counts and delete complex objects such
- *              as packages.
- *
- ******************************************************************************/
-
-ACPI_GENERIC_STATE *
-acpi_cm_create_pkg_state (
-	void                    *internal_object,
-	void                    *external_object,
-	u16                     index)
-{
-	ACPI_GENERIC_STATE      *state;
-
-
-	/* Create the generic state object */
-
-	state = acpi_cm_create_generic_state ();
-	if (!state) {
-		return (NULL);
-	}
-
-	/* Init fields specific to the update struct */
-
-	state->pkg.source_object = (ACPI_OPERAND_OBJECT *) internal_object;
-	state->pkg.dest_object  = external_object;
-	state->pkg.index        = index;
-	state->pkg.num_packages = 1;
-
-	return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_create_control_state
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
- *              to support nested IF/WHILE constructs in the AML.
- *
- ******************************************************************************/
-
-ACPI_GENERIC_STATE *
-acpi_cm_create_control_state (
-	void)
-{
-	ACPI_GENERIC_STATE      *state;
-
-
-	/* Create the generic state object */
-
-	state = acpi_cm_create_generic_state ();
-	if (!state) {
-		return (NULL);
-	}
-
-
-	/* Init fields specific to the control struct */
-
-	state->common.state = CONTROL_CONDITIONAL_EXECUTING;
-
-	return (state);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_generic_state
- *
- * PARAMETERS:  State               - The state object to be deleted
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Put a state object back into the global state cache.  The object
- *              is not actually freed at this time.
- *
- ******************************************************************************/
-
-void
-acpi_cm_delete_generic_state (
-	ACPI_GENERIC_STATE      *state)
-{
-
-	/* If cache is full, just free this state object */
-
-	if (acpi_gbl_generic_state_cache_depth >= MAX_STATE_CACHE_DEPTH) {
-		acpi_cm_free (state);
-	}
-
-	/* Otherwise put this object back into the cache */
-
-	else {
-		acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
-
-		/* Clear the state */
-
-		MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE));
-		state->common.data_type = ACPI_DESC_TYPE_STATE;
-
-		/* Put the object at the head of the global cache list */
-
-		state->common.next = acpi_gbl_generic_state_cache;
-		acpi_gbl_generic_state_cache = state;
-		acpi_gbl_generic_state_cache_depth++;
-
-
-		acpi_cm_release_mutex (ACPI_MTX_CACHES);
-	}
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_delete_generic_state_cache
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Purge the global state object cache.  Used during subsystem
- *              termination.
- *
- ******************************************************************************/
-
-void
-acpi_cm_delete_generic_state_cache (
-	void)
-{
-	ACPI_GENERIC_STATE      *next;
-
-
-	/* Traverse the global cache list */
-
-	while (acpi_gbl_generic_state_cache) {
-		/* Delete one cached state object */
-
-		next = acpi_gbl_generic_state_cache->common.next;
-		acpi_cm_free (acpi_gbl_generic_state_cache);
-		acpi_gbl_generic_state_cache = next;
-		acpi_gbl_generic_state_cache_depth--;
-	}
-
-	return;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_resolve_package_references
- *
- * PARAMETERS:  Obj_desc        - The Package object on which to resolve refs
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Walk through a package and turn internal references into values
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_resolve_package_references (
-	ACPI_OPERAND_OBJECT     *obj_desc)
-{
-	u32                     count;
-	ACPI_OPERAND_OBJECT     *sub_object;
-
-
-	if (obj_desc->common.type != ACPI_TYPE_PACKAGE) {
-		/* The object must be a package */
-
-		REPORT_ERROR (("Must resolve Package Refs on a Package\n"));
-		return(AE_ERROR);
-	}
-
-	/*
-	 * TBD: what about nested packages? */
-
-	for (count = 0; count < obj_desc->package.count; count++) {
-		sub_object = obj_desc->package.elements[count];
-
-		if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) {
-			if (sub_object->reference.op_code == AML_ZERO_OP) {
-				sub_object->common.type = ACPI_TYPE_INTEGER;
-				sub_object->integer.value = 0;
-			}
-			else if (sub_object->reference.op_code == AML_ONE_OP) {
-				sub_object->common.type = ACPI_TYPE_INTEGER;
-				sub_object->integer.value = 1;
-			}
-			else if (sub_object->reference.op_code == AML_ONES_OP) {
-				sub_object->common.type = ACPI_TYPE_INTEGER;
-				sub_object->integer.value = ACPI_INTEGER_MAX;
-			}
-		}
-	}
-
-	return(AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_cm_walk_package_tree
- *
- * PARAMETERS:  Obj_desc        - The Package object on which to resolve refs
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Walk through a package
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_cm_walk_package_tree (
-	ACPI_OPERAND_OBJECT     *source_object,
-	void                    *target_object,
-	ACPI_PKG_CALLBACK       walk_callback,
-	void                    *context)
-{
-	ACPI_STATUS             status = AE_OK;
-	ACPI_GENERIC_STATE      *state_list = NULL;
-	ACPI_GENERIC_STATE      *state;
-	u32                     this_index;
-	ACPI_OPERAND_OBJECT     *this_source_obj;
-
-
-	state = acpi_cm_create_pkg_state (source_object, target_object, 0);
-	if (!state) {
-		return (AE_NO_MEMORY);
-	}
-
-	while (state) {
-		this_index       = state->pkg.index;
-		this_source_obj  = (ACPI_OPERAND_OBJECT *)
-				   state->pkg.source_object->package.elements[this_index];
-
-		/*
-		 * Check for
-		 * 1) An uninitialized package element.  It is completely
-		 *      legal to declare a package and leave it uninitialized
-		 * 2) Not an internal object - can be a namespace node instead
-		 * 3) Any type other than a package.  Packages are handled in else case below.
-		 */
-		if ((!this_source_obj) ||
-			(!VALID_DESCRIPTOR_TYPE (
-					this_source_obj, ACPI_DESC_TYPE_INTERNAL)) ||
-			(!IS_THIS_OBJECT_TYPE (
-					this_source_obj, ACPI_TYPE_PACKAGE)))
-		{
-
-			status = walk_callback (0, this_source_obj, state, context);
-			if (ACPI_FAILURE (status)) {
-				/* TBD: must delete package created up to this point */
-
-				return (status);
-			}
-
-			state->pkg.index++;
-			while (state->pkg.index >= state->pkg.source_object->package.count) {
-				/*
-				 * We've handled all of the objects at this level,  This means
-				 * that we have just completed a package.  That package may
-				 * have contained one or more packages itself.
-				 *
-				 * Delete this state and pop the previous state (package).
-				 */
-				acpi_cm_delete_generic_state (state);
-				state = acpi_cm_pop_generic_state (&state_list);
-
-
-				/* Finished when there are no more states */
-
-				if (!state) {
-					/*
-					 * We have handled all of the objects in the top level
-					 * package just add the length of the package objects
-					 * and exit
-					 */
-					return (AE_OK);
-				}
-
-				/*
-				 * Go back up a level and move the index past the just
-				 * completed package object.
-				 */
-				state->pkg.index++;
-			}
-		}
-
-		else {
-			/* This is a sub-object of type package */
-
-			status = walk_callback (1, this_source_obj, state, context);
-			if (ACPI_FAILURE (status)) {
-				/* TBD: must delete package created up to this point */
-
-				return (status);
-			}
-
-
-			/*
-			 * The callback above returned a new target package object.
-			 */
-
-			/*
-			 * Push the current state and create a new one
-			 */
-			acpi_cm_push_generic_state (&state_list, state);
-			state = acpi_cm_create_pkg_state (this_source_obj, state->pkg.this_target_obj, 0);
-			if (!state) {
-				/* TBD: must delete package created up to this point */
-
-				return (AE_NO_MEMORY);
-			}
-		}
-	}
-
-	/* We should never get here */
-
-	return (AE_AML_INTERNAL);
-
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    _Report_error
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Message             - Error message to use on failure
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print error message
- *
- ******************************************************************************/
-
-void
-_report_error (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id)
-{
-
-
-	acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    _Report_warning
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Message             - Error message to use on failure
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print warning message
- *
- ******************************************************************************/
-
-void
-_report_warning (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id)
-{
-
-	acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    _Report_info
- *
- * PARAMETERS:  Module_name         - Caller's module name (for error output)
- *              Line_number         - Caller's line number (for error output)
- *              Component_id        - Caller's component ID (for error output)
- *              Message             - Error message to use on failure
- *
- * RETURN:      None
- *
- * DESCRIPTION: Print information message
- *
- ******************************************************************************/
-
-void
-_report_info (
-	NATIVE_CHAR             *module_name,
-	u32                     line_number,
-	u32                     component_id)
-{
-
-	acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number);
-}
-
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/common/cmxface.c linux/drivers/acpi/common/cmxface.c
--- v2.4.5/linux/drivers/acpi/common/cmxface.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/common/cmxface.c	Wed Dec 31 16:00:00 1969
@@ -1,396 +0,0 @@
-/******************************************************************************
- *
- * Module Name: cmxface - External interfaces for "global" ACPI functions
- *              $Revision: 64 $
- *
- *****************************************************************************/
-
-/*
- *  Copyright (C) 2000, 2001 R. Byron Moore
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-
-#include "acpi.h"
-#include "acevents.h"
-#include "achware.h"
-#include "acnamesp.h"
-#include "acinterp.h"
-#include "amlcode.h"
-#include "acdebug.h"
-
-
-#define _COMPONENT          MISCELLANEOUS
-	 MODULE_NAME         ("cmxface")
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_initialize_subsystem
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Initializes all global variables.  This is the first function
- *              called, so any early initialization belongs here.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_initialize_subsystem (
-	void)
-{
-	ACPI_STATUS             status;
-
-
-	/* Initialize all globals used by the subsystem */
-
-	acpi_cm_init_globals ();
-
-	/* Initialize the OS-Dependent layer */
-
-	status = acpi_os_initialize ();
-	if (ACPI_FAILURE (status)) {
-		REPORT_ERROR (("OSD failed to initialize, %s\n",
-			acpi_cm_format_exception (status)));
-		return (status);
-	}
-
-	/* Create the default mutex objects */
-
-	status = acpi_cm_mutex_initialize ();
-	if (ACPI_FAILURE (status)) {
-		REPORT_ERROR (("Global mutex creation failure, %s\n",
-			acpi_cm_format_exception (status)));
-		return (status);
-	}
-
-	/*
-	 * Initialize the namespace manager and
-	 * the root of the namespace tree
-	 */
-
-	status = acpi_ns_root_initialize ();
-	if (ACPI_FAILURE (status)) {
-		REPORT_ERROR (("Namespace initialization failure, %s\n",
-			acpi_cm_format_exception (status)));
-		return (status);
-	}
-
-
-	/* If configured, initialize the AML debugger */
-
-	DEBUGGER_EXEC (acpi_db_initialize ());
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_enable_subsystem
- *
- * PARAMETERS:  Flags           - Init/enable Options
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Completes the subsystem initialization including hardware.
- *              Puts system into ACPI mode if it isn't already.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_enable_subsystem (
-	u32                     flags)
-{
-	ACPI_STATUS             status = AE_OK;
-
-
-	/* Sanity check the FADT for valid values */
-
-	status = acpi_cm_validate_fadt ();
-	if (ACPI_FAILURE (status)) {
-		return (status);
-	}
-
-	/*
-	 * Install the default Op_region handlers. These are
-	 * installed unless other handlers have already been
-	 * installed via the Install_address_space_handler interface
-	 */
-
-	if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
-		status = acpi_ev_install_default_address_space_handlers ();
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-	/*
-	 * We must initialize the hardware before we can enable ACPI.
-	 */
-
-	if (!(flags & ACPI_NO_HARDWARE_INIT)) {
-		status = acpi_hw_initialize ();
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-	/*
-	 * Enable ACPI on this platform
-	 */
-
-	if (!(flags & ACPI_NO_ACPI_ENABLE)) {
-		status = acpi_enable ();
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-	/*
-	 * Note:
-	 * We must have the hardware AND events initialized before we can execute
-	 * ANY control methods SAFELY.  Any control method can require ACPI hardware
-	 * support, so the hardware MUST be initialized before execution!
-	 */
-
-	if (!(flags & ACPI_NO_EVENT_INIT)) {
-		status = acpi_ev_initialize ();
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-
-	/*
-	 * Initialize all device objects in the namespace
-	 * This runs the _STA and _INI methods.
-	 */
-
-	if (!(flags & ACPI_NO_DEVICE_INIT)) {
-		status = acpi_ns_initialize_devices ();
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-
-	/*
-	 * Initialize the objects that remain uninitialized.  This
-	 * runs the executable AML that is part of the declaration of Op_regions
-	 * and Fields.
-	 */
-
-	if (!(flags & ACPI_NO_OBJECT_INIT)) {
-		status = acpi_ns_initialize_objects ();
-		if (ACPI_FAILURE (status)) {
-			return (status);
-		}
-	}
-
-
-	return (status);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_terminate
- *
- * PARAMETERS:  None
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Shutdown the ACPI subsystem.  Release all resources.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_terminate (void)
-{
-
-	/* Terminate the AML Debuger if present */
-
-	DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE);
-
-	/* TBD: [Investigate] This is no longer needed?*/
-/*    Acpi_cm_release_mutex (ACPI_MTX_DEBUG_CMD_READY); */
-
-
-	/* Shutdown and free all resources */
-
-	acpi_cm_subsystem_shutdown ();
-
-
-	/* Free the mutex objects */
-
-	acpi_cm_mutex_terminate ();
-
-
-	/* Now we can shutdown the OS-dependent layer */
-
-	acpi_os_terminate ();
-
-	return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_get_system_info
- *
- * PARAMETERS:  Out_buffer      - a pointer to a buffer to receive the
- *                                resources for the device
- *              Buffer_length   - the number of bytes available in the buffer
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: This function is called to get information about the current
- *              state of the ACPI subsystem.  It will return system information
- *              in the Out_buffer.
- *
- *              If the function fails an appropriate status will be returned
- *              and the value of Out_buffer is undefined.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_get_system_info (
-	ACPI_BUFFER             *out_buffer)
-{
-	ACPI_SYSTEM_INFO        *info_ptr;
-	u32                     i;
-
-
-	/*
-	 *  Must have a valid buffer
-	 */
-	if ((!out_buffer)         ||
-		(!out_buffer->pointer))
-	{
-		return (AE_BAD_PARAMETER);
-	}
-
-	if (out_buffer->length < sizeof (ACPI_SYSTEM_INFO)) {
-		/*
-		 *  Caller's buffer is too small
-		 */
-		out_buffer->length = sizeof (ACPI_SYSTEM_INFO);
-
-		return (AE_BUFFER_OVERFLOW);
-	}
-
-
-	/*
-	 *  Set return length and get data
-	 */
-	out_buffer->length = sizeof (ACPI_SYSTEM_INFO);
-	info_ptr = (ACPI_SYSTEM_INFO *) out_buffer->pointer;
-
-	info_ptr->acpi_ca_version   = ACPI_CA_VERSION;
-
-	/* System flags (ACPI capabilities) */
-
-	info_ptr->flags             = acpi_gbl_system_flags;
-
-	/* Timer resolution - 24 or 32 bits  */
-	if (!acpi_gbl_FADT) {
-		info_ptr->timer_resolution = 0;
-	}
-	else if (acpi_gbl_FADT->tmr_val_ext == 0) {
-		info_ptr->timer_resolution = 24;
-	}
-	else {
-		info_ptr->timer_resolution = 32;
-	}
-
-	/* Clear the reserved fields */
-
-	info_ptr->reserved1         = 0;
-	info_ptr->reserved2         = 0;
-
-	/* Current debug levels */
-
-	info_ptr->debug_layer       = acpi_dbg_layer;
-	info_ptr->debug_level       = acpi_dbg_level;
-
-	/* Current status of the ACPI tables, per table type */
-
-	info_ptr->num_table_types = NUM_ACPI_TABLES;
-	for (i = 0; i < NUM_ACPI_TABLES; i++) {
-		info_ptr->table_info[i].count = acpi_gbl_acpi_tables[i].count;
-	}
-
-	return (AE_OK);
-}
-
-
-/******************************************************************************
- *
- * FUNCTION:    Acpi_format_exception
- *
- * PARAMETERS:  Out_buffer      - a pointer to a buffer to receive the
- *                                exception name
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: This function translates an ACPI exception into an ASCII string.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_format_exception (
-	ACPI_STATUS             exception,
-	ACPI_BUFFER             *out_buffer)
-{
-	u32                     length;
-	NATIVE_CHAR             *formatted_exception;
-
-
-	/*
-	 *  Must have a valid buffer
-	 */
-	if ((!out_buffer)         ||
-		(!out_buffer->pointer))
-	{
-		return (AE_BAD_PARAMETER);
-	}
-
-
-	/* Convert the exception code (Handles bad exception codes) */
-
-	formatted_exception = acpi_cm_format_exception (exception);
-
-	/*
-	 * Get length of string and check if it will fit in caller's buffer
-	 */
-
-	length = STRLEN (formatted_exception);
-	if (out_buffer->length < length) {
-		out_buffer->length = length;
-		return (AE_BUFFER_OVERFLOW);
-	}
-
-
-	/* Copy the string, all done */
-
-	STRCPY (out_buffer->pointer, formatted_exception);
-
-	return (AE_OK);
-}
-
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/cpu.c linux/drivers/acpi/cpu.c
--- v2.4.5/linux/drivers/acpi/cpu.c	Fri Feb  9 11:45:58 2001
+++ linux/drivers/acpi/cpu.c	Wed Dec 31 16:00:00 1969
@@ -1,353 +0,0 @@
-/*
- *  cpu.c - Processor handling
- *
- *  Copyright (C) 2000 Andrew Henroid
- *  Copyright (C) 2001 Andrew Grover
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/pm.h>
-#include <linux/acpi.h>
-#include "acpi.h"
-#include "driver.h"
-
-#define _COMPONENT	OS_DEPENDENT
-	MODULE_NAME	("cpu")
-
-u32 acpi_c2_exit_latency = ACPI_INFINITE;
-u32 acpi_c3_exit_latency = ACPI_INFINITE;
-u32 acpi_c2_enter_latency = ACPI_INFINITE;
-u32 acpi_c3_enter_latency = ACPI_INFINITE;
-u32 acpi_use_idle = TRUE;
-
-u32 acpi_c1_count = 0;
-u32 acpi_c2_count = 0;
-u32 acpi_c3_count = 0;
-
-static u32 acpi_pblk = ACPI_INVALID;
-static int acpi_c2_tested = 0;
-static int acpi_c3_tested = 0;
-static int acpi_max_c_state = 1;
-static int acpi_pm_tmr_len = 24;
-
-#define CPU_POWER_STATES	3
-#define MAX_C2_LATENCY		100
-#define MAX_C3_LATENCY		1000
-
-#define ACPI_STATE_C1		0
-#define ACPI_STATE_C2		1
-#define ACPI_STATE_C3		2
-
-/*
- * Clear busmaster activity flag
- */
-static inline void
-acpi_clear_bm_activity(void)
-{
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1);
-}
-
-/*
- * Returns 1 if there has been busmaster activity
- */
-static inline int
-acpi_bm_activity(void)
-{
-	return acpi_hw_register_bit_access(ACPI_READ, ACPI_MTX_LOCK, BM_STS);
-}
-
-/*
- * Set system to sleep through busmaster requests
- */
-static void
-acpi_sleep_on_busmaster(void)
-{
-	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 1);
-}
-
-/*
- * Set system to wake on busmaster requests
- */
-static void
-acpi_wake_on_busmaster(void)
-{
-	acpi_hw_register_bit_access (ACPI_WRITE, ACPI_MTX_LOCK, BM_RLD, 0);
-}
-
-u32
-acpi_read_pm_timer(void)
-{
-	return acpi_hw_register_read(ACPI_MTX_LOCK, PM_TIMER);
-}
-
-/*
- * Do a compare, accounting for 24/32bit rollover
- */
-static u32
-acpi_compare_pm_timers(u32 first, u32 second)
-{
-	if (first < second) {
-		return (second - first);
-	} else {
-		if (acpi_pm_tmr_len == 24)
-			return (second + (0xFFFFFF - first));
-		else
-			return (second + (0xFFFFFFFF - first));
-	}
-}
-
-
-/*
- * Idle loop (uniprocessor only)
- */
-static void
-acpi_idle(void)
-{
-	static int sleep_level = 1;
-	FADT_DESCRIPTOR *fadt = &acpi_fadt;
-
-	/*
-	 * start from the previous sleep level.
-	 * if not initialized, we goto sleep1
-	 */
-	if (sleep_level == 1
-	    || acpi_max_c_state < 2)
-		goto sleep1;
-
-	if (sleep_level == 2
-	    || acpi_max_c_state < 3)
-		goto sleep2;
-
-sleep3:
-	sleep_level = 3;
-	if (!acpi_c3_tested) {
-		DEBUG_PRINT(ACPI_INFO, ("C3 works\n"));
-		acpi_c3_tested = 1;
-	}
-	acpi_wake_on_busmaster();
-	if (fadt->Xpm2_cnt_blk.address)
-		goto sleep3_with_arbiter;
-
-	for (;;) {
-		unsigned long time;
-		unsigned long diff;
-		
-		__cli();
-		if (current->need_resched)
-			goto out;
-		if (acpi_bm_activity())
-			goto sleep2;
-
-		time = acpi_read_pm_timer();
-		acpi_c3_count++;
-		inb(acpi_pblk + ACPI_P_LVL3);
-		/* Dummy read, force synchronization with the PMU */
-		acpi_read_pm_timer();
-		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
-
-		__sti();
-		if (diff < acpi_c3_exit_latency)
-			goto sleep1;
-	}
-
-sleep3_with_arbiter:
-	for (;;) {
-		unsigned long time;
-		unsigned long diff;
-
-		__cli();
-		if (current->need_resched)
-			goto out;
-		if (acpi_bm_activity())
-			goto sleep2;
-
-		time = acpi_read_pm_timer();
-		
-		/* Disable arbiter, park on CPU */
-		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);
-		acpi_c3_count++;
-		inb(acpi_pblk + ACPI_P_LVL3);
-		/* Dummy read, force synchronization with the PMU */
-		acpi_read_pm_timer();
-		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
-		/* Enable arbiter again.. */
-		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 0);
-
-		__sti();
-		if (diff < acpi_c3_exit_latency)
-			goto sleep1;
-	}
-
-sleep2:
-	sleep_level = 2;
-	if (!acpi_c2_tested) {
-		DEBUG_PRINT(ACPI_INFO, ("C2 works\n"));
-		acpi_c2_tested = 1;
-	}
-	acpi_wake_on_busmaster();	/* Required to track BM activity.. */
-	for (;;) {
-		unsigned long time;
-		unsigned long diff;
-
-		__cli();
-		if (current->need_resched)
-			goto out;
-
-		time = acpi_read_pm_timer();
-		acpi_c2_count++;
-		inb(acpi_pblk + ACPI_P_LVL2);
-		/* Dummy read, force synchronization with the PMU */
-		acpi_read_pm_timer();
-		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
-
-		__sti();
-		if (diff < acpi_c2_exit_latency)
-			goto sleep1;
-		if (acpi_bm_activity()) {
-			acpi_clear_bm_activity();
-			continue;
-		}
-		if (diff > acpi_c3_enter_latency
-		    && acpi_max_c_state >= 3)
-			goto sleep3;
-	}
-
-sleep1:
-	sleep_level = 1;
-	acpi_sleep_on_busmaster();
-	for (;;) {
-		unsigned long time;
-		unsigned long diff;
-
-		__cli();
-		if (current->need_resched)
-			goto out;
-		time = acpi_read_pm_timer();
-		acpi_c1_count++;
-		safe_halt();
-		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
-		if (diff > acpi_c2_enter_latency
-		    && acpi_max_c_state >= 2)
-			goto sleep2;
-	}
-
-out:
-	__sti();
-}
-
-/*
- * Get processor information
- */
-static ACPI_STATUS
-acpi_found_cpu(ACPI_HANDLE handle, u32 level, void *ctx, void **value)
-{
-	ACPI_OBJECT obj;
-	ACPI_BUFFER buf;
-
-	buf.length = sizeof(obj);
-	buf.pointer = &obj;
-	if (!ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buf)))
-		return AE_OK;
-
-	DEBUG_PRINT(ACPI_INFO, ("PBLK %d @ 0x%04x:%d\n",
-			obj.processor.proc_id,
-			obj.processor.pblk_address,
-			obj.processor.pblk_length));
-
-	if (acpi_pblk != ACPI_INVALID
-	    || !obj.processor.pblk_address
-	    || obj.processor.pblk_length != 6)
-		return AE_OK;
-
-	acpi_pblk = obj.processor.pblk_address;
-
-	if (acpi_fadt.plvl2_lat
-	    && acpi_fadt.plvl2_lat <= MAX_C2_LATENCY) {
-		acpi_c2_exit_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat);
-		acpi_c2_enter_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat * 4);
-		acpi_max_c_state = 2;
-
-		printk(KERN_INFO "ACPI: System firmware supports: C2");
-			
-		if (acpi_fadt.plvl3_lat
-		    && acpi_fadt.plvl3_lat <= MAX_C3_LATENCY) {
-			acpi_c3_exit_latency
-				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat);
-			acpi_c3_enter_latency
-				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 12);
-			acpi_max_c_state = 3;
-
-			printk(" C3");
-		}
-
-		printk("\n");
-	}
-
-	printk(KERN_INFO "ACPI: plvl2lat=%d plvl3lat=%d\n", acpi_fadt.plvl2_lat, acpi_fadt.plvl3_lat);
-	printk(KERN_INFO "ACPI: C2 enter=%d C2 exit=%d\n", acpi_c2_enter_latency, acpi_c2_exit_latency);
-	printk(KERN_INFO "ACPI: C3 enter=%d C3 exit=%d\n", acpi_c3_enter_latency, acpi_c3_exit_latency);
-
-	return AE_OK;
-}
-
-static int
-acpi_pm_timer_init(void)
-{
-	FADT_DESCRIPTOR *fadt = &acpi_fadt;
-
-	if (fadt->tmr_val_ext) {
-		acpi_pm_tmr_len = 32;
-	} else {
-		acpi_pm_tmr_len = 24;
-	}
-
-	DEBUG_PRINT(ACPI_INFO, ("PM Timer width: %d bits\n", acpi_pm_tmr_len));
-
-	return AE_OK;
-}
-
-int
-acpi_cpu_init(void)
-{
-	acpi_walk_namespace(ACPI_TYPE_PROCESSOR,
-			    ACPI_ROOT_OBJECT,
-			    ACPI_UINT32_MAX,
-			    acpi_found_cpu,
-			    NULL,
-			    NULL);
-
-	acpi_pm_timer_init();
-
-	if (acpi_use_idle) {
-#ifdef CONFIG_SMP
-		if (smp_num_cpus == 1)
-			pm_idle = acpi_idle;
-#else
-		pm_idle = acpi_idle;
-#endif
-		printk(KERN_INFO "ACPI: Using ACPI idle\n");
-		printk(KERN_INFO "ACPI: If experiencing system slowness, try adding \"acpi=no-idle\" to cmdline\n");
-	}
-	else {
-		printk(KERN_INFO "ACPI: Not using ACPI idle\n");
-	}
-
-	return 0;
-}
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbcmds.c linux/drivers/acpi/debugger/dbcmds.c
--- v2.4.5/linux/drivers/acpi/debugger/dbcmds.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/debugger/dbcmds.c	Wed Jun 20 17:47:39 2001
@@ -0,0 +1,987 @@
+/*******************************************************************************
+ *
+ * Module Name: dbcmds - debug commands and output routines
+ *              $Revision: 60 $
+ *
+ ******************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+#include "acparser.h"
+#include "acevents.h"
+#include "acinterp.h"
+#include "acdebug.h"
+#include "actables.h"
+#include "acresrc.h"
+
+#ifdef ENABLE_DEBUGGER
+
+#define _COMPONENT          ACPI_DEBUGGER
+	 MODULE_NAME         ("dbcmds")
+
+
+/*
+ * Arguments for the Objects command
+ * These object types map directly to the ACPI_TYPES
+ */
+
+ARGUMENT_INFO               acpi_db_object_types [] =
+{ {"ANY"},
+	{"NUMBERS"},
+	{"STRINGS"},
+	{"BUFFERS"},
+	{"PACKAGES"},
+	{"FIELDS"},
+	{"DEVICES"},
+	{"EVENTS"},
+	{"METHODS"},
+	{"MUTEXES"},
+	{"REGIONS"},
+	{"POWERRESOURCES"},
+	{"PROCESSORS"},
+	{"THERMALZONES"},
+	{"BUFFERFIELDS"},
+	{"DDBHANDLES"},
+	{NULL}           /* Must be null terminated */
+};
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_walk_for_references
+ *
+ * PARAMETERS:  Callback from Walk_namespace
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Check if this namespace object refers to the target object
+ *              that is passed in as the context value.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_walk_for_references (
+	ACPI_HANDLE             obj_handle,
+	u32                     nesting_level,
+	void                    *context,
+	void                    **return_value)
+{
+	ACPI_OPERAND_OBJECT     *obj_desc = (ACPI_OPERAND_OBJECT *) context;
+	ACPI_NAMESPACE_NODE     *node = (ACPI_NAMESPACE_NODE *) obj_handle;
+
+
+	/* Check for match against the namespace node itself */
+
+	if (node == (void *) obj_desc) {
+		acpi_os_printf ("Object is a Node [%4.4s]\n", &node->name);
+	}
+
+	/* Check for match against the object attached to the node */
+
+	if (node->object == obj_desc) {
+		acpi_os_printf ("Reference at Node->Object %p [%4.4s]\n", node, &node->name);
+	}
+
+	/* Check first child for a match */
+	/* TBD: [Investigate] probably now obsolete with new datastructure */
+
+	if (node->child == (void *) obj_desc) {
+		acpi_os_printf ("Reference at Node->Child %p [%4.4s]\n", node, &node->name);
+	}
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_find_references
+ *
+ * PARAMETERS:  Object_arg      - String with hex value of the object
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Search namespace for all references to the input object
+ *
+ ******************************************************************************/
+
+void
+acpi_db_find_references (
+	NATIVE_CHAR             *object_arg)
+{
+	ACPI_OPERAND_OBJECT     *obj_desc;
+
+
+	/* Convert string to object pointer */
+
+	obj_desc = (ACPI_OPERAND_OBJECT *) STRTOUL (object_arg, NULL, 16);
+
+	/* Search all nodes in namespace */
+
+	acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			  acpi_db_walk_for_references, (void *) obj_desc, NULL);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_locks
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display information about internal mutexes.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_locks (void)
+{
+	u32                     i;
+
+
+	for (i = 0; i < MAX_MTX; i++) {
+		acpi_os_printf ("%26s : %s\n", acpi_ut_get_mutex_name (i),
+				 acpi_gbl_acpi_mutex_info[i].owner_id == ACPI_MUTEX_NOT_ACQUIRED
+						? "Locked" : "Unlocked");
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_table_info
+ *
+ * PARAMETERS:  Table_arg       - String with name of table to be displayed
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display information about loaded tables.  Current
+ *              implementation displays all loaded tables.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_table_info (
+	NATIVE_CHAR             *table_arg)
+{
+	u32                     i;
+
+
+	for (i = 0; i < NUM_ACPI_TABLES; i++) {
+		if (acpi_gbl_acpi_tables[i].pointer) {
+			acpi_os_printf ("%s at %p length %X\n", acpi_gbl_acpi_table_data[i].name,
+					 acpi_gbl_acpi_tables[i].pointer, acpi_gbl_acpi_tables[i].length);
+		}
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_unload_acpi_table
+ *
+ * PARAMETERS:  Table_arg       - Name of the table to be unloaded
+ *              Instance_arg    - Which instance of the table to unload (if
+ *                                there are multiple tables of the same type)
+ *
+ * RETURN:      Nonde
+ *
+ * DESCRIPTION: Unload an ACPI table.
+ *              Instance is not implemented
+ *
+ ******************************************************************************/
+
+void
+acpi_db_unload_acpi_table (
+	NATIVE_CHAR             *table_arg,
+	NATIVE_CHAR             *instance_arg)
+{
+	u32                     i;
+	ACPI_STATUS             status;
+
+
+	/* Search all tables for the target type */
+
+	for (i = 0; i < NUM_ACPI_TABLES; i++) {
+		if (!STRNCMP (table_arg, acpi_gbl_acpi_table_data[i].signature, acpi_gbl_acpi_table_data[i].sig_length)) {
+			/* Found the table, unload it */
+
+			status = acpi_unload_table (i);
+			if (ACPI_SUCCESS (status)) {
+				acpi_os_printf ("[%s] unloaded and uninstalled\n", table_arg);
+			}
+			else {
+				acpi_os_printf ("%s, while unloading [%s]\n", acpi_ut_format_exception (status), table_arg);
+			}
+
+			return;
+		}
+	}
+
+	acpi_os_printf ("Unknown table type [%s]\n", table_arg);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_set_method_breakpoint
+ *
+ * PARAMETERS:  Location            - AML offset of breakpoint
+ *              Walk_state          - Current walk info
+ *              Op                  - Current Op (from parse walk)
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Set a breakpoint in a control method at the specified
+ *              AML offset
+ *
+ ******************************************************************************/
+
+void
+acpi_db_set_method_breakpoint (
+	NATIVE_CHAR             *location,
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_PARSE_OBJECT       *op)
+{
+	u32                     address;
+
+
+	if (!op) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	/* Get and verify the breakpoint address */
+
+	address = STRTOUL (location, NULL, 16);
+	if (address <= op->aml_offset) {
+		acpi_os_printf ("Breakpoint %X is beyond current address %X\n", address, op->aml_offset);
+	}
+
+	/* Save breakpoint in current walk */
+
+	walk_state->method_breakpoint = address;
+	acpi_os_printf ("Breakpoint set at AML offset %X\n", address);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_set_method_call_breakpoint
+ *
+ * PARAMETERS:  Op                  - Current Op (from parse walk)
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Set a breakpoint in a control method at the specified
+ *              AML offset
+ *
+ ******************************************************************************/
+
+void
+acpi_db_set_method_call_breakpoint (
+	ACPI_PARSE_OBJECT       *op)
+{
+
+
+	if (!op) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+
+	acpi_gbl_step_to_next_call = TRUE;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_disassemble_aml
+ *
+ * PARAMETERS:  Statements          - Number of statements to disassemble
+ *              Op                  - Current Op (from parse walk)
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display disassembled AML (ASL) starting from Op for the number
+ *              of statements specified.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_disassemble_aml (
+	NATIVE_CHAR             *statements,
+	ACPI_PARSE_OBJECT       *op)
+{
+	u32                     num_statements = 8;
+
+
+	if (!op) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	if (statements) {
+		num_statements = STRTOUL (statements, NULL, 0);
+	}
+
+
+	acpi_db_display_op (NULL, op, num_statements);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_dump_namespace
+ *
+ * PARAMETERS:  Start_arg       - Node to begin namespace dump
+ *              Depth_arg       - Maximum tree depth to be dumped
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Dump entire namespace or a subtree.  Each node is displayed
+ *              with type and other information.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_dump_namespace (
+	NATIVE_CHAR             *start_arg,
+	NATIVE_CHAR             *depth_arg)
+{
+	ACPI_HANDLE             subtree_entry = acpi_gbl_root_node;
+	u32                     max_depth = ACPI_UINT32_MAX;
+
+
+	/* No argument given, just start at the root and dump entire namespace */
+
+	if (start_arg) {
+		/* Check if numeric argument, must be a Node */
+
+		if ((start_arg[0] >= 0x30) && (start_arg[0] <= 0x39)) {
+			subtree_entry = (ACPI_HANDLE) STRTOUL (start_arg, NULL, 16);
+			if (!acpi_os_readable (subtree_entry, sizeof (ACPI_NAMESPACE_NODE))) {
+				acpi_os_printf ("Address %p is invalid in this address space\n", subtree_entry);
+				return;
+			}
+
+			if (!VALID_DESCRIPTOR_TYPE ((subtree_entry), ACPI_DESC_TYPE_NAMED)) {
+				acpi_os_printf ("Address %p is not a valid Named object\n", subtree_entry);
+				return;
+			}
+		}
+
+		/* Alpha argument */
+
+		else {
+			/* The parameter is a name string that must be resolved to a Named obj*/
+
+			subtree_entry = acpi_db_local_ns_lookup (start_arg);
+			if (!subtree_entry) {
+				subtree_entry = acpi_gbl_root_node;
+			}
+		}
+
+		/* Now we can check for the depth argument */
+
+		if (depth_arg) {
+			max_depth = STRTOUL (depth_arg, NULL, 0);
+		}
+	}
+
+
+	acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT);
+	acpi_os_printf ("ACPI Namespace (from %p subtree):\n", subtree_entry);
+
+	/* Display the subtree */
+
+	acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT);
+	acpi_ns_dump_objects (ACPI_TYPE_ANY, max_depth, ACPI_UINT32_MAX, subtree_entry);
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_dump_namespace_by_owner
+ *
+ * PARAMETERS:  Owner_arg       - Owner ID whose nodes will be displayed
+ *              Depth_arg       - Maximum tree depth to be dumped
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Dump elements of the namespace that are owned by the Owner_id.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_dump_namespace_by_owner (
+	NATIVE_CHAR             *owner_arg,
+	NATIVE_CHAR             *depth_arg)
+{
+	ACPI_HANDLE             subtree_entry = acpi_gbl_root_node;
+	u32                     max_depth = ACPI_UINT32_MAX;
+	u16                     owner_id;
+
+
+	owner_id = (u16) STRTOUL (owner_arg, NULL, 0);
+
+
+	/* Now we can check for the depth argument */
+
+	if (depth_arg) {
+		max_depth = STRTOUL (depth_arg, NULL, 0);
+	}
+
+
+	acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT);
+	acpi_os_printf ("ACPI Namespace by owner %X:\n", owner_id);
+
+	/* Display the subtree */
+
+	acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT);
+	acpi_ns_dump_objects (ACPI_TYPE_ANY, max_depth, owner_id, subtree_entry);
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_send_notify
+ *
+ * PARAMETERS:  Name            - Name of ACPI object to send the notify to
+ *              Value           - Value of the notify to send.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Send an ACPI notification.  The value specified is sent to the
+ *              named object as an ACPI notify.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_send_notify (
+	NATIVE_CHAR             *name,
+	u32                     value)
+{
+	ACPI_NAMESPACE_NODE     *node;
+
+
+	/* Translate name to an Named object */
+
+	node = acpi_db_local_ns_lookup (name);
+	if (!node) {
+		return;
+	}
+
+	/* Decode Named object type */
+
+	switch (node->type) {
+	case ACPI_TYPE_DEVICE:
+	case ACPI_TYPE_THERMAL:
+
+		 /* Send the notify */
+
+		acpi_ev_queue_notify_request (node, value);
+		break;
+
+	default:
+		acpi_os_printf ("Named object is not a device or a thermal object\n");
+		break;
+	}
+
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_set_method_data
+ *
+ * PARAMETERS:  Type_arg        - L for local, A for argument
+ *              Index_arg       - which one
+ *              Value_arg       - Value to set.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Set a local or argument for the running control method.
+ *              NOTE: only object supported is Number.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_set_method_data (
+	NATIVE_CHAR             *type_arg,
+	NATIVE_CHAR             *index_arg,
+	NATIVE_CHAR             *value_arg)
+{
+	NATIVE_CHAR             type;
+	u32                     index;
+	u32                     value;
+	ACPI_WALK_STATE         *walk_state;
+	ACPI_OPERAND_OBJECT     *obj_desc;
+
+
+	/* Validate Type_arg */
+
+	STRUPR (type_arg);
+	type = type_arg[0];
+	if ((type != 'L') &&
+		(type != 'A')) {
+		acpi_os_printf ("Invalid SET operand: %s\n", type_arg);
+		return;
+	}
+
+	/* Get the index and value */
+
+	index = STRTOUL (index_arg, NULL, 16);
+	value = STRTOUL (value_arg, NULL, 16);
+
+	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
+	if (!walk_state) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+
+	/* Create and initialize the new object */
+
+	obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+	if (!obj_desc) {
+		acpi_os_printf ("Could not create an internal object\n");
+		return;
+	}
+
+	obj_desc->integer.value = value;
+
+
+	/* Store the new object into the target */
+
+	switch (type) {
+	case 'A':
+
+		/* Set a method argument */
+
+		if (index > MTH_NUM_ARGS) {
+			acpi_os_printf ("Arg%d - Invalid argument name\n", index);
+			return;
+		}
+
+		acpi_ds_store_object_to_local (AML_ARG_OP, index, obj_desc, walk_state);
+		obj_desc = walk_state->arguments[index].object;
+
+		acpi_os_printf ("Arg%d: ", index);
+		acpi_db_display_internal_object (obj_desc, walk_state);
+		break;
+
+	case 'L':
+
+		/* Set a method local */
+
+		if (index > MTH_NUM_LOCALS) {
+			acpi_os_printf ("Local%d - Invalid local variable name\n", index);
+			return;
+		}
+
+		acpi_ds_store_object_to_local (AML_LOCAL_OP, index, obj_desc, walk_state);
+		obj_desc = walk_state->local_variables[index].object;
+
+		acpi_os_printf ("Local%d: ", index);
+		acpi_db_display_internal_object (obj_desc, walk_state);
+		break;
+
+	default:
+		break;
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_walk_for_specific_objects
+ *
+ * PARAMETERS:  Callback from Walk_namespace
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Display short info about objects in the namespace
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_walk_for_specific_objects (
+	ACPI_HANDLE             obj_handle,
+	u32                     nesting_level,
+	void                    *context,
+	void                    **return_value)
+{
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	ACPI_STATUS             status;
+	u32                     buf_size;
+	NATIVE_CHAR             buffer[64];
+
+
+	obj_desc = ((ACPI_NAMESPACE_NODE *)obj_handle)->object;
+	buf_size = sizeof (buffer) / sizeof (*buffer);
+
+	/* Get and display the full pathname to this object */
+
+	status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer);
+
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle);
+		return (AE_OK);
+	}
+
+	acpi_os_printf ("%32s", buffer);
+
+
+	/* Display short information about the object */
+
+	if (obj_desc) {
+		switch (obj_desc->common.type) {
+		case ACPI_TYPE_METHOD:
+			acpi_os_printf (" #Args %d Concurrency %X", obj_desc->method.param_count, obj_desc->method.concurrency);
+			break;
+
+		case ACPI_TYPE_INTEGER:
+			acpi_os_printf (" Value %X", obj_desc->integer.value);
+			break;
+
+		case ACPI_TYPE_STRING:
+			acpi_os_printf (" \"%s\"", obj_desc->string.pointer);
+			break;
+
+		case ACPI_TYPE_REGION:
+			acpi_os_printf (" Space_id %X Address %X Length %X", obj_desc->region.space_id, obj_desc->region.address, obj_desc->region.length);
+			break;
+
+		case ACPI_TYPE_PACKAGE:
+			acpi_os_printf (" #Elements %X", obj_desc->package.count);
+			break;
+
+		case ACPI_TYPE_BUFFER:
+			acpi_os_printf (" Length %X", obj_desc->buffer.length);
+			break;
+		}
+	}
+
+	acpi_os_printf ("\n");
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_objects
+ *
+ * PARAMETERS:  Obj_type_arg        - Type of object to display
+ *              Display_count_arg   - Max depth to display
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display objects in the namespace of the requested type
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_display_objects (
+	NATIVE_CHAR             *obj_type_arg,
+	NATIVE_CHAR             *display_count_arg)
+{
+	ACPI_OBJECT_TYPE8       type;
+
+
+	/* Get the object type */
+
+	type = acpi_db_match_argument (obj_type_arg, acpi_db_object_types);
+	if (type == ACPI_TYPE_NOT_FOUND) {
+		acpi_os_printf ("Invalid or unsupported argument\n");
+		return (AE_OK);
+	}
+
+	acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT);
+	acpi_os_printf ("Objects of type [%s] defined in the current ACPI Namespace: \n", acpi_ut_get_type_name (type));
+
+	acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT);
+
+	/* Walk the namespace from the root */
+
+	acpi_walk_namespace (type, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			   acpi_db_walk_for_specific_objects, (void *) &type, NULL);
+
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_walk_and_match_name
+ *
+ * PARAMETERS:  Callback from Walk_namespace
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Find a particular name/names within the namespace.  Wildcards
+ *              are supported -- '?' matches any character.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_walk_and_match_name (
+	ACPI_HANDLE             obj_handle,
+	u32                     nesting_level,
+	void                    *context,
+	void                    **return_value)
+{
+	ACPI_STATUS             status;
+	NATIVE_CHAR             *requested_name = (NATIVE_CHAR *) context;
+	u32                     i;
+	u32                     buf_size;
+	NATIVE_CHAR             buffer[96];
+
+
+	/* Check for a name match */
+
+	for (i = 0; i < 4; i++) {
+		/* Wildcard support */
+
+		if ((requested_name[i] != '?') &&
+			(requested_name[i] != ((NATIVE_CHAR *) (&((ACPI_NAMESPACE_NODE *) obj_handle)->name))[i])) {
+			/* No match, just exit */
+
+			return (AE_OK);
+		}
+	}
+
+
+	/* Get the full pathname to this object */
+
+	buf_size = sizeof (buffer) / sizeof (*buffer);
+
+	status = acpi_ns_handle_to_pathname (obj_handle, &buf_size, buffer);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could Not get pathname for object %p\n", obj_handle);
+	}
+
+	else {
+		acpi_os_printf ("%32s (%p) - %s\n", buffer, obj_handle,
+			acpi_ut_get_type_name (((ACPI_NAMESPACE_NODE *) obj_handle)->type));
+	}
+
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_find_name_in_namespace
+ *
+ * PARAMETERS:  Name_arg        - The 4-character ACPI name to find.
+ *                                wildcards are supported.
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Search the namespace for a given name (with wildcards)
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_find_name_in_namespace (
+	NATIVE_CHAR             *name_arg)
+{
+
+	if (STRLEN (name_arg) > 4) {
+		acpi_os_printf ("Name must be no longer than 4 characters\n");
+		return (AE_OK);
+	}
+
+	/* Walk the namespace from the root */
+
+	acpi_walk_namespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
+			   acpi_db_walk_and_match_name, name_arg, NULL);
+
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_set_scope
+ *
+ * PARAMETERS:  Name                - New scope path
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Set the "current scope" as maintained by this utility.
+ *              The scope is used as a prefix to ACPI paths.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_set_scope (
+	NATIVE_CHAR             *name)
+{
+
+	if (!name || name[0] == 0) {
+		acpi_os_printf ("Current scope: %s\n", scope_buf);
+		return;
+	}
+
+	acpi_db_prep_namestring (name);
+
+	/* TBD: [Future] Validate scope here */
+
+	if (name[0] == '\\') {
+		STRCPY (scope_buf, name);
+		STRCAT (scope_buf, "\\");
+	}
+
+	else {
+		STRCAT (scope_buf, name);
+		STRCAT (scope_buf, "\\");
+	}
+
+	acpi_os_printf ("New scope: %s\n", scope_buf);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_resources
+ *
+ * PARAMETERS:  Object_arg      - String with hex value of the object
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION:
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_resources (
+	NATIVE_CHAR             *object_arg)
+{
+#ifndef _IA16
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	ACPI_STATUS             status;
+	ACPI_BUFFER             return_obj;
+
+
+	acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT);
+
+	/* Convert string to object pointer */
+
+	obj_desc = (ACPI_OPERAND_OBJECT *) STRTOUL (object_arg, NULL, 16);
+
+	/* Prepare for a return object of arbitrary size */
+
+	return_obj.pointer          = buffer;
+	return_obj.length           = BUFFER_SIZE;
+
+	/* _PRT */
+
+	acpi_os_printf ("Evaluating _PRT\n");
+
+	status = acpi_evaluate_object (obj_desc, "_PRT", NULL, &return_obj);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could not obtain _PRT: %s\n", acpi_ut_format_exception (status));
+		goto go_cRS;
+	}
+
+	return_obj.pointer          = buffer;
+	return_obj.length           = BUFFER_SIZE;
+
+	status = acpi_get_irq_routing_table (obj_desc, &return_obj);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Get_irq_routing_table failed: %s\n", acpi_ut_format_exception (status));
+		goto go_cRS;
+	}
+
+
+	acpi_rs_dump_irq_list((u8 *)buffer);
+
+	/* _CRS */
+go_cRS:
+	acpi_os_printf ("Evaluating _CRS\n");
+
+	return_obj.pointer          = buffer;
+	return_obj.length           = BUFFER_SIZE;
+
+	status = acpi_evaluate_object (obj_desc, "_CRS", NULL, &return_obj);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could not obtain _CRS: %s\n", acpi_ut_format_exception (status));
+		goto go_pRS;
+	}
+
+	return_obj.pointer          = buffer;
+	return_obj.length           = BUFFER_SIZE;
+
+	status = acpi_get_current_resources (obj_desc, &return_obj);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Acpi_get_current_resources failed: %s\n", acpi_ut_format_exception (status));
+		goto go_pRS;
+	}
+
+	acpi_rs_dump_resource_list ((ACPI_RESOURCE *) buffer);
+
+	/* _PRS */
+go_pRS:
+	acpi_os_printf ("Evaluating _PRS\n");
+
+	return_obj.pointer          = buffer;
+	return_obj.length           = BUFFER_SIZE;
+
+	status = acpi_evaluate_object (obj_desc, "_PRS", NULL, &return_obj);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could not obtain _PRS: %s\n", acpi_ut_format_exception (status));
+		goto cleanup;
+	}
+
+	return_obj.pointer          = buffer;
+	return_obj.length           = BUFFER_SIZE;
+
+	status = acpi_get_possible_resources (obj_desc, &return_obj);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Acpi_get_possible_resources failed: %s\n", acpi_ut_format_exception (status));
+		goto cleanup;
+	}
+
+	acpi_rs_dump_resource_list ((ACPI_RESOURCE *) buffer);
+
+
+cleanup:
+
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+	return;
+#endif
+
+}
+
+
+#endif /* ENABLE_DEBUGGER */
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbdisasm.c linux/drivers/acpi/debugger/dbdisasm.c
--- v2.4.5/linux/drivers/acpi/debugger/dbdisasm.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/debugger/dbdisasm.c	Wed Jun 20 17:47:39 2001
@@ -0,0 +1,674 @@
+/*******************************************************************************
+ *
+ * Module Name: dbdisasm - parser op tree display routines
+ *              $Revision: 40 $
+ *
+ ******************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+#include "acdebug.h"
+
+
+#ifdef ENABLE_DEBUGGER
+
+#define _COMPONENT          ACPI_DEBUGGER
+	 MODULE_NAME         ("dbdisasm")
+
+
+#define MAX_SHOW_ENTRY      128
+#define BLOCK_PAREN         1
+#define BLOCK_BRACE         2
+#define DB_NO_OP_INFO       "            [%2.2d]  "
+#define DB_FULL_OP_INFO     "%5.5X #%4.4X [%2.2d]  "
+
+
+NATIVE_CHAR                 *INDENT_STRING = "....";
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_block_type
+ *
+ * PARAMETERS:  Op              - Object to be examined
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Type of block for this op (parens or braces)
+ *
+ ******************************************************************************/
+
+u32
+acpi_db_block_type (
+	ACPI_PARSE_OBJECT       *op)
+{
+
+	switch (op->opcode) {
+	case AML_METHOD_OP:
+		return (BLOCK_BRACE);
+		break;
+
+	default:
+		break;
+	}
+
+	return (BLOCK_PAREN);
+
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ps_display_object_pathname
+ *
+ * PARAMETERS:  Op              - Object whose pathname is to be obtained
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Diplay the pathname associated with a named object.  Two
+ *              versions. One searches the parse tree (for parser-only
+ *              applications suchas Acpi_dump), and the other searches the
+ *              ACPI namespace (the parse tree is probably deleted)
+ *
+ ******************************************************************************/
+
+#ifdef PARSER_ONLY
+
+ACPI_STATUS
+acpi_ps_display_object_pathname (
+	ACPI_PARSE_OBJECT       *op)
+{
+	ACPI_PARSE_OBJECT       *target_op;
+
+
+	/* Search parent tree up to the root if necessary */
+
+	target_op = acpi_ps_find (op, op->value.name, 0, 0);
+	if (!target_op) {
+		/*
+		 * Didn't find the name in the parse tree.  This may be
+		 * a problem, or it may simply be one of the predefined names
+		 * (such as _OS_).  Rather than worry about looking up all
+		 * the predefined names, just display the name as given
+		 */
+
+		acpi_os_printf (" **** Path not found in parse tree");
+	}
+
+	else {
+		/* The target was found, print the name and complete path */
+
+		acpi_os_printf (" (Path ");
+		acpi_db_display_path (target_op);
+		acpi_os_printf (")");
+	}
+
+	return (AE_OK);
+}
+
+#else
+
+ACPI_STATUS
+acpi_ps_display_object_pathname (
+	ACPI_PARSE_OBJECT       *op)
+{
+	ACPI_STATUS             status;
+	ACPI_NAMESPACE_NODE     *node;
+	NATIVE_CHAR             buffer[MAX_SHOW_ENTRY];
+	u32                     buffer_size = MAX_SHOW_ENTRY;
+
+
+	acpi_os_printf (" (Path ");
+
+	/* Just get the Node out of the Op object */
+
+	node = op->node;
+	if (!node) {
+		/*
+		 * No Named obj,  so we can't get the pathname since the object
+		 * is not in the namespace.  This can happen during single
+		 * stepping where a dynamic named object is *about* to be created.
+		 */
+		return (AE_OK);
+	}
+
+	/* Convert Named_desc/handle to a full pathname */
+
+	status = acpi_ns_handle_to_pathname (node, &buffer_size, buffer);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("****Could not get pathname****)");
+		return (status);
+	}
+
+	acpi_os_printf ("%s)", buffer);
+	return (AE_OK);
+}
+
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_op
+ *
+ * PARAMETERS:  Origin          - Starting object
+ *              Num_opcodes     - Max number of opcodes to be displayed
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display parser object and its children
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_op (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_PARSE_OBJECT       *origin,
+	u32                     num_opcodes)
+{
+	ACPI_PARSE_OBJECT       *op = origin;
+	ACPI_PARSE_OBJECT       *arg;
+	ACPI_PARSE_OBJECT       *depth;
+	u32                     depth_count = 0;
+	u32                     last_depth = 0;
+	u32                     i;
+	u32                     j;
+
+
+	if (op) {
+		while (op) {
+			/* indentation */
+
+			depth_count = 0;
+			if (!opt_verbose) {
+				depth_count++;
+			}
+
+			/* Determine the nesting depth of this argument */
+
+			for (depth = op->parent; depth; depth = depth->parent) {
+				arg = acpi_ps_get_arg (depth, 0);
+				while (arg && arg != origin) {
+					arg = arg->next;
+				}
+
+				if (arg) {
+					break;
+				}
+
+				depth_count++;
+			}
+
+
+			/* Open a new block if we are nested further than last time */
+
+			if (depth_count > last_depth) {
+				VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth));
+				for (i = 0; i < last_depth; i++) {
+					acpi_os_printf (INDENT_STRING);
+				}
+
+				if (acpi_db_block_type (op) == BLOCK_PAREN) {
+					acpi_os_printf ("(\n");
+				}
+				else {
+					acpi_os_printf ("{\n");
+				}
+			}
+
+			/* Close a block if we are nested less than last time */
+
+			else if (depth_count < last_depth) {
+				for (j = 0; j < (last_depth - depth_count); j++) {
+					VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - j));
+					for (i = 0; i < (last_depth - j - 1); i++) {
+						acpi_os_printf (INDENT_STRING);
+					}
+
+					if (acpi_db_block_type (op) == BLOCK_PAREN) {
+						acpi_os_printf (")\n");
+					}
+					else {
+						acpi_os_printf ("}\n");
+					}
+				}
+			}
+
+			/* In verbose mode, print the AML offset, opcode and depth count */
+
+			VERBOSE_PRINT ((DB_FULL_OP_INFO, (unsigned) op->aml_offset, op->opcode, depth_count));
+
+
+			/* Indent the output according to the depth count */
+
+			for (i = 0; i < depth_count; i++) {
+				acpi_os_printf (INDENT_STRING);
+			}
+
+
+			/* Now print the opcode */
+
+			acpi_db_display_opcode (walk_state, op);
+
+			/* Resolve a name reference */
+
+			if ((op->opcode == AML_INT_NAMEPATH_OP && op->value.name)  &&
+				(op->parent) &&
+				(opt_verbose)) {
+				acpi_ps_display_object_pathname (op);
+			}
+
+			acpi_os_printf ("\n");
+
+			/* Get the next node in the tree */
+
+			op = acpi_ps_get_depth_next (origin, op);
+			last_depth = depth_count;
+
+			num_opcodes--;
+			if (!num_opcodes) {
+				op = NULL;
+			}
+		}
+
+		/* Close the last block(s) */
+
+		depth_count = last_depth -1;
+		for (i = 0; i < last_depth; i++) {
+			VERBOSE_PRINT ((DB_NO_OP_INFO, last_depth - i));
+			for (j = 0; j < depth_count; j++) {
+				acpi_os_printf (INDENT_STRING);
+			}
+			acpi_os_printf ("}\n");
+			depth_count--;
+		}
+
+	}
+
+	else {
+		acpi_db_display_opcode (walk_state, op);
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_namestring
+ *
+ * PARAMETERS:  Name                - ACPI Name string to store
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display namestring. Handles prefix characters
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_namestring (
+	NATIVE_CHAR             *name)
+{
+	u32                     seg_count;
+	u8                      do_dot = FALSE;
+
+
+	if (!name) {
+		acpi_os_printf ("<NULL NAME PTR>");
+		return;
+	}
+
+	if (acpi_ps_is_prefix_char (GET8 (name))) {
+		/* append prefix character */
+
+		acpi_os_printf ("%1c", GET8 (name));
+		name++;
+	}
+
+	switch (GET8 (name)) {
+	case AML_DUAL_NAME_PREFIX:
+		seg_count = 2;
+		name++;
+		break;
+
+	case AML_MULTI_NAME_PREFIX_OP:
+		seg_count = (u32) GET8 (name + 1);
+		name += 2;
+		break;
+
+	default:
+		seg_count = 1;
+		break;
+	}
+
+	while (seg_count--) {
+		/* append Name segment */
+
+		if (do_dot) {
+			/* append dot */
+
+			acpi_os_printf (".");
+		}
+
+		acpi_os_printf ("%4.4s", name);
+		do_dot = TRUE;
+
+		name += 4;
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_path
+ *
+ * PARAMETERS:  Op                  - Named Op whose path is to be constructed
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Walk backwards from current scope and display the name
+ *              of each previous level of scope up to the root scope
+ *              (like "pwd" does with file systems)
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_path (
+	ACPI_PARSE_OBJECT       *op)
+{
+	ACPI_PARSE_OBJECT       *prev;
+	ACPI_PARSE_OBJECT       *search;
+	u32                     name;
+	u8                      do_dot = FALSE;
+	ACPI_PARSE_OBJECT       *name_path;
+
+
+	/* We are only interested in named objects */
+
+	if (!acpi_ps_is_node_op (op->opcode)) {
+		return;
+	}
+
+
+	if (acpi_ps_is_create_field_op (op->opcode)) {
+		/* Field creation - check for a fully qualified namepath */
+
+		if (op->opcode == AML_CREATE_FIELD_OP) {
+			name_path = acpi_ps_get_arg (op, 3);
+		}
+		else {
+			name_path = acpi_ps_get_arg (op, 2);
+		}
+
+		if ((name_path) &&
+			(name_path->value.string) &&
+			(name_path->value.string[0] == '\\')) {
+			acpi_db_display_namestring (name_path->value.string);
+			return;
+		}
+	}
+
+	prev = NULL;            /* Start with Root Node */
+
+	while (prev != op) {
+		/* Search upwards in the tree to find scope with "prev" as its parent */
+
+		search = op;
+		for (; ;) {
+			if (search->parent == prev) {
+				break;
+			}
+
+			/* Go up one level */
+
+			search = search->parent;
+		}
+
+		if (prev && !acpi_ps_is_field_op (search->opcode)) {
+			/* below root scope, append scope name */
+
+			if (do_dot) {
+				/* append dot */
+
+				acpi_os_printf (".");
+			}
+
+			if (acpi_ps_is_create_field_op (search->opcode)) {
+				if (op->opcode == AML_CREATE_FIELD_OP) {
+					name_path = acpi_ps_get_arg (op, 3);
+				}
+				else {
+					name_path = acpi_ps_get_arg (op, 2);
+				}
+
+				if ((name_path) &&
+					(name_path->value.string)) {
+					acpi_os_printf ("%4.4s", name_path->value.string);
+				}
+			}
+
+			else {
+				name = acpi_ps_get_name (search);
+				acpi_os_printf ("%4.4s", &name);
+			}
+
+			do_dot = TRUE;
+		}
+
+		prev = search;
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_opcode
+ *
+ * PARAMETERS:  Op                  - Op that is to be printed
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Store printed op in a Buffer and return its length
+ *              (or -1 if out of space)
+ *
+ * NOTE: Terse mode prints out ASL-like code.  Verbose mode adds more info.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_opcode (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_PARSE_OBJECT       *op)
+{
+	u8                      *byte_data;
+	u32                     byte_count;
+	u32                     i;
+	ACPI_OPCODE_INFO        *opc = NULL;
+	u32                     name;
+
+
+	if (!op) {
+		acpi_os_printf ("<NULL OP PTR>");
+	}
+
+
+	/* op and arguments */
+
+	switch (op->opcode) {
+
+	case AML_BYTE_OP:
+
+		if (opt_verbose) {
+			acpi_os_printf ("(u8) 0x%2.2X", op->value.integer & ACPI_UINT8_MAX);
+		}
+
+		else {
+			acpi_os_printf ("0x%2.2X", op->value.integer & ACPI_UINT8_MAX);
+		}
+
+		break;
+
+
+	case AML_WORD_OP:
+
+		if (opt_verbose) {
+			acpi_os_printf ("(u16) 0x%4.4X", op->value.integer & ACPI_UINT16_MAX);
+		}
+
+		else {
+			acpi_os_printf ("0x%4.4X", op->value.integer & ACPI_UINT16_MAX);
+		}
+
+		break;
+
+
+	case AML_DWORD_OP:
+
+		if (opt_verbose) {
+			acpi_os_printf ("(u32) 0x%8.8X", op->value.integer);
+		}
+
+		else {
+			acpi_os_printf ("0x%8.8X", op->value.integer);
+		}
+
+		break;
+
+
+	case AML_STRING_OP:
+
+		if (op->value.string) {
+			acpi_os_printf ("\"%s\"", op->value.string);
+		}
+
+		else {
+			acpi_os_printf ("<\"NULL STRING PTR\">");
+		}
+
+		break;
+
+
+	case AML_INT_STATICSTRING_OP:
+
+		if (op->value.string) {
+			acpi_os_printf ("\"%s\"", op->value.string);
+		}
+
+		else {
+			acpi_os_printf ("\"<NULL STATIC STRING PTR>\"");
+		}
+
+		break;
+
+
+	case AML_INT_NAMEPATH_OP:
+
+		acpi_db_display_namestring (op->value.name);
+		break;
+
+
+	case AML_INT_NAMEDFIELD_OP:
+
+		acpi_os_printf ("Named_field (Length 0x%8.8X)  ", op->value.integer);
+		break;
+
+
+	case AML_INT_RESERVEDFIELD_OP:
+
+		acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->value.integer);
+		break;
+
+
+	case AML_INT_ACCESSFIELD_OP:
+
+		acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->value.integer);
+		break;
+
+
+	case AML_INT_BYTELIST_OP:
+
+		if (opt_verbose) {
+			acpi_os_printf ("Byte_list   (Length 0x%8.8X)  ", op->value.integer);
+		}
+
+		else {
+			acpi_os_printf ("0x%2.2X", op->value.integer);
+
+			byte_count = op->value.integer;
+			byte_data = ((ACPI_PARSE2_OBJECT *) op)->data;
+
+			for (i = 0; i < byte_count; i++) {
+				acpi_os_printf (", 0x%2.2X", byte_data[i]);
+			}
+		}
+
+		break;
+
+
+	default:
+
+		/* Just get the opcode name and print it */
+
+		opc = acpi_ps_get_opcode_info (op->opcode);
+		acpi_os_printf ("%s", opc->name);
+
+
+#ifndef PARSER_ONLY
+		if ((op->opcode == AML_INT_RETURN_VALUE_OP) &&
+			(walk_state->results) &&
+			(walk_state->results->results.num_results)) {
+			acpi_db_decode_internal_object (walk_state->results->results.obj_desc [walk_state->results->results.num_results-1]);
+		}
+#endif
+
+		break;
+	}
+
+
+	if (!opc) {
+		/* If there is another element in the list, add a comma */
+
+		if (op->next) {
+			acpi_os_printf (",");
+		}
+	}
+
+
+	/*
+	 * If this is a named opcode, print the associated name value
+	 */
+
+	if (op && acpi_ps_is_named_op (op->opcode)) {
+		name = acpi_ps_get_name (op);
+		acpi_os_printf (" %4.4s", &name);
+
+		if (opt_verbose) {
+			acpi_os_printf (" (Path \\");
+			acpi_db_display_path (op);
+			acpi_os_printf (")");
+		}
+	}
+}
+
+
+#endif  /* ENABLE_DEBUGGER */
+
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbdisply.c linux/drivers/acpi/debugger/dbdisply.c
--- v2.4.5/linux/drivers/acpi/debugger/dbdisply.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/debugger/dbdisply.c	Wed Jun 20 17:47:39 2001
@@ -0,0 +1,780 @@
+/*******************************************************************************
+ *
+ * Module Name: dbdisply - debug display commands
+ *              $Revision: 45 $
+ *
+ ******************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+#include "acparser.h"
+#include "acevents.h"
+#include "acinterp.h"
+#include "acdebug.h"
+
+
+#ifdef ENABLE_DEBUGGER
+
+
+#define _COMPONENT          ACPI_DEBUGGER
+	 MODULE_NAME         ("dbdisply")
+
+
+/******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_get_pointer
+ *
+ * PARAMETERS:  Target          - Pointer to string to be converted
+ *
+ * RETURN:      Converted pointer
+ *
+ * DESCRIPTION: Convert an ascii pointer value to a real value
+ *
+ *****************************************************************************/
+
+void *
+acpi_db_get_pointer (
+	void                    *target)
+{
+	void                    *obj_ptr;
+
+
+#ifdef _IA16
+#include <stdio.h>
+
+	/* Have to handle 16-bit pointers of the form segment:offset */
+
+	if (!sscanf (target, "%p", &obj_ptr)) {
+		acpi_os_printf ("Invalid pointer: %s\n", target);
+		return (NULL);
+	}
+
+#else
+
+	/* Simple flat pointer */
+
+	obj_ptr = (void *) STRTOUL (target, NULL, 16);
+
+#endif
+
+	return (obj_ptr);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_dump_parser_descriptor
+ *
+ * PARAMETERS:  Op              - A parser Op descriptor
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display a formatted parser object
+ *
+ ******************************************************************************/
+
+void
+acpi_db_dump_parser_descriptor (
+	ACPI_PARSE_OBJECT       *op)
+{
+	ACPI_OPCODE_INFO        *info;
+
+
+	info = acpi_ps_get_opcode_info (op->opcode);
+
+	acpi_os_printf ("Parser Op Descriptor:\n");
+	acpi_os_printf ("%20.20s : %4.4X\n", "Opcode", op->opcode);
+
+	DEBUG_ONLY_MEMBERS (acpi_os_printf ("%20.20s : %s\n", "Opcode Name", info->name));
+
+	acpi_os_printf ("%20.20s : %p\n", "Value/Arg_list", op->value);
+	acpi_os_printf ("%20.20s : %p\n", "Parent", op->parent);
+	acpi_os_printf ("%20.20s : %p\n", "Next_op", op->next);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_decode_and_display_object
+ *
+ * PARAMETERS:  Target          - String with object to be displayed.  Names
+ *                                and hex pointers are supported.
+ *              Output_type     - Byte, Word, Dword, or Qword (B|W|D|Q)
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display a formatted ACPI object
+ *
+ ******************************************************************************/
+
+void
+acpi_db_decode_and_display_object (
+	NATIVE_CHAR             *target,
+	NATIVE_CHAR             *output_type)
+{
+	void                    *obj_ptr;
+	ACPI_NAMESPACE_NODE     *node;
+	u32                     display = DB_BYTE_DISPLAY;
+	NATIVE_CHAR             buffer[80];
+	ACPI_BUFFER             ret_buf;
+	ACPI_STATUS             status;
+	u32                     size;
+
+
+	if (!target) {
+		return;
+	}
+
+	/* Decode the output type */
+
+	if (output_type) {
+		STRUPR (output_type);
+		if (output_type[0] == 'W') {
+			display = DB_WORD_DISPLAY;
+		}
+		else if (output_type[0] == 'D') {
+			display = DB_DWORD_DISPLAY;
+		}
+		else if (output_type[0] == 'Q') {
+			display = DB_QWORD_DISPLAY;
+		}
+	}
+
+
+	ret_buf.length = sizeof (buffer);
+	ret_buf.pointer = buffer;
+
+	/* Differentiate between a number and a name */
+
+	if ((target[0] >= 0x30) && (target[0] <= 0x39)) {
+		obj_ptr = acpi_db_get_pointer (target);
+		if (!acpi_os_readable (obj_ptr, 16)) {
+			acpi_os_printf ("Address %p is invalid in this address space\n", obj_ptr);
+			return;
+		}
+
+		/* Decode the object type */
+
+		if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_NAMED)) {
+			/* This is a Node */
+
+			if (!acpi_os_readable (obj_ptr, sizeof (ACPI_NAMESPACE_NODE))) {
+				acpi_os_printf ("Cannot read entire Named object at address %p\n", obj_ptr);
+				return;
+			}
+
+			node = obj_ptr;
+			goto dump_nte;
+		}
+
+		else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_INTERNAL)) {
+			/* This is an ACPI OBJECT */
+
+			if (!acpi_os_readable (obj_ptr, sizeof (ACPI_OPERAND_OBJECT))) {
+				acpi_os_printf ("Cannot read entire ACPI object at address %p\n", obj_ptr);
+				return;
+			}
+
+			acpi_ut_dump_buffer (obj_ptr, sizeof (ACPI_OPERAND_OBJECT), display, ACPI_UINT32_MAX);
+			acpi_ex_dump_object_descriptor (obj_ptr, 1);
+		}
+
+		else if (VALID_DESCRIPTOR_TYPE ((obj_ptr), ACPI_DESC_TYPE_PARSER)) {
+			/* This is an Parser Op object */
+
+			if (!acpi_os_readable (obj_ptr, sizeof (ACPI_PARSE_OBJECT))) {
+				acpi_os_printf ("Cannot read entire Parser object at address %p\n", obj_ptr);
+				return;
+			}
+
+
+			acpi_ut_dump_buffer (obj_ptr, sizeof (ACPI_PARSE_OBJECT), display, ACPI_UINT32_MAX);
+			acpi_db_dump_parser_descriptor ((ACPI_PARSE_OBJECT *) obj_ptr);
+		}
+
+		else {
+			size = 16;
+			if (acpi_os_readable (obj_ptr, 64)) {
+				size = 64;
+			}
+
+			/* Just dump some memory */
+
+			acpi_ut_dump_buffer (obj_ptr, size, display, ACPI_UINT32_MAX);
+		}
+
+		return;
+	}
+
+
+	/* The parameter is a name string that must be resolved to a Named obj */
+
+	node = acpi_db_local_ns_lookup (target);
+	if (!node) {
+		return;
+	}
+
+
+dump_nte:
+	/* Now dump the Named obj */
+
+	status = acpi_get_name (node, ACPI_FULL_PATHNAME, &ret_buf);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could not convert name to pathname\n");
+	}
+
+	else {
+		acpi_os_printf ("Object Pathname: %s\n", ret_buf.pointer);
+	}
+
+	if (!acpi_os_readable (node, sizeof (ACPI_NAMESPACE_NODE))) {
+		acpi_os_printf ("Invalid Named object at address %p\n", node);
+		return;
+	}
+
+	acpi_ut_dump_buffer ((void *) node, sizeof (ACPI_NAMESPACE_NODE), display, ACPI_UINT32_MAX);
+	acpi_ex_dump_node (node, 1);
+
+	if (node->object) {
+		acpi_os_printf ("\n_attached Object (%p):\n", node->object);
+		if (!acpi_os_readable (node->object, sizeof (ACPI_OPERAND_OBJECT))) {
+			acpi_os_printf ("Invalid internal ACPI Object at address %p\n", node->object);
+			return;
+		}
+
+		acpi_ut_dump_buffer (node->object, sizeof (ACPI_OPERAND_OBJECT), display, ACPI_UINT32_MAX);
+		acpi_ex_dump_object_descriptor (node->object, 1);
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_decode_internal_object
+ *
+ * PARAMETERS:  Obj_desc        - Object to be displayed
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Short display of an internal object.  Numbers and Strings.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_decode_internal_object (
+	ACPI_OPERAND_OBJECT     *obj_desc)
+{
+	u32                     i;
+
+
+	if (!obj_desc) {
+		return;
+	}
+
+	acpi_os_printf (" %s", acpi_ut_get_type_name (obj_desc->common.type));
+
+	switch (obj_desc->common.type) {
+	case ACPI_TYPE_INTEGER:
+		acpi_os_printf (" %.8X", obj_desc->integer.value);
+		break;
+
+	case ACPI_TYPE_STRING:
+		acpi_os_printf ("(%d) \"%.16s\"...",
+				obj_desc->string.length, obj_desc->string.pointer);
+		break;
+
+	case ACPI_TYPE_BUFFER:
+		acpi_os_printf ("(%d)", obj_desc->buffer.length);
+		for (i = 0; (i < 8) && (i < obj_desc->buffer.length); i++) {
+			acpi_os_printf (" %2.2X", obj_desc->buffer.pointer[i]);
+		}
+		break;
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_internal_object
+ *
+ * PARAMETERS:  Obj_desc        - Object to be displayed
+ *              Walk_state      - Current walk state
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Short display of an internal object
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_internal_object (
+	ACPI_OPERAND_OBJECT     *obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+	u8                      type;
+
+
+	acpi_os_printf ("%p ", obj_desc);
+
+	if (!obj_desc) {
+		acpi_os_printf ("<Null_obj>\n");
+		return;
+	}
+
+
+	/* Decode the object type */
+
+	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_PARSER)) {
+		acpi_os_printf ("<Parser> ");
+	}
+
+	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
+		acpi_os_printf ("<Node>          Name %4.4s Type-%s",
+				  &((ACPI_NAMESPACE_NODE *)obj_desc)->name,
+				  acpi_ut_get_type_name (((ACPI_NAMESPACE_NODE *) obj_desc)->type));
+		if (((ACPI_NAMESPACE_NODE *) obj_desc)->flags & ANOBJ_METHOD_ARG) {
+			acpi_os_printf (" [Method Arg]");
+		}
+		if (((ACPI_NAMESPACE_NODE *) obj_desc)->flags & ANOBJ_METHOD_LOCAL) {
+			acpi_os_printf (" [Method Local]");
+		}
+	}
+
+	else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
+		acpi_os_printf ("<Obj> ");
+		type = obj_desc->common.type;
+		if (type > INTERNAL_TYPE_MAX) {
+			acpi_os_printf (" Type %x [Invalid Type]", type);
+			return;
+		}
+
+		/* Decode the ACPI object type */
+
+		switch (obj_desc->common.type) {
+		case INTERNAL_TYPE_REFERENCE:
+			switch (obj_desc->reference.opcode) {
+			case AML_ZERO_OP:
+				acpi_os_printf ("[Const]   Number %.8X", 0);
+				break;
+
+			case AML_ONES_OP:
+				acpi_os_printf ("[Const]   Number %.8X", ACPI_UINT32_MAX);
+				break;
+
+			case AML_ONE_OP:
+				acpi_os_printf ("[Const]   Number %.8X", 1);
+				break;
+
+			case AML_LOCAL_OP:
+				acpi_os_printf ("[Local%d] ", obj_desc->reference.offset);
+				if (walk_state) {
+					obj_desc = walk_state->local_variables[obj_desc->reference.offset].object;
+					acpi_db_decode_internal_object (obj_desc);
+				}
+				break;
+
+			case AML_ARG_OP:
+				acpi_os_printf ("[Arg%d]   ", obj_desc->reference.offset);
+				if (walk_state) {
+					obj_desc = walk_state->arguments[obj_desc->reference.offset].object;
+					acpi_db_decode_internal_object (obj_desc);
+				}
+				break;
+
+			case AML_DEBUG_OP:
+				acpi_os_printf ("[Debug] ");
+				break;
+
+			case AML_INDEX_OP:
+				acpi_os_printf ("[Index]   ");
+				acpi_db_decode_internal_object (obj_desc->reference.object);
+				break;
+
+			default:
+				break;
+
+			}
+			break;
+
+		default:
+			acpi_os_printf ("         ");
+			acpi_db_decode_internal_object (obj_desc);
+			break;
+		}
+	}
+
+	else {
+		acpi_os_printf ("<Not a valid ACPI Object Descriptor> ");
+	}
+
+	acpi_os_printf ("\n");
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_method_info
+ *
+ * PARAMETERS:  Start_op        - Root of the control method parse tree
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display information about the current method
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_method_info (
+	ACPI_PARSE_OBJECT       *start_op)
+{
+	ACPI_WALK_STATE         *walk_state;
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	ACPI_NAMESPACE_NODE     *node;
+	ACPI_PARSE_OBJECT       *root_op;
+	ACPI_PARSE_OBJECT       *op;
+	ACPI_OPCODE_INFO        *op_info;
+	u32                     num_ops = 0;
+	u32                     num_operands = 0;
+	u32                     num_operators = 0;
+	u32                     num_remaining_ops = 0;
+	u32                     num_remaining_operands = 0;
+	u32                     num_remaining_operators = 0;
+	u32                     num_args;
+	u32                     concurrency;
+	u8                      count_remaining = FALSE;
+
+
+	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
+	if (!walk_state) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	obj_desc = walk_state->method_desc;
+	node = walk_state->method_node;
+
+	num_args = obj_desc->method.param_count;
+	concurrency = obj_desc->method.concurrency;
+
+	acpi_os_printf ("Currently executing control method is [%4.4s]\n", &node->name);
+	acpi_os_printf ("%X arguments, max concurrency = %X\n", num_args, concurrency);
+
+
+	root_op = start_op;
+	while (root_op->parent) {
+		root_op = root_op->parent;
+	}
+
+	op = root_op;
+
+	while (op) {
+		if (op == start_op) {
+			count_remaining = TRUE;
+		}
+
+		num_ops++;
+		if (count_remaining) {
+			num_remaining_ops++;
+		}
+
+		op_info = acpi_ps_get_opcode_info (op->opcode);
+		if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
+			/* Bad opcode or ASCII character */
+
+			continue;
+		}
+
+
+		/* Decode the opcode */
+
+		switch (ACPI_GET_OP_CLASS (op_info)) {
+		case OPTYPE_CONSTANT:           /* argument type only */
+		case OPTYPE_LITERAL:            /* argument type only */
+		case OPTYPE_DATA_TERM:          /* argument type only */
+		case OPTYPE_LOCAL_VARIABLE:     /* argument type only */
+		case OPTYPE_METHOD_ARGUMENT:    /* argument type only */
+			if (count_remaining) {
+				num_remaining_operands++;
+			}
+
+			num_operands++;
+			break;
+
+		default:
+			if (count_remaining) {
+				num_remaining_operators++;
+			}
+
+			num_operators++;
+			break;
+		}
+
+
+		op = acpi_ps_get_depth_next (start_op, op);
+	}
+
+	acpi_os_printf ("Method contains:     %X AML Opcodes - %X Operators, %X Operands\n",
+			 num_ops, num_operators, num_operands);
+
+	acpi_os_printf ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n",
+			 num_remaining_ops, num_remaining_operators, num_remaining_operands);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_locals
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display all locals for the currently running control method
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_locals (void)
+{
+	u32                     i;
+	ACPI_WALK_STATE         *walk_state;
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	ACPI_NAMESPACE_NODE     *node;
+
+
+	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
+	if (!walk_state) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	obj_desc = walk_state->method_desc;
+	node = walk_state->method_node;
+
+
+	acpi_os_printf ("Local Variables for method [%4.4s]:\n", &node->name);
+
+	for (i = 0; i < MTH_NUM_LOCALS; i++) {
+		obj_desc = walk_state->local_variables[i].object;
+		acpi_os_printf ("Local%d: ", i);
+		acpi_db_display_internal_object (obj_desc, walk_state);
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_arguments
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display all arguments for the currently running control method
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_arguments (void)
+{
+	u32                     i;
+	ACPI_WALK_STATE         *walk_state;
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	u32                     num_args;
+	u32                     concurrency;
+	ACPI_NAMESPACE_NODE     *node;
+
+
+	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
+	if (!walk_state) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	obj_desc = walk_state->method_desc;
+	node = walk_state->method_node;
+
+	num_args = obj_desc->method.param_count;
+	concurrency = obj_desc->method.concurrency;
+
+	acpi_os_printf ("Method [%4.4s] has %X arguments, max concurrency = %X\n", &node->name, num_args, concurrency);
+
+	for (i = 0; i < num_args; i++) {
+		obj_desc = walk_state->arguments[i].object;
+		acpi_os_printf ("Arg%d: ", i);
+		acpi_db_display_internal_object (obj_desc, walk_state);
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_results
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display current contents of a method result stack
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_results (void)
+{
+	u32                     i;
+	ACPI_WALK_STATE         *walk_state;
+	ACPI_OPERAND_OBJECT     *obj_desc;
+	u32                     num_results = 0;
+	ACPI_NAMESPACE_NODE     *node;
+
+
+	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
+	if (!walk_state) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	obj_desc = walk_state->method_desc;
+	node = walk_state->method_node;
+
+	if (walk_state->results) {
+		num_results = walk_state->results->results.num_results;
+	}
+
+	acpi_os_printf ("Method [%4.4s] has %X stacked result objects\n", &node->name, num_results);
+
+	for (i = 0; i < num_results; i++) {
+		obj_desc = walk_state->results->results.obj_desc[i];
+		acpi_os_printf ("Result%d: ", i);
+		acpi_db_display_internal_object (obj_desc, walk_state);
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_calling_tree
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display current calling tree of nested control methods
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_calling_tree (void)
+{
+	u32                     i;
+	ACPI_WALK_STATE         *walk_state;
+	ACPI_NAMESPACE_NODE     *node;
+
+
+	walk_state = acpi_ds_get_current_walk_state (acpi_gbl_current_walk_list);
+	if (!walk_state) {
+		acpi_os_printf ("There is no method currently executing\n");
+		return;
+	}
+
+	node = walk_state->method_node;
+
+	acpi_os_printf ("Current Control Method Call Tree\n");
+
+	for (i = 0; walk_state; i++) {
+		node = walk_state->method_node;
+
+		acpi_os_printf ("  [%4.4s]\n", &node->name);
+
+		walk_state = walk_state->next;
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_result_object
+ *
+ * PARAMETERS:  Obj_desc        - Object to be displayed
+ *              Walk_state      - Current walk state
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display the result of an AML opcode
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_result_object (
+	ACPI_OPERAND_OBJECT     *obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+
+	/* TBD: [Future] We don't always want to display the result.
+	 * For now, only display if single stepping
+	 * however, this output is very useful in other contexts also
+	 */
+
+	if (!acpi_gbl_cm_single_step) {
+		return;
+	}
+
+	acpi_os_printf ("Result_obj: ");
+	acpi_db_display_internal_object (obj_desc, walk_state);
+	acpi_os_printf ("\n");
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_display_argument_object
+ *
+ * PARAMETERS:  Obj_desc        - Object to be displayed
+ *              Walk_state      - Current walk state
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Display the result of an AML opcode
+ *
+ ******************************************************************************/
+
+void
+acpi_db_display_argument_object (
+	ACPI_OPERAND_OBJECT     *obj_desc,
+	ACPI_WALK_STATE         *walk_state)
+{
+
+
+	if (!acpi_gbl_cm_single_step) {
+		return;
+	}
+
+	acpi_os_printf ("Arg_obj: ");
+	acpi_db_display_internal_object (obj_desc, walk_state);
+}
+
+#endif /* ENABLE_DEBUGGER */
+
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbexec.c linux/drivers/acpi/debugger/dbexec.c
--- v2.4.5/linux/drivers/acpi/debugger/dbexec.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/debugger/dbexec.c	Wed Jun 20 17:47:39 2001
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ *
+ * Module Name: dbexec - debugger control method execution
+ *              $Revision: 26 $
+ *
+ ******************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "acparser.h"
+#include "acdispat.h"
+#include "amlcode.h"
+#include "acnamesp.h"
+#include "acparser.h"
+#include "acevents.h"
+#include "acinterp.h"
+#include "acdebug.h"
+#include "actables.h"
+
+#ifdef ENABLE_DEBUGGER
+
+#define _COMPONENT          ACPI_DEBUGGER
+	 MODULE_NAME         ("dbexec")
+
+
+DB_METHOD_INFO              info;
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_execute_method
+ *
+ * PARAMETERS:  Info            - Valid info segment
+ *              Return_obj      - Where to put return object
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute a control method.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_execute_method (
+	DB_METHOD_INFO          *info,
+	ACPI_BUFFER             *return_obj)
+{
+	ACPI_STATUS             status;
+	ACPI_OBJECT_LIST        param_objects;
+	ACPI_OBJECT             params[MTH_NUM_ARGS];
+	u32                     i;
+
+
+	if (output_to_file && !acpi_dbg_level) {
+		acpi_os_printf ("Warning: debug output is not enabled!\n");
+	}
+
+	/* Are there arguments to the method? */
+
+	if (info->args && info->args[0]) {
+		for (i = 0; info->args[i] && i < MTH_NUM_ARGS; i++) {
+			params[i].type              = ACPI_TYPE_INTEGER;
+			params[i].integer.value     = STRTOUL (info->args[i], NULL, 16);
+		}
+
+		param_objects.pointer       = params;
+		param_objects.count         = i;
+	}
+
+	else {
+		/* Setup default parameters */
+
+		params[0].type              = ACPI_TYPE_INTEGER;
+		params[0].integer.value     = 0x01020304;
+
+		params[1].type              = ACPI_TYPE_STRING;
+		params[1].string.length     = 12;
+		params[1].string.pointer    = "AML Debugger";
+
+		param_objects.pointer       = params;
+		param_objects.count         = 2;
+	}
+
+	/* Prepare for a return object of arbitrary size */
+
+	return_obj->pointer          = buffer;
+	return_obj->length           = BUFFER_SIZE;
+
+
+	/* Do the actual method execution */
+
+	status = acpi_evaluate_object (NULL, info->pathname, &param_objects, return_obj);
+
+	acpi_gbl_cm_single_step = FALSE;
+	acpi_gbl_method_executing = FALSE;
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_execute_setup
+ *
+ * PARAMETERS:  Info            - Valid method info
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Setup info segment prior to method execution
+ *
+ ******************************************************************************/
+
+void
+acpi_db_execute_setup (
+	DB_METHOD_INFO          *info)
+{
+
+	/* Catenate the current scope to the supplied name */
+
+	info->pathname[0] = 0;
+	if ((info->name[0] != '\\') &&
+		(info->name[0] != '/')) {
+		STRCAT (info->pathname, scope_buf);
+	}
+
+	STRCAT (info->pathname, info->name);
+	acpi_db_prep_namestring (info->pathname);
+
+	acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT);
+	acpi_os_printf ("Executing %s\n", info->pathname);
+
+	if (info->flags & EX_SINGLE_STEP) {
+		acpi_gbl_cm_single_step = TRUE;
+		acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+	}
+
+	else {
+		/* No single step, allow redirection to a file */
+
+		acpi_db_set_output_destination (DB_REDIRECTABLE_OUTPUT);
+	}
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_execute
+ *
+ * PARAMETERS:  Name                - Name of method to execute
+ *              Args                - Parameters to the method
+ *              Flags               - single step/no single step
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Execute a control method.  Name is relative to the current
+ *              scope.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_execute (
+	NATIVE_CHAR             *name,
+	NATIVE_CHAR             **args,
+	u32                     flags)
+{
+	ACPI_STATUS             status;
+	ACPI_BUFFER             return_obj;
+
+
+	info.name = name;
+	info.args = args;
+	info.flags = flags;
+
+	acpi_db_execute_setup (&info);
+	status = acpi_db_execute_method (&info, &return_obj);
+
+
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Execution of %s failed with status %s\n",
+			info.pathname, acpi_ut_format_exception (status));
+	}
+
+	else {
+		/* Display a return object, if any */
+
+		if (return_obj.length) {
+			acpi_os_printf ("Execution of %s returned object %p Buflen %X\n",
+				info.pathname, return_obj.pointer, return_obj.length);
+			acpi_db_dump_object (return_obj.pointer, 1);
+		}
+	}
+
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_method_thread
+ *
+ * PARAMETERS:  Context             - Execution info segment
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Debugger execute thread.  Waits for a command line, then
+ *              simply dispatches it.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_method_thread (
+	void                    *context)
+{
+	ACPI_STATUS             status;
+	DB_METHOD_INFO          *info = context;
+	u32                     i;
+	ACPI_BUFFER             return_obj;
+
+
+	for (i = 0; i < info->num_loops; i++) {
+		status = acpi_db_execute_method (info, &return_obj);
+		if (ACPI_SUCCESS (status)) {
+			if (return_obj.length) {
+				acpi_os_printf ("Execution of %s returned object %p Buflen %X\n",
+					info->pathname, return_obj.pointer, return_obj.length);
+				acpi_db_dump_object (return_obj.pointer, 1);
+			}
+		}
+	}
+
+
+	/* Signal our completion */
+
+	acpi_os_signal_semaphore (info->thread_gate, 1);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_create_execution_threads
+ *
+ * PARAMETERS:  Num_threads_arg         - Number of threads to create
+ *              Num_loops_arg           - Loop count for the thread(s)
+ *              Method_name_arg         - Control method to execute
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Create threads to execute method(s)
+ *
+ ******************************************************************************/
+
+void
+acpi_db_create_execution_threads (
+	NATIVE_CHAR             *num_threads_arg,
+	NATIVE_CHAR             *num_loops_arg,
+	NATIVE_CHAR             *method_name_arg)
+{
+	ACPI_STATUS             status;
+	u32                     num_threads;
+	u32                     num_loops;
+	u32                     i;
+	ACPI_HANDLE             thread_gate;
+
+
+	/* Get the arguments */
+
+	num_threads = STRTOUL (num_threads_arg, NULL, 0);
+	num_loops = STRTOUL (num_loops_arg, NULL, 0);
+
+	if (!num_threads || !num_loops) {
+		acpi_os_printf ("Bad argument: Threads %X, Loops %X\n", num_threads, num_loops);
+		return;
+	}
+
+
+	/* Create the synchronization semaphore */
+
+	status = acpi_os_create_semaphore (1, 0, &thread_gate);
+	if (ACPI_FAILURE (status)) {
+		acpi_os_printf ("Could not create semaphore, %s\n", acpi_ut_format_exception (status));
+		return;
+	}
+
+	/* Setup the context to be passed to each thread */
+
+	info.name = method_name_arg;
+	info.args = NULL;
+	info.flags = 0;
+	info.num_loops = num_loops;
+	info.thread_gate = thread_gate;
+
+	acpi_db_execute_setup (&info);
+
+
+	/* Create the threads */
+
+	acpi_os_printf ("Creating %X threads to execute %X times each\n", num_threads, num_loops);
+
+	for (i = 0; i < (num_threads); i++) {
+		acpi_os_queue_for_execution (OSD_PRIORITY_MED, acpi_db_method_thread, &info);
+	}
+
+
+	/* Wait for all threads to complete */
+
+	i = num_threads;
+	while (i)   /* Brain damage for OSD implementations that only support wait of 1 unit */ {
+		status = acpi_os_wait_semaphore (thread_gate, 1, WAIT_FOREVER);
+		i--;
+	}
+
+	/* Cleanup and exit */
+
+	acpi_os_delete_semaphore (thread_gate);
+
+	acpi_db_set_output_destination (DB_DUPLICATE_OUTPUT);
+	acpi_os_printf ("All threads (%X) have completed\n", num_threads);
+	acpi_db_set_output_destination (DB_CONSOLE_OUTPUT);
+}
+
+
+#endif /* ENABLE_DEBUGGER */
+
+
diff -u --recursive --new-file v2.4.5/linux/drivers/acpi/debugger/dbfileio.c linux/drivers/acpi/debugger/dbfileio.c
--- v2.4.5/linux/drivers/acpi/debugger/dbfileio.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acpi/debugger/dbfileio.c	Wed Jun 20 17:47:39 2001
@@ -0,0 +1,378 @@
+/*******************************************************************************
+ *
+ * Module Name: dbfileio - Debugger file I/O commands.  These can't usually
+ *              be used when running the debugger in Ring 0 (Kernel mode)
+ *              $Revision: 41 $
+ *
+ ******************************************************************************/
+
+/*
+ *  Copyright (C) 2000, 2001 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "acdebug.h"
+#include "acnamesp.h"
+#include "acparser.h"
+#include "acevents.h"
+#include "actables.h"
+
+#ifdef ENABLE_DEBUGGER
+
+#define _COMPONENT          ACPI_DEBUGGER
+	 MODULE_NAME         ("dbfileio")
+
+
+ACPI_PARSE_OBJECT           *root;
+
+#ifdef ACPI_APPLICATION
+#include <stdio.h>
+FILE                        *debug_file = NULL;
+#endif
+
+
+/*
+ * NOTE: this is here for lack of a better place.  It is used in all
+ *  flavors of the debugger, need LCD file
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_match_argument
+ *
+ * PARAMETERS:  User_argument           - User command line
+ *              Arguments               - Array of commands to match against
+ *
+ * RETURN:      Index into command array or ACPI_TYPE_NOT_FOUND if not found
+ *
+ * DESCRIPTION: Search command array for a command match
+ *
+ ******************************************************************************/
+
+ACPI_OBJECT_TYPE8
+acpi_db_match_argument (
+	NATIVE_CHAR             *user_argument,
+	ARGUMENT_INFO           *arguments)
+{
+	u32                     i;
+
+
+	if (!user_argument || user_argument[0] == 0) {
+		return (ACPI_TYPE_NOT_FOUND);
+	}
+
+	for (i = 0; arguments[i].name; i++) {
+		if (STRSTR (arguments[i].name, user_argument) == arguments[i].name) {
+			return ((ACPI_OBJECT_TYPE8) i);
+		}
+	}
+
+	/* Argument not recognized */
+
+	return (ACPI_TYPE_NOT_FOUND);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_close_debug_file
+ *
+ * PARAMETERS:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: If open, close the current debug output file
+ *
+ ******************************************************************************/
+
+void
+acpi_db_close_debug_file (
+	void)
+{
+
+#ifdef ACPI_APPLICATION
+
+	if (debug_file) {
+	   fclose (debug_file);
+	   debug_file = NULL;
+	   output_to_file = FALSE;
+	   acpi_os_printf ("Debug output file %s closed\n", debug_filename);
+	}
+#endif
+
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_open_debug_file
+ *
+ * PARAMETERS:  Name                - Filename to open
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Open a file where debug output will be directed.
+ *
+ ******************************************************************************/
+
+void
+acpi_db_open_debug_file (
+	NATIVE_CHAR             *name)
+{
+
+#ifdef ACPI_APPLICATION
+
+	acpi_db_close_debug_file ();
+	debug_file = fopen (name, "w+");
+	if (debug_file) {
+		acpi_os_printf ("Debug output file %s opened\n", name);
+		STRCPY (debug_filename, name);
+		output_to_file = TRUE;
+	}
+	else {
+		acpi_os_printf ("Could not open debug file %s\n", name);
+	}
+
+#endif
+}
+
+
+#ifdef ACPI_APPLICATION
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_db_load_table
+ *
+ * PARAMETERS:  fp              - File that contains table
+ *              Table_ptr       - Return value, buffer with table
+ *              Table_lenght    - Return value, length of table
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Load the DSDT from the file pointer
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_db_load_table(
+	FILE                    *fp,
+	ACPI_TABLE_HEADER       **table_ptr,
+	u32                     *table_length)
+{
+	ACPI_TABLE_HEADER       table_header;
+	u8                      *aml_ptr;
+	u32                     aml_length;
+	u32                     actual;
+	ACPI_STATUS             status;
+
+
+	/* Read the table header */
+
+	if (fread (&table_header, 1, sizeof (table_header), fp) != sizeof (ACPI_TABLE_HEADER)) {
+		acpi_os_printf ("Couldn't read the table header\n");
+		return (AE_BAD_SIGNATURE);
+	}
+
+
+	/* Validate the table header/length */
+
+	status = acpi_tb_validate_table_header (&table_header);
+	if ((ACPI_FAILURE (status)) ||
+		(table_header.length > 524288)) /* 1/2 Mbyte should be enough */ {
+		acpi_os_printf ("Table header is invalid!\n");
+		return (AE_ERROR);
+	}
+
+
+	/* We only support a limited number of table types */
+
+	if (STRNCMP ((char *) table_header.signature, DSDT_SIG, 4) &&
+		STRNCMP ((char *) table_header.signature, PSDT_SIG, 4) &&
+		STRNCMP ((char *) table_header.signature, SSDT_SIG, 4)) {
+		acpi_os_printf ("Table signature is invalid\n");
+		return (AE_ERROR);
+	}
+
+	/* Allocate a buffer for the table */
+
+	*table_length = table_header.length;
+	*table_ptr = (ACPI_TABLE_HEADER *) acpi_ut_allocate ((size_t) *table_length);
+	if (!*table_ptr) {
+		acpi_os_printf ("Could not allocate memory for the table (size=%X)\n", table_header.length);
+		return (AE_NO_MEMORY);
+	}
+
+
+	aml_ptr     = (u8 *) *table_ptr + sizeof (table_header);
+	aml_length  = *table_length - sizeof (table_header);
+
+	/* Copy the header to the buffer */
+
+	MEMCPY (*table_ptr, &table_header, sizeof (table_header));
+
+	/* Get the rest of the table */
+
+	actual = fread (aml_ptr, 1, (size_t) aml_length, fp);
+	if (actual == aml_length) {
+		return (AE_OK);
+	}
+
+	if (actual > 0) {
+		acpi_os_printf ("Warning - reading table, asked for %X got %X\n", aml_length, actual);
+	   return (AE_OK);
+	}
+
+
+	acpi_os_printf ("Error - could not read the table file\n");
+	acpi_ut_free (*table_ptr);
+	*table_ptr = NULL;
+	*table_length = 0;
+
+	return (AE_ERROR);
+}
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Ae_local_load_table
+ *
+ * PARAMETERS:  Table_ptr       - pointer to a buffer containing the entire
+ *                                table to be loaded
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This function is called to load a table from the caller's
+ *              buffer.  The buffer must contain an entire ACPI Table including
+ *              a valid header.  The header fields will be verified, and if it
+ *              is determined that the table is invalid, the call will fail.
+ *
+ *              If the call fails an appropriate status will be returned.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+ae_local_load_table (
+	ACPI_TABLE_HEADER       *table_ptr)
+{
+	ACPI_STATUS             status;
+	ACPI_TABLE_DESC         table_info;
+
+
+	if (!table_ptr) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	/* Install the new table into the localred interrupts 